Code cleanup in ZygoteInit.

This commit mostly re-flows the code in ZygoteInit.java to conform to
the Frameworks style guide.

Topic: zygote-prefork
Test: make & flash & launch apps
Bug: 68253328
Change-Id: I0d348caa1d9ca2a4c1e32430e0eebdd91672e473
This commit is contained in:
Chris Wailes
2019-01-11 14:30:43 -08:00
parent efce929711
commit 143f7cc78e

View File

@@ -70,9 +70,8 @@ import java.security.Security;
/** /**
* Startup class for the zygote process. * Startup class for the zygote process.
* *
* Pre-initializes some classes, and then waits for commands on a UNIX domain * Pre-initializes some classes, and then waits for commands on a UNIX domain socket. Based on these
* socket. Based on these commands, forks off child processes that inherit * commands, forks off child processes that inherit the initial state of the VM.
* the initial state of the VM.
* *
* Please see {@link ZygoteConnection.Arguments} for documentation on the * Please see {@link ZygoteConnection.Arguments} for documentation on the
* client protocol. * client protocol.
@@ -80,6 +79,8 @@ import java.security.Security;
* @hide * @hide
*/ */
public class ZygoteInit { public class ZygoteInit {
// TODO (chriswailes): Change this so it is set with Zygote or ZygoteSecondary as appropriate
private static final String TAG = "Zygote"; private static final String TAG = "Zygote";
private static final String PROPERTY_DISABLE_OPENGL_PRELOADING = "ro.zygote.disable_gl_preload"; private static final String PROPERTY_DISABLE_OPENGL_PRELOADING = "ro.zygote.disable_gl_preload";
@@ -88,11 +89,15 @@ public class ZygoteInit {
private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020; private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020;
private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030; private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030;
/** when preloading, GC after allocating this many bytes */ /**
* when preloading, GC after allocating this many bytes
*/
private static final int PRELOAD_GC_THRESHOLD = 50000; private static final int PRELOAD_GC_THRESHOLD = 50000;
private static final String ABI_LIST_ARG = "--abi-list="; private static final String ABI_LIST_ARG = "--abi-list=";
// TODO (chriswailes): Re-name this --zygote-socket-name= and then add a
// --blastula-socket-name parameter.
private static final String SOCKET_NAME_ARG = "--socket-name="; private static final String SOCKET_NAME_ARG = "--socket-name=";
/** /**
@@ -105,7 +110,9 @@ public class ZygoteInit {
*/ */
private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes"; private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
/** Controls whether we should preload resources during zygote init. */ /**
* Controls whether we should preload resources during zygote init.
*/
public static final boolean PRELOAD_RESOURCES = true; public static final boolean PRELOAD_RESOURCES = true;
private static final int UNPRIVILEGED_UID = 9999; private static final int UNPRIVILEGED_UID = 9999;
@@ -172,6 +179,7 @@ public class ZygoteInit {
} }
native private static void nativePreloadAppProcessHALs(); native private static void nativePreloadAppProcessHALs();
native private static void nativePreloadOpenGL(); native private static void nativePreloadOpenGL();
private static void preloadOpenGL() { private static void preloadOpenGL() {
@@ -190,8 +198,8 @@ public class ZygoteInit {
/** /**
* Register AndroidKeyStoreProvider and warm up the providers that are already registered. * Register AndroidKeyStoreProvider and warm up the providers that are already registered.
* *
* By doing it here we avoid that each app does it when requesting a service from the * By doing it here we avoid that each app does it when requesting a service from the provider
* provider for the first time. * for the first time.
*/ */
private static void warmUpJcaProviders() { private static void warmUpJcaProviders() {
long startTime = SystemClock.uptimeMillis(); long startTime = SystemClock.uptimeMillis();
@@ -217,11 +225,10 @@ public class ZygoteInit {
} }
/** /**
* Performs Zygote process initialization. Loads and initializes * Performs Zygote process initialization. Loads and initializes commonly used classes.
* commonly used classes.
* *
* Most classes only cause a few hundred bytes to be allocated, but * Most classes only cause a few hundred bytes to be allocated, but a few will allocate a dozen
* a few will allocate a dozen Kbytes (in one case, 500+K). * Kbytes (in one case, 500+K).
*/ */
private static void preloadClasses() { private static void preloadClasses() {
final VMRuntime runtime = VMRuntime.getRuntime(); final VMRuntime runtime = VMRuntime.getRuntime();
@@ -262,8 +269,8 @@ public class ZygoteInit {
runtime.setTargetHeapUtilization(0.8f); runtime.setTargetHeapUtilization(0.8f);
try { try {
BufferedReader br BufferedReader br =
= new BufferedReader(new InputStreamReader(is), 256); new BufferedReader(new InputStreamReader(is), 256);
int count = 0; int count = 0;
String line; String line;
@@ -304,7 +311,7 @@ public class ZygoteInit {
} }
Log.i(TAG, "...preloaded " + count + " classes in " Log.i(TAG, "...preloaded " + count + " classes in "
+ (SystemClock.uptimeMillis()-startTime) + "ms."); + (SystemClock.uptimeMillis() - startTime) + "ms.");
} catch (IOException e) { } catch (IOException e) {
Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e); Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
} finally { } finally {
@@ -330,11 +337,10 @@ public class ZygoteInit {
} }
/** /**
* Load in commonly used resources, so they can be shared across * Load in commonly used resources, so they can be shared across processes.
* processes.
* *
* These tend to be a few Kbytes, but are frequently in the 20-40K * These tend to be a few Kbytes, but are frequently in the 20-40K range, and occasionally even
* range, and occasionally even larger. * larger.
*/ */
private static void preloadResources() { private static void preloadResources() {
final VMRuntime runtime = VMRuntime.getRuntime(); final VMRuntime runtime = VMRuntime.getRuntime();
@@ -351,7 +357,7 @@ public class ZygoteInit {
int N = preloadDrawables(ar); int N = preloadDrawables(ar);
ar.recycle(); ar.recycle();
Log.i(TAG, "...preloaded " + N + " resources in " Log.i(TAG, "...preloaded " + N + " resources in "
+ (SystemClock.uptimeMillis()-startTime) + "ms."); + (SystemClock.uptimeMillis() - startTime) + "ms.");
startTime = SystemClock.uptimeMillis(); startTime = SystemClock.uptimeMillis();
ar = mResources.obtainTypedArray( ar = mResources.obtainTypedArray(
@@ -359,7 +365,7 @@ public class ZygoteInit {
N = preloadColorStateLists(ar); N = preloadColorStateLists(ar);
ar.recycle(); ar.recycle();
Log.i(TAG, "...preloaded " + N + " resources in " Log.i(TAG, "...preloaded " + N + " resources in "
+ (SystemClock.uptimeMillis()-startTime) + "ms."); + (SystemClock.uptimeMillis() - startTime) + "ms.");
if (mResources.getBoolean( if (mResources.getBoolean(
com.android.internal.R.bool.config_freeformWindowManagement)) { com.android.internal.R.bool.config_freeformWindowManagement)) {
@@ -380,7 +386,7 @@ public class ZygoteInit {
private static int preloadColorStateLists(TypedArray ar) { private static int preloadColorStateLists(TypedArray ar) {
int N = ar.length(); int N = ar.length();
for (int i=0; i<N; i++) { for (int i = 0; i < N; i++) {
int id = ar.getResourceId(i, 0); int id = ar.getResourceId(i, 0);
if (false) { if (false) {
Log.v(TAG, "Preloading resource #" + Integer.toHexString(id)); Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
@@ -389,8 +395,8 @@ public class ZygoteInit {
if (mResources.getColorStateList(id, null) == null) { if (mResources.getColorStateList(id, null) == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Unable to find preloaded color resource #0x" "Unable to find preloaded color resource #0x"
+ Integer.toHexString(id) + Integer.toHexString(id)
+ " (" + ar.getString(i) + ")"); + " (" + ar.getString(i) + ")");
} }
} }
} }
@@ -400,7 +406,7 @@ public class ZygoteInit {
private static int preloadDrawables(TypedArray ar) { private static int preloadDrawables(TypedArray ar) {
int N = ar.length(); int N = ar.length();
for (int i=0; i<N; i++) { for (int i = 0; i < N; i++) {
int id = ar.getResourceId(i, 0); int id = ar.getResourceId(i, 0);
if (false) { if (false) {
Log.v(TAG, "Preloading resource #" + Integer.toHexString(id)); Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
@@ -409,8 +415,8 @@ public class ZygoteInit {
if (mResources.getDrawable(id, null) == null) { if (mResources.getDrawable(id, null) == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Unable to find preloaded drawable resource #0x" "Unable to find preloaded drawable resource #0x"
+ Integer.toHexString(id) + Integer.toHexString(id)
+ " (" + ar.getString(i) + ")"); + " (" + ar.getString(i) + ")");
} }
} }
} }
@@ -418,9 +424,8 @@ public class ZygoteInit {
} }
/** /**
* Runs several special GCs to try to clean up a few generations of * Runs several special GCs to try to clean up a few generations of softly- and final-reachable
* softly- and final-reachable objects, along with any other garbage. * objects, along with any other garbage. This is only useful just before a fork().
* This is only useful just before a fork().
*/ */
private static void gcAndFinalize() { private static void gcAndFinalize() {
ZygoteHooks.gcAndFinalize(); ZygoteHooks.gcAndFinalize();
@@ -482,16 +487,17 @@ public class ZygoteInit {
/* /*
* Pass the remaining arguments to SystemServer. * Pass the remaining arguments to SystemServer.
*/ */
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, cl);
} }
/* should never reach here */ /* should never reach here */
} }
/** /**
* Note that preparing the profiles for system server does not require special * Note that preparing the profiles for system server does not require special selinux
* selinux permissions. From the installer perspective the system server is a regular package * permissions. From the installer perspective the system server is a regular package which can
* which can capture profile information. * capture profile information.
*/ */
private static void prepareSystemServerProfile(String systemServerClasspath) private static void prepareSystemServerProfile(String systemServerClasspath)
throws RemoteException { throws RemoteException {
@@ -543,8 +549,8 @@ public class ZygoteInit {
} }
/** /**
* Performs dex-opt on the elements of {@code classPath}, if needed. We * Performs dex-opt on the elements of {@code classPath}, if needed. We choose the instruction
* choose the instruction set of the current runtime. * set of the current runtime.
*/ */
private static void performSystemServerDexOpt(String classPath) { private static void performSystemServerDexOpt(String classPath) {
final String[] classPathElements = classPath.split(":"); final String[] classPathElements = classPath.split(":");
@@ -562,8 +568,9 @@ public class ZygoteInit {
int dexoptNeeded; int dexoptNeeded;
try { try {
dexoptNeeded = DexFile.getDexOptNeeded( dexoptNeeded = DexFile.getDexOptNeeded(
classPathElement, instructionSet, systemServerFilter, classPathElement, instructionSet, systemServerFilter,
null /* classLoaderContext */, false /* newProfile */, false /* downgrade */); null /* classLoaderContext */, false /* newProfile */,
false /* downgrade */);
} catch (FileNotFoundException ignored) { } catch (FileNotFoundException ignored) {
// Do not add to the classpath. // Do not add to the classpath.
Log.w(TAG, "Missing classpath element for system server: " + classPathElement); Log.w(TAG, "Missing classpath element for system server: " + classPathElement);
@@ -606,8 +613,8 @@ public class ZygoteInit {
} }
/** /**
* Encodes the system server class loader context in a format that is accepted by dexopt. * Encodes the system server class loader context in a format that is accepted by dexopt. This
* This assumes the system server is always loaded with a {@link dalvik.system.PathClassLoader}. * assumes the system server is always loaded with a {@link dalvik.system.PathClassLoader}.
* *
* Note that ideally we would use the {@code DexoptUtils} to compute this. However we have no * Note that ideally we would use the {@code DexoptUtils} to compute this. However we have no
* dependency here on the server so we hard code the logic again. * dependency here on the server so we hard code the logic again.
@@ -618,10 +625,11 @@ public class ZygoteInit {
/** /**
* Encodes the class path in a format accepted by dexopt. * Encodes the class path in a format accepted by dexopt.
* @param classPath the old class path (may be empty). *
* @param newElement the new class path elements * @param classPath The old class path (may be empty).
* @return the class path encoding resulted from appending {@code newElement} to * @param newElement The new class path elements
* {@code classPath}. * @return The class path encoding resulted from appending {@code newElement} to {@code
* classPath}.
*/ */
private static String encodeSystemServerClassPath(String classPath, String newElement) { private static String encodeSystemServerClassPath(String classPath, String newElement) {
return (classPath == null || classPath.isEmpty()) return (classPath == null || classPath.isEmpty())
@@ -632,25 +640,25 @@ public class ZygoteInit {
/** /**
* Prepare the arguments and forks for the system server process. * Prepare the arguments and forks for the system server process.
* *
* Returns an {@code Runnable} that provides an entrypoint into system_server code in the * @return A {@code Runnable} that provides an entrypoint into system_server code in the child
* child process, and {@code null} in the parent. * process; {@code null} in the parent.
*/ */
private static Runnable forkSystemServer(String abiList, String socketName, private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) { ZygoteServer zygoteServer) {
long capabilities = posixCapabilitiesAsBits( long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_IPC_LOCK, OsConstants.CAP_IPC_LOCK,
OsConstants.CAP_KILL, OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN, OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE, OsConstants.CAP_NET_BIND_SERVICE,
OsConstants.CAP_NET_BROADCAST, OsConstants.CAP_NET_BROADCAST,
OsConstants.CAP_NET_RAW, OsConstants.CAP_NET_RAW,
OsConstants.CAP_SYS_MODULE, OsConstants.CAP_SYS_MODULE,
OsConstants.CAP_SYS_NICE, OsConstants.CAP_SYS_NICE,
OsConstants.CAP_SYS_PTRACE, OsConstants.CAP_SYS_PTRACE,
OsConstants.CAP_SYS_TIME, OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG, OsConstants.CAP_SYS_TTY_CONFIG,
OsConstants.CAP_WAKE_ALARM, OsConstants.CAP_WAKE_ALARM,
OsConstants.CAP_BLOCK_SUSPEND OsConstants.CAP_BLOCK_SUSPEND
); );
/* Containers run without some capabilities, so drop any caps that are not available. */ /* Containers run without some capabilities, so drop any caps that are not available. */
StructCapUserHeader header = new StructCapUserHeader( StructCapUserHeader header = new StructCapUserHeader(
@@ -665,14 +673,15 @@ public class ZygoteInit {
/* Hardcoded command line to start the system server */ /* Hardcoded command line to start the system server */
String args[] = { String args[] = {
"--setuid=1000", "--setuid=1000",
"--setgid=1000", "--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1024,1032,1065,3001,3002,3003,3006,3007,3009,3010", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
"--capabilities=" + capabilities + "," + capabilities, + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
"--nice-name=system_server", "--capabilities=" + capabilities + "," + capabilities,
"--runtime-args", "--nice-name=system_server",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT, "--runtime-args",
"com.android.server.SystemServer", "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
}; };
ZygoteConnection.Arguments parsedArgs = null; ZygoteConnection.Arguments parsedArgs = null;
@@ -784,10 +793,10 @@ public class ZygoteInit {
if (!enableLazyPreload) { if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload"); bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis()); SystemClock.uptimeMillis());
preload(bootTimingsTraceLog); preload(bootTimingsTraceLog);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis()); SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else { } else {
Zygote.resetNicePriority(); Zygote.resetNicePriority();
@@ -843,9 +852,8 @@ public class ZygoteInit {
/** /**
* Return {@code true} if this device configuration has another zygote. * Return {@code true} if this device configuration has another zygote.
* *
* We determine this by comparing the device ABI list with this zygotes * We determine this by comparing the device ABI list with this zygotes list. If this zygote
* list. If this zygote supports all ABIs this device supports, there won't * supports all ABIs this device supports, there won't be another zygote.
* be another zygote.
*/ */
private static boolean hasSecondZygote(String abiList) { private static boolean hasSecondZygote(String abiList) {
return !SystemProperties.get("ro.product.cpu.abilist").equals(abiList); return !SystemProperties.get("ro.product.cpu.abilist").equals(abiList);
@@ -868,9 +876,8 @@ public class ZygoteInit {
} }
/** /**
* The main function called when started through the zygote process. This * The main function called when started through the zygote process. This could be unified with
* could be unified with main(), if the native code in nativeFinishInit() * main(), if the native code in nativeFinishInit() were rationalized with Zygote startup.<p>
* were rationalized with Zygote startup.<p>
* *
* Current recognized args: * Current recognized args:
* <ul> * <ul>
@@ -880,7 +887,8 @@ public class ZygoteInit {
* @param targetSdkVersion target SDK version * @param targetSdkVersion target SDK version
* @param argv arg strings * @param argv arg strings
*/ */
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) { public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
if (RuntimeInit.DEBUG) { if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote"); Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
} }
@@ -894,9 +902,9 @@ public class ZygoteInit {
} }
/** /**
* The main function called when starting a child zygote process. This is used as an * The main function called when starting a child zygote process. This is used as an alternative
* alternative to zygoteInit(), which skips calling into initialization routines that * to zygoteInit(), which skips calling into initialization routines that start the Binder
* start the Binder threadpool. * threadpool.
*/ */
static final Runnable childZygoteInit( static final Runnable childZygoteInit(
int targetSdkVersion, String[] argv, ClassLoader classLoader) { int targetSdkVersion, String[] argv, ClassLoader classLoader) {