The Zygote is a process in the Android operating system that acts as the root of all system and app processes with the same application binary interface (ABI).
On modern devices, such as Pixel 7 and later, there is a 64-bit Zygote process. In addition, there is the WebView Zygote for the primary ABI, which is a specialized Zygote that contains libraries and resources specific to processes that run WebViews.
Here are the tasks the Zygote performs:
The init daemon spawns the Zygote process when the Android OS is initialized. On some dual architecture systems, two Zygote processes (a 64-bit and 32-bit) are spawned. This page covers only single architecture systems.
The Zygote can immediately spawn processes called unspecialized app processes (USAP) or wait to spawn processes as needed by applications. The former option must be enabled through a system property or Android debug bridge command. For more information on configuring the Zygote to spawn processes immediately, see Enable unspecialized app processes pool .
If the USAP pool is enabled on your device:
- The system server uses a Unix domain socket to connect to an available USAP from a pool. The system server requests that the USAP is preconfigured for application use by changing the process's ID (PID), cgroup, and other information.
- When the USAP is done preconfiguring, it replies to the system server with the PID.
- When an application occupies one of these USAPs, the USAP is no longer part of the pool. When the pool reaches one or fewer USAPs in the pool, the Zygote replenishes the pool with new USAPs.
If your Zygote spawns processes using lazy evaluation:
- The system server receives a command that an app needs a process.
- The system server uses a Unix domain socket to send a command to the appropriate Zygote.
- The Zygote forks the process and changes the PID, cgroup, and other information.
- When the process is complete, it sends the PID back to the Zygote which then passes it back to the system server.
Enable USAP pool
To enable the use of USAP pool, do one of the following:
Set the
dalvik.vm.usap_pool_enabled
system property totrue
in/build/make/target/product/runtime_libart.mk
.Run the following command:
adb shell am broadcast -a \"com.google.android.gms.phenotype.FLAG_OVERRIDE\" --es package \"com.google.android.platform.runtime_native\" --es user \"\*\" --esa flags \"usap_pool_enabled\" --esa values \"true\" --esa types \"string\" com.google.android.gms
When this feature is enabled, each Zygote maintains a pool of forked processes that perform the application-independent portions of the application startup process.
Troubleshoot Zygote issues
This section contains solutions to Zygote-related issues.
The Zygote is crashing
If your device doesn't reboot properly and your logs or crash reports show issues with the Zygote, it's likely because you made a recent change that causes initd or the system server to crash. Fixing your code should fix the problem.
SELinux denials or IO Failures
The Zygote is particular about file descriptor hygiene across process
boundaries. When file descriptors are present at fork time but not in an
allowlist, we use a dup
system call to /dev/null
to prevent cached file
descriptors from being used unintentionally to access newly opened files.
If you're making framework changes that include trying to load resources into the Zygote, and you're receiving SELinux denials or IO failures:
For unnamed file descriptors, include the file descriptors in the
fds_to_ignore
vector whenRestat
is called.For named file descriptors:
- Edit
WORKING_DIRECTORY/frameworks/base/core/jni/fd_utils.cpp
. - Add the path to the allowlist for open files.
- Edit