About the Zygote processes

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:

  1. 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.

  2. 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:

      1. 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.
      2. When the USAP is done preconfiguring, it replies to the system server with the PID.
      3. 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:

      1. The system server receives a command that an app needs a process.
      2. The system server uses a Unix domain socket to send a command to the appropriate Zygote.
      3. The Zygote forks the process and changes the PID, cgroup, and other information.
      4. 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 to true 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 when Restat is called.

  • For named file descriptors:

    1. Edit WORKING_DIRECTORY/frameworks/base/core/jni/fd_utils.cpp.
    2. Add the path to the allowlist for open files.