• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.os;
18 
19 import static android.system.OsConstants.S_IRWXG;
20 import static android.system.OsConstants.S_IRWXO;
21 
22 import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SECONDARY_ZYGOTE_INIT_START;
23 import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__ZYGOTE_INIT_START;
24 
25 import android.app.ApplicationLoaders;
26 import android.compat.annotation.UnsupportedAppUsage;
27 import android.content.pm.SharedLibraryInfo;
28 import android.content.res.Resources;
29 import android.content.res.TypedArray;
30 import android.os.Build;
31 import android.os.Environment;
32 import android.os.IInstalld;
33 import android.os.Process;
34 import android.os.RemoteException;
35 import android.os.ServiceManager;
36 import android.os.SystemClock;
37 import android.os.SystemProperties;
38 import android.os.Trace;
39 import android.os.UserHandle;
40 import android.os.ZygoteProcess;
41 import android.provider.DeviceConfig;
42 import android.security.keystore2.AndroidKeyStoreProvider;
43 import android.system.ErrnoException;
44 import android.system.Os;
45 import android.system.OsConstants;
46 import android.system.StructCapUserData;
47 import android.system.StructCapUserHeader;
48 import android.text.Hyphenator;
49 import android.text.TextUtils;
50 import android.util.EventLog;
51 import android.util.Log;
52 import android.util.Slog;
53 import android.util.TimingsTraceLog;
54 import android.view.WindowManager;
55 import android.webkit.WebViewFactory;
56 import android.widget.TextView;
57 
58 import com.android.internal.util.FrameworkStatsLog;
59 import com.android.internal.util.Preconditions;
60 
61 import dalvik.system.VMRuntime;
62 import dalvik.system.ZygoteHooks;
63 
64 import libcore.io.IoUtils;
65 
66 import java.io.BufferedReader;
67 import java.io.EOFException;
68 import java.io.File;
69 import java.io.FileInputStream;
70 import java.io.FileNotFoundException;
71 import java.io.IOException;
72 import java.io.InputStream;
73 import java.io.InputStreamReader;
74 import java.security.Provider;
75 import java.security.Security;
76 import java.util.ArrayList;
77 import java.util.List;
78 
79 /**
80  * Startup class for the zygote process.
81  *
82  * Pre-initializes some classes, and then waits for commands on a UNIX domain socket. Based on these
83  * commands, forks off child processes that inherit the initial state of the VM.
84  *
85  * Please see {@link ZygoteArguments} for documentation on the client protocol.
86  *
87  * @hide
88  */
89 public class ZygoteInit {
90 
91     private static final String TAG = "Zygote";
92 
93     private static final boolean LOGGING_DEBUG = Log.isLoggable(TAG, Log.DEBUG);
94 
95     private static final String PROPERTY_DISABLE_GRAPHICS_DRIVER_PRELOADING =
96             "ro.zygote.disable_gl_preload";
97 
98     private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020;
99     private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030;
100 
101     private static final String ABI_LIST_ARG = "--abi-list=";
102 
103     // TODO (chriswailes): Re-name this --zygote-socket-name= and then add a
104     // --usap-socket-name parameter.
105     private static final String SOCKET_NAME_ARG = "--socket-name=";
106 
107     /**
108      * Used to pre-load resources.
109      */
110     @UnsupportedAppUsage
111     private static Resources mResources;
112 
113     /**
114      * The path of a file that contains classes to preload.
115      */
116     private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
117 
118     /**
119      * Controls whether we should preload resources during zygote init.
120      */
121     private static final boolean PRELOAD_RESOURCES = true;
122 
123     private static final int UNPRIVILEGED_UID = 9999;
124     private static final int UNPRIVILEGED_GID = 9999;
125 
126     private static final int ROOT_UID = 0;
127     private static final int ROOT_GID = 0;
128 
129     private static boolean sPreloadComplete;
130 
131     /**
132      * Cached classloader to use for the system server. Will only be populated in the system
133      * server process.
134      */
135     private static ClassLoader sCachedSystemServerClassLoader = null;
136 
preload(TimingsTraceLog bootTimingsTraceLog)137     static void preload(TimingsTraceLog bootTimingsTraceLog) {
138         Log.d(TAG, "begin preload");
139         bootTimingsTraceLog.traceBegin("BeginPreload");
140         beginPreload();
141         bootTimingsTraceLog.traceEnd(); // BeginPreload
142         bootTimingsTraceLog.traceBegin("PreloadClasses");
143         preloadClasses();
144         bootTimingsTraceLog.traceEnd(); // PreloadClasses
145         bootTimingsTraceLog.traceBegin("CacheNonBootClasspathClassLoaders");
146         cacheNonBootClasspathClassLoaders();
147         bootTimingsTraceLog.traceEnd(); // CacheNonBootClasspathClassLoaders
148         bootTimingsTraceLog.traceBegin("PreloadResources");
149         preloadResources();
150         bootTimingsTraceLog.traceEnd(); // PreloadResources
151         Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
152         nativePreloadAppProcessHALs();
153         Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
154         Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadGraphicsDriver");
155         maybePreloadGraphicsDriver();
156         Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
157         preloadSharedLibraries();
158         preloadTextResources();
159         // Ask the WebViewFactory to do any initialization that must run in the zygote process,
160         // for memory sharing purposes.
161         WebViewFactory.prepareWebViewInZygote();
162         endPreload();
163         warmUpJcaProviders();
164         Log.d(TAG, "end preload");
165 
166         sPreloadComplete = true;
167     }
168 
lazyPreload()169     static void lazyPreload() {
170         Preconditions.checkState(!sPreloadComplete);
171         Log.i(TAG, "Lazily preloading resources.");
172 
173         preload(new TimingsTraceLog("ZygoteInitTiming_lazy", Trace.TRACE_TAG_DALVIK));
174     }
175 
beginPreload()176     private static void beginPreload() {
177         Log.i(TAG, "Calling ZygoteHooks.beginPreload()");
178 
179         ZygoteHooks.onBeginPreload();
180     }
181 
endPreload()182     private static void endPreload() {
183         ZygoteHooks.onEndPreload();
184 
185         Log.i(TAG, "Called ZygoteHooks.endPreload()");
186     }
187 
preloadSharedLibraries()188     private static void preloadSharedLibraries() {
189         Log.i(TAG, "Preloading shared libraries...");
190         System.loadLibrary("android");
191         System.loadLibrary("jnigraphics");
192 
193         // TODO(b/206676167): This library is only used for renderscript today. When renderscript is
194         // removed, this load can be removed as well.
195         if (!SystemProperties.getBoolean("config.disable_renderscript", false)) {
196             System.loadLibrary("compiler_rt");
197         }
198     }
199 
nativePreloadAppProcessHALs()200     native private static void nativePreloadAppProcessHALs();
201 
202     /**
203      * This call loads the graphics driver by making an OpenGL or Vulkan call.  If the driver is
204      * not currently in memory it will load and initialize it.  The OpenGL call itself is relatively
205      * cheap and pure.  This means that it is a low overhead on the initial call, and is safe and
206      * cheap to call later.  Calls after the initial invocation will effectively be no-ops for the
207      * system.
208      */
nativePreloadGraphicsDriver()209     static native void nativePreloadGraphicsDriver();
210 
maybePreloadGraphicsDriver()211     private static void maybePreloadGraphicsDriver() {
212         if (!SystemProperties.getBoolean(PROPERTY_DISABLE_GRAPHICS_DRIVER_PRELOADING, false)) {
213             nativePreloadGraphicsDriver();
214         }
215     }
216 
preloadTextResources()217     private static void preloadTextResources() {
218         Hyphenator.init();
219         TextView.preloadFontCache();
220     }
221 
222     /**
223      * Register AndroidKeyStoreProvider and warm up the providers that are already registered.
224      *
225      * By doing it here we avoid that each app does it when requesting a service from the provider
226      * for the first time.
227      */
warmUpJcaProviders()228     private static void warmUpJcaProviders() {
229         long startTime = SystemClock.uptimeMillis();
230         Trace.traceBegin(
231                 Trace.TRACE_TAG_DALVIK, "Starting installation of AndroidKeyStoreProvider");
232 
233         AndroidKeyStoreProvider.install();
234         Log.i(TAG, "Installed AndroidKeyStoreProvider in "
235                 + (SystemClock.uptimeMillis() - startTime) + "ms.");
236         Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
237 
238         startTime = SystemClock.uptimeMillis();
239         Trace.traceBegin(
240                 Trace.TRACE_TAG_DALVIK, "Starting warm up of JCA providers");
241         for (Provider p : Security.getProviders()) {
242             p.warmUpServiceProvision();
243         }
244         Log.i(TAG, "Warmed up JCA providers in "
245                 + (SystemClock.uptimeMillis() - startTime) + "ms.");
246         Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
247     }
248 
isExperimentEnabled(String experiment)249     private static boolean isExperimentEnabled(String experiment) {
250         boolean defaultValue = SystemProperties.getBoolean(
251                 "dalvik.vm." + experiment,
252                 /*def=*/false);
253         // Can't use device_config since we are the zygote, and it's not initialized at this point.
254         return SystemProperties.getBoolean(
255                 "persist.device_config." + DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT
256                         + "." + experiment,
257                 defaultValue);
258     }
259 
shouldProfileSystemServer()260     /* package-private */ static boolean shouldProfileSystemServer() {
261         return isExperimentEnabled("profilesystemserver");
262     }
263 
264     /**
265      * Performs Zygote process initialization. Loads and initializes commonly used classes.
266      *
267      * Most classes only cause a few hundred bytes to be allocated, but a few will allocate a dozen
268      * Kbytes (in one case, 500+K).
269      */
preloadClasses()270     private static void preloadClasses() {
271         final VMRuntime runtime = VMRuntime.getRuntime();
272 
273         InputStream is;
274         try {
275             is = new FileInputStream(PRELOADED_CLASSES);
276         } catch (FileNotFoundException e) {
277             Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
278             return;
279         }
280 
281         Log.i(TAG, "Preloading classes...");
282         long startTime = SystemClock.uptimeMillis();
283 
284         // Drop root perms while running static initializers.
285         final int reuid = Os.getuid();
286         final int regid = Os.getgid();
287 
288         // We need to drop root perms only if we're already root. In the case of "wrapped"
289         // processes (see WrapperInit), this function is called from an unprivileged uid
290         // and gid.
291         boolean droppedPriviliges = false;
292         if (reuid == ROOT_UID && regid == ROOT_GID) {
293             try {
294                 Os.setregid(ROOT_GID, UNPRIVILEGED_GID);
295                 Os.setreuid(ROOT_UID, UNPRIVILEGED_UID);
296             } catch (ErrnoException ex) {
297                 throw new RuntimeException("Failed to drop root", ex);
298             }
299 
300             droppedPriviliges = true;
301         }
302 
303         try {
304             BufferedReader br =
305                     new BufferedReader(new InputStreamReader(is), Zygote.SOCKET_BUFFER_SIZE);
306 
307             int count = 0;
308             int missingLambdaCount = 0;
309             String line;
310             while ((line = br.readLine()) != null) {
311                 // Skip comments and blank lines.
312                 line = line.trim();
313                 if (line.startsWith("#") || line.equals("")) {
314                     continue;
315                 }
316 
317                 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, line);
318                 try {
319                     // Load and explicitly initialize the given class. Use
320                     // Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups
321                     // (to derive the caller's class-loader). Use true to force initialization, and
322                     // null for the boot classpath class-loader (could as well cache the
323                     // class-loader of this class in a variable).
324                     Class.forName(line, true, null);
325                     count++;
326                 } catch (ClassNotFoundException e) {
327                     if (line.contains("$$Lambda$")) {
328                         if (LOGGING_DEBUG) {
329                             missingLambdaCount++;
330                         }
331                     } else {
332                         Log.w(TAG, "Class not found for preloading: " + line);
333                     }
334                 } catch (UnsatisfiedLinkError e) {
335                     Log.w(TAG, "Problem preloading " + line + ": " + e);
336                 } catch (Throwable t) {
337                     Log.e(TAG, "Error preloading " + line + ".", t);
338                     if (t instanceof Error) {
339                         throw (Error) t;
340                     } else if (t instanceof RuntimeException) {
341                         throw (RuntimeException) t;
342                     } else {
343                         throw new RuntimeException(t);
344                     }
345                 }
346                 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
347             }
348 
349             Log.i(TAG, "...preloaded " + count + " classes in "
350                     + (SystemClock.uptimeMillis() - startTime) + "ms.");
351             if (LOGGING_DEBUG && missingLambdaCount != 0) {
352                 Log.i(TAG, "Unresolved lambda preloads: " + missingLambdaCount);
353             }
354         } catch (IOException e) {
355             Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
356         } finally {
357             IoUtils.closeQuietly(is);
358 
359             // Fill in dex caches with classes, fields, and methods brought in by preloading.
360             Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadDexCaches");
361             runtime.preloadDexCaches();
362             Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
363 
364             // If we are profiling the boot image, reset the Jit counters after preloading the
365             // classes. We want to preload for performance, and we can use method counters to
366             // infer what clases are used after calling resetJitCounters, for profile purposes.
367             if (isExperimentEnabled("profilebootclasspath")) {
368                 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ResetJitCounters");
369                 VMRuntime.resetJitCounters();
370                 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
371             }
372 
373             // Bring back root. We'll need it later if we're in the zygote.
374             if (droppedPriviliges) {
375                 try {
376                     Os.setreuid(ROOT_UID, ROOT_UID);
377                     Os.setregid(ROOT_GID, ROOT_GID);
378                 } catch (ErrnoException ex) {
379                     throw new RuntimeException("Failed to restore root", ex);
380                 }
381             }
382         }
383     }
384 
385     /**
386      * Load in things which are used by many apps but which cannot be put in the boot
387      * classpath.
388      */
cacheNonBootClasspathClassLoaders()389     private static void cacheNonBootClasspathClassLoaders() {
390         // Ordered dependencies first
391         final List<SharedLibraryInfo> libs = new ArrayList<>();
392         // These libraries used to be part of the bootclasspath, but had to be removed.
393         // Old system applications still get them for backwards compatibility reasons,
394         // so they are cached here in order to preserve performance characteristics.
395         libs.add(new SharedLibraryInfo(
396                 "/system/framework/android.hidl.base-V1.0-java.jar", null /*packageName*/,
397                 null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN,
398                 null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/,
399                 false /*isNative*/));
400         libs.add(new SharedLibraryInfo(
401                 "/system/framework/android.hidl.manager-V1.0-java.jar", null /*packageName*/,
402                 null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN,
403                 null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/,
404                 false /*isNative*/));
405 
406         libs.add(new SharedLibraryInfo(
407                 "/system/framework/android.test.base.jar", null /*packageName*/,
408                 null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN,
409                 null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/,
410                 false /*isNative*/));
411 
412         // WindowManager Extensions is an optional shared library that is required for WindowManager
413         // Jetpack to fully function. Since it is a widely used library, preload it to improve apps
414         // startup performance.
415         if (WindowManager.hasWindowExtensionsEnabled()) {
416             final String systemExtFrameworkPath =
417                     new File(Environment.getSystemExtDirectory(), "framework").getPath();
418             libs.add(new SharedLibraryInfo(
419                     systemExtFrameworkPath + "/androidx.window.extensions.jar",
420                     "androidx.window.extensions", null /*codePaths*/,
421                     "androidx.window.extensions", SharedLibraryInfo.VERSION_UNDEFINED,
422                     SharedLibraryInfo.TYPE_BUILTIN, null /*declaringPackage*/,
423                     null /*dependentPackages*/, null /*dependencies*/, false /*isNative*/));
424             libs.add(new SharedLibraryInfo(
425                     systemExtFrameworkPath + "/androidx.window.sidecar.jar",
426                     "androidx.window.sidecar", null /*codePaths*/,
427                     "androidx.window.sidecar", SharedLibraryInfo.VERSION_UNDEFINED,
428                     SharedLibraryInfo.TYPE_BUILTIN, null /*declaringPackage*/,
429                     null /*dependentPackages*/, null /*dependencies*/, false /*isNative*/));
430         }
431 
432         ApplicationLoaders.getDefault().createAndCacheNonBootclasspathSystemClassLoaders(libs);
433     }
434 
435     /**
436      * Load in commonly used resources, so they can be shared across processes.
437      *
438      * These tend to be a few Kbytes, but are frequently in the 20-40K range, and occasionally even
439      * larger.
440      */
preloadResources()441     private static void preloadResources() {
442         try {
443             mResources = Resources.getSystem();
444             mResources.startPreloading();
445             if (PRELOAD_RESOURCES) {
446                 Log.i(TAG, "Preloading resources...");
447 
448                 long startTime = SystemClock.uptimeMillis();
449                 TypedArray ar = mResources.obtainTypedArray(
450                         com.android.internal.R.array.preloaded_drawables);
451                 int N = preloadDrawables(ar);
452                 ar.recycle();
453                 Log.i(TAG, "...preloaded " + N + " resources in "
454                         + (SystemClock.uptimeMillis() - startTime) + "ms.");
455 
456                 startTime = SystemClock.uptimeMillis();
457                 ar = mResources.obtainTypedArray(
458                         com.android.internal.R.array.preloaded_color_state_lists);
459                 N = preloadColorStateLists(ar);
460                 ar.recycle();
461                 Log.i(TAG, "...preloaded " + N + " resources in "
462                         + (SystemClock.uptimeMillis() - startTime) + "ms.");
463 
464                 if (mResources.getBoolean(
465                         com.android.internal.R.bool.config_freeformWindowManagement)) {
466                     startTime = SystemClock.uptimeMillis();
467                     ar = mResources.obtainTypedArray(
468                             com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
469                     N = preloadDrawables(ar);
470                     ar.recycle();
471                     Log.i(TAG, "...preloaded " + N + " resource in "
472                             + (SystemClock.uptimeMillis() - startTime) + "ms.");
473                 }
474             }
475             mResources.finishPreloading();
476         } catch (RuntimeException e) {
477             Log.w(TAG, "Failure preloading resources", e);
478         }
479     }
480 
preloadColorStateLists(TypedArray ar)481     private static int preloadColorStateLists(TypedArray ar) {
482         int N = ar.length();
483         for (int i = 0; i < N; i++) {
484             int id = ar.getResourceId(i, 0);
485 
486             if (id != 0) {
487                 if (mResources.getColorStateList(id, null) == null) {
488                     throw new IllegalArgumentException(
489                             "Unable to find preloaded color resource #0x"
490                                     + Integer.toHexString(id)
491                                     + " (" + ar.getString(i) + ")");
492                 }
493             }
494         }
495         return N;
496     }
497 
498 
preloadDrawables(TypedArray ar)499     private static int preloadDrawables(TypedArray ar) {
500         int N = ar.length();
501         for (int i = 0; i < N; i++) {
502             int id = ar.getResourceId(i, 0);
503 
504             if (id != 0) {
505                 if (mResources.getDrawable(id, null) == null) {
506                     throw new IllegalArgumentException(
507                             "Unable to find preloaded drawable resource #0x"
508                                     + Integer.toHexString(id)
509                                     + " (" + ar.getString(i) + ")");
510                 }
511             }
512         }
513         return N;
514     }
515 
516     /**
517      * Runs several special GCs to try to clean up a few generations of softly- and final-reachable
518      * objects, along with any other garbage. This is only useful just before a fork().
519      */
gcAndFinalize()520     private static void gcAndFinalize() {
521         ZygoteHooks.gcAndFinalize();
522     }
523 
524     /**
525      * Finish remaining work for the newly forked system server process.
526      */
handleSystemServerProcess(ZygoteArguments parsedArgs)527     private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
528         // set umask to 0077 so new files and directories will default to owner-only permissions.
529         Os.umask(S_IRWXG | S_IRWXO);
530 
531         if (parsedArgs.mNiceName != null) {
532             Process.setArgV0(parsedArgs.mNiceName);
533         }
534 
535         final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
536         if (systemServerClasspath != null) {
537             // Capturing profiles is only supported for debug or eng builds since selinux normally
538             // prevents it.
539             if (shouldProfileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {
540                 try {
541                     Log.d(TAG, "Preparing system server profile");
542                     final String standaloneSystemServerJars =
543                             Os.getenv("STANDALONE_SYSTEMSERVER_JARS");
544                     final String systemServerPaths = standaloneSystemServerJars != null
545                             ? String.join(":", systemServerClasspath, standaloneSystemServerJars)
546                             : systemServerClasspath;
547                     prepareSystemServerProfile(systemServerPaths);
548                 } catch (Exception e) {
549                     Log.wtf(TAG, "Failed to set up system server profile", e);
550                 }
551             }
552         }
553 
554         if (parsedArgs.mInvokeWith != null) {
555             String[] args = parsedArgs.mRemainingArgs;
556             // If we have a non-null system server class path, we'll have to duplicate the
557             // existing arguments and append the classpath to it. ART will handle the classpath
558             // correctly when we exec a new process.
559             if (systemServerClasspath != null) {
560                 String[] amendedArgs = new String[args.length + 2];
561                 amendedArgs[0] = "-cp";
562                 amendedArgs[1] = systemServerClasspath;
563                 System.arraycopy(args, 0, amendedArgs, 2, args.length);
564                 args = amendedArgs;
565             }
566 
567             WrapperInit.execApplication(parsedArgs.mInvokeWith,
568                     parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
569                     VMRuntime.getCurrentInstructionSet(), null, args);
570 
571             throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
572         } else {
573             ClassLoader cl = getOrCreateSystemServerClassLoader();
574             if (cl != null) {
575                 Thread.currentThread().setContextClassLoader(cl);
576             }
577 
578             /*
579              * Pass the remaining arguments to SystemServer.
580              */
581             return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
582                     parsedArgs.mDisabledCompatChanges,
583                     parsedArgs.mRemainingArgs, cl);
584         }
585 
586         /* should never reach here */
587     }
588 
589     /**
590      * Create the classloader for the system server and store it in
591      * {@link sCachedSystemServerClassLoader}. This function is called through JNI in the forked
592      * system server process in the zygote SELinux domain.
593      */
getOrCreateSystemServerClassLoader()594     private static ClassLoader getOrCreateSystemServerClassLoader() {
595         if (sCachedSystemServerClassLoader == null) {
596             final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
597             if (systemServerClasspath != null) {
598                 sCachedSystemServerClassLoader = createPathClassLoader(systemServerClasspath,
599                         VMRuntime.SDK_VERSION_CUR_DEVELOPMENT);
600             }
601         }
602         return sCachedSystemServerClassLoader;
603     }
604 
605     /**
606      * Creates class loaders for standalone system server jars. This function is called through JNI
607      * in the forked system server process in the zygote SELinux domain.
608      */
prefetchStandaloneSystemServerJars()609     private static void prefetchStandaloneSystemServerJars() {
610         if (shouldProfileSystemServer()) {
611             // We don't prefetch AOT artifacts if we are profiling system server, as we are going to
612             // JIT it.
613             // This method only gets called from native and should already be skipped if we profile
614             // system server. Still, be robust and check it again.
615             return;
616         }
617         String envStr = Os.getenv("STANDALONE_SYSTEMSERVER_JARS");
618         if (TextUtils.isEmpty(envStr)) {
619             return;
620         }
621         for (String jar : envStr.split(":")) {
622             try {
623                 SystemServerClassLoaderFactory.createClassLoader(
624                         jar, getOrCreateSystemServerClassLoader());
625             } catch (Error e) {
626                 // We don't want the process to crash for this error because prefetching is just an
627                 // optimization.
628                 Log.e(TAG,
629                         String.format("Failed to prefetch standalone system server jar \"%s\": %s",
630                                 jar, e.toString()));
631             }
632         }
633     }
634 
635     /**
636      * Note that preparing the profiles for system server does not require special selinux
637      * permissions. From the installer perspective the system server is a regular package which can
638      * capture profile information.
639      */
prepareSystemServerProfile(String systemServerPaths)640     private static void prepareSystemServerProfile(String systemServerPaths)
641             throws RemoteException {
642         if (systemServerPaths.isEmpty()) {
643             return;
644         }
645         String[] codePaths = systemServerPaths.split(":");
646 
647         final IInstalld installd = IInstalld.Stub
648                 .asInterface(ServiceManager.getService("installd"));
649 
650         String systemServerPackageName = "android";
651         String systemServerProfileName = "primary.prof";
652         installd.prepareAppProfile(
653                 systemServerPackageName,
654                 UserHandle.USER_SYSTEM,
655                 UserHandle.getAppId(Process.SYSTEM_UID),
656                 systemServerProfileName,
657                 codePaths[0],
658                 /*dexMetadata*/ null);
659 
660         File curProfileDir = Environment.getDataProfilesDePackageDirectory(
661                 UserHandle.USER_SYSTEM, systemServerPackageName);
662         String curProfilePath = new File(curProfileDir, systemServerProfileName).getAbsolutePath();
663         File refProfileDir = Environment.getDataProfilesDePackageDirectory(
664                 UserHandle.USER_SYSTEM, systemServerPackageName);
665         String refProfilePath = new File(refProfileDir, systemServerProfileName).getAbsolutePath();
666         VMRuntime.registerAppInfo(
667                 systemServerPackageName,
668                 curProfilePath,
669                 refProfilePath,
670                 codePaths,
671                 VMRuntime.CODE_PATH_TYPE_PRIMARY_APK);
672     }
673 
674     /**
675      * Sets the list of classes/methods for the hidden API
676      */
setApiDenylistExemptions(String[] exemptions)677     public static void setApiDenylistExemptions(String[] exemptions) {
678         VMRuntime.getRuntime().setHiddenApiExemptions(exemptions);
679     }
680 
setHiddenApiAccessLogSampleRate(int percent)681     public static void setHiddenApiAccessLogSampleRate(int percent) {
682         VMRuntime.getRuntime().setHiddenApiAccessLogSamplingRate(percent);
683     }
684 
685     /**
686      * Sets the implementation to be used for logging hidden API accesses
687      * @param logger the implementation of the VMRuntime.HiddenApiUsageLogger interface
688      */
setHiddenApiUsageLogger(VMRuntime.HiddenApiUsageLogger logger)689     public static void setHiddenApiUsageLogger(VMRuntime.HiddenApiUsageLogger logger) {
690         VMRuntime.getRuntime().setHiddenApiUsageLogger(logger);
691     }
692 
693     /**
694      * Creates a PathClassLoader for the given class path that is associated with a shared
695      * namespace, i.e., this classloader can access platform-private native libraries.
696      *
697      * The classloader will add java.library.path to the native library path for the classloader
698      * namespace. Since it includes platform locations like /system/lib, this is only appropriate
699      * for platform code that don't need linker namespace isolation (as opposed to APEXes and apps).
700      */
createPathClassLoader(String classPath, int targetSdkVersion)701     static ClassLoader createPathClassLoader(String classPath, int targetSdkVersion) {
702         String libraryPath = System.getProperty("java.library.path");
703 
704         // We use the boot class loader, that's what the runtime expects at AOT.
705         ClassLoader parent = ClassLoader.getSystemClassLoader().getParent();
706 
707         return ClassLoaderFactory.createClassLoader(classPath, libraryPath, libraryPath,
708                 parent, targetSdkVersion, true /* isNamespaceShared */, null /* classLoaderName */);
709     }
710 
711     /**
712      * Prepare the arguments and forks for the system server process.
713      *
714      * @return A {@code Runnable} that provides an entrypoint into system_server code in the child
715      * process; {@code null} in the parent.
716      */
forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)717     private static Runnable forkSystemServer(String abiList, String socketName,
718             ZygoteServer zygoteServer) {
719         long capabilities = posixCapabilitiesAsBits(
720                 OsConstants.CAP_IPC_LOCK,
721                 OsConstants.CAP_KILL,
722                 OsConstants.CAP_NET_ADMIN,
723                 OsConstants.CAP_NET_BIND_SERVICE,
724                 OsConstants.CAP_NET_BROADCAST,
725                 OsConstants.CAP_NET_RAW,
726                 OsConstants.CAP_SYS_MODULE,
727                 OsConstants.CAP_SYS_NICE,
728                 OsConstants.CAP_SYS_PTRACE,
729                 OsConstants.CAP_SYS_TIME,
730                 OsConstants.CAP_SYS_TTY_CONFIG,
731                 OsConstants.CAP_WAKE_ALARM,
732                 OsConstants.CAP_BLOCK_SUSPEND
733         );
734         /* Containers run without some capabilities, so drop any caps that are not available. */
735         StructCapUserHeader header = new StructCapUserHeader(
736                 OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
737         StructCapUserData[] data;
738         try {
739             data = Os.capget(header);
740         } catch (ErrnoException ex) {
741             throw new RuntimeException("Failed to capget()", ex);
742         }
743         capabilities &= Integer.toUnsignedLong(data[0].effective) |
744                 (Integer.toUnsignedLong(data[1].effective) << 32);
745 
746         /* Hardcoded command line to start the system server */
747         String[] args = {
748                 "--setuid=1000",
749                 "--setgid=1000",
750                 "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
751                         + "1024,1032,1065,3001,3002,3003,3005,3006,3007,3009,3010,3011,3012",
752                 "--capabilities=" + capabilities + "," + capabilities,
753                 "--nice-name=system_server",
754                 "--runtime-args",
755                 "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
756                 "com.android.server.SystemServer",
757         };
758         ZygoteArguments parsedArgs;
759 
760         int pid;
761 
762         try {
763             ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
764             try {
765                 parsedArgs = ZygoteArguments.getInstance(commandBuffer);
766             } catch (EOFException e) {
767                 throw new AssertionError("Unexpected argument error for forking system server", e);
768             }
769             commandBuffer.close();
770             Zygote.applyDebuggerSystemProperty(parsedArgs);
771             Zygote.applyInvokeWithSystemProperty(parsedArgs);
772 
773             if (Zygote.nativeSupportsMemoryTagging()) {
774                 String mode = SystemProperties.get("persist.arm64.memtag.system_server", "");
775                 if (mode.isEmpty()) {
776                   /* The system server has ASYNC MTE by default, in order to allow
777                    * system services to specify their own MTE level later, as you
778                    * can't re-enable MTE once it's disabled. */
779                   mode = SystemProperties.get("persist.arm64.memtag.default", "async");
780                 }
781                 if (mode.equals("async")) {
782                     parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_ASYNC;
783                 } else if (mode.equals("sync")) {
784                     parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_SYNC;
785                 } else if (!mode.equals("off")) {
786                     /* When we have an invalid memory tag level, keep the current level. */
787                     parsedArgs.mRuntimeFlags |= Zygote.nativeCurrentTaggingLevel();
788                     Slog.e(TAG, "Unknown memory tag level for the system server: \"" + mode + "\"");
789                 }
790             } else if (Zygote.nativeSupportsTaggedPointers()) {
791                 /* Enable pointer tagging in the system server. Hardware support for this is present
792                  * in all ARMv8 CPUs. */
793                 parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
794             }
795 
796             /* Enable gwp-asan on the system server with a small probability. This is the same
797              * policy as applied to native processes and system apps. */
798             parsedArgs.mRuntimeFlags |= Zygote.GWP_ASAN_LEVEL_LOTTERY;
799 
800             if (shouldProfileSystemServer()) {
801                 parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
802             }
803 
804             /* Request to fork the system server process */
805             pid = Zygote.forkSystemServer(
806                     parsedArgs.mUid, parsedArgs.mGid,
807                     parsedArgs.mGids,
808                     parsedArgs.mRuntimeFlags,
809                     null,
810                     parsedArgs.mPermittedCapabilities,
811                     parsedArgs.mEffectiveCapabilities);
812         } catch (IllegalArgumentException ex) {
813             throw new RuntimeException(ex);
814         }
815 
816         /* For child process */
817         if (pid == 0) {
818             if (hasSecondZygote(abiList)) {
819                 waitForSecondaryZygote(socketName);
820             }
821 
822             zygoteServer.closeServerSocket();
823             return handleSystemServerProcess(parsedArgs);
824         }
825 
826         return null;
827     }
828 
829     /**
830      * Gets the bit array representation of the provided list of POSIX capabilities.
831      */
posixCapabilitiesAsBits(int... capabilities)832     private static long posixCapabilitiesAsBits(int... capabilities) {
833         long result = 0;
834         for (int capability : capabilities) {
835             if ((capability < 0) || (capability > OsConstants.CAP_LAST_CAP)) {
836                 throw new IllegalArgumentException(String.valueOf(capability));
837             }
838             result |= (1L << capability);
839         }
840         return result;
841     }
842 
843     /**
844      * This is the entry point for a Zygote process.  It creates the Zygote server, loads resources,
845      * and handles other tasks related to preparing the process for forking into applications.
846      *
847      * This process is started with a nice value of -20 (highest priority).  All paths that flow
848      * into new processes are required to either set the priority to the default value or terminate
849      * before executing any non-system code.  The native side of this occurs in SpecializeCommon,
850      * while the Java Language priority is changed in ZygoteInit.handleSystemServerProcess,
851      * ZygoteConnection.handleChildProc, and Zygote.childMain.
852      *
853      * @param argv  Command line arguments used to specify the Zygote's configuration.
854      */
855     @UnsupportedAppUsage
main(String[] argv)856     public static void main(String[] argv) {
857         ZygoteServer zygoteServer = null;
858 
859         // Mark zygote start. This ensures that thread creation will throw
860         // an error.
861         ZygoteHooks.startZygoteNoThreadCreation();
862 
863         // Zygote goes into its own process group.
864         try {
865             Os.setpgid(0, 0);
866         } catch (ErrnoException ex) {
867             throw new RuntimeException("Failed to setpgid(0,0)", ex);
868         }
869 
870         Runnable caller;
871         try {
872             // Store now for StatsLogging later.
873             final long startTime = SystemClock.elapsedRealtime();
874             final boolean isRuntimeRestarted = "1".equals(
875                     SystemProperties.get("sys.boot_completed"));
876 
877             String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
878             TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
879                     Trace.TRACE_TAG_DALVIK);
880             bootTimingsTraceLog.traceBegin("ZygoteInit");
881             RuntimeInit.preForkInit();
882 
883             boolean startSystemServer = false;
884             String zygoteSocketName = "zygote";
885             String abiList = null;
886             boolean enableLazyPreload = false;
887             for (int i = 1; i < argv.length; i++) {
888                 if ("start-system-server".equals(argv[i])) {
889                     startSystemServer = true;
890                 } else if ("--enable-lazy-preload".equals(argv[i])) {
891                     enableLazyPreload = true;
892                 } else if (argv[i].startsWith(ABI_LIST_ARG)) {
893                     abiList = argv[i].substring(ABI_LIST_ARG.length());
894                 } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
895                     zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
896                 } else {
897                     throw new RuntimeException("Unknown command line argument: " + argv[i]);
898                 }
899             }
900 
901             final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
902             if (!isRuntimeRestarted) {
903                 if (isPrimaryZygote) {
904                     FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
905                             BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__ZYGOTE_INIT_START,
906                             startTime);
907                 } else if (zygoteSocketName.equals(Zygote.SECONDARY_SOCKET_NAME)) {
908                     FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
909                             BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SECONDARY_ZYGOTE_INIT_START,
910                             startTime);
911                 }
912             }
913 
914             if (abiList == null) {
915                 throw new RuntimeException("No ABI list supplied.");
916             }
917 
918             // In some configurations, we avoid preloading resources and classes eagerly.
919             // In such cases, we will preload things prior to our first fork.
920             if (!enableLazyPreload) {
921                 bootTimingsTraceLog.traceBegin("ZygotePreload");
922                 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
923                         SystemClock.uptimeMillis());
924                 preload(bootTimingsTraceLog);
925                 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
926                         SystemClock.uptimeMillis());
927                 bootTimingsTraceLog.traceEnd(); // ZygotePreload
928             }
929 
930             // Do an initial gc to clean up after startup
931             bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
932             gcAndFinalize();
933             bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
934 
935             bootTimingsTraceLog.traceEnd(); // ZygoteInit
936 
937             Zygote.initNativeState(isPrimaryZygote);
938 
939             ZygoteHooks.stopZygoteNoThreadCreation();
940 
941             zygoteServer = new ZygoteServer(isPrimaryZygote);
942 
943             if (startSystemServer) {
944                 Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
945 
946                 // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
947                 // child (system_server) process.
948                 if (r != null) {
949                     r.run();
950                     return;
951                 }
952             }
953 
954             Log.i(TAG, "Accepting command socket connections");
955 
956             // The select loop returns early in the child process after a fork and
957             // loops forever in the zygote.
958             caller = zygoteServer.runSelectLoop(abiList);
959         } catch (Throwable ex) {
960             Log.e(TAG, "System zygote died with fatal exception", ex);
961             throw ex;
962         } finally {
963             if (zygoteServer != null) {
964                 zygoteServer.closeServerSocket();
965             }
966         }
967 
968         // We're in the child process and have exited the select loop. Proceed to execute the
969         // command.
970         if (caller != null) {
971             caller.run();
972         }
973     }
974 
975     /**
976      * Return {@code true} if this device configuration has another zygote.
977      *
978      * We determine this by comparing the device ABI list with this zygotes list. If this zygote
979      * supports all ABIs this device supports, there won't be another zygote.
980      */
hasSecondZygote(String abiList)981     private static boolean hasSecondZygote(String abiList) {
982         return !SystemProperties.get("ro.product.cpu.abilist").equals(abiList);
983     }
984 
waitForSecondaryZygote(String socketName)985     private static void waitForSecondaryZygote(String socketName) {
986         String otherZygoteName = Zygote.PRIMARY_SOCKET_NAME.equals(socketName)
987                 ? Zygote.SECONDARY_SOCKET_NAME : Zygote.PRIMARY_SOCKET_NAME;
988         ZygoteProcess.waitForConnectionToZygote(otherZygoteName);
989     }
990 
isPreloadComplete()991     static boolean isPreloadComplete() {
992         return sPreloadComplete;
993     }
994 
995     /**
996      * Class not instantiable.
997      */
ZygoteInit()998     private ZygoteInit() {
999     }
1000 
1001     /**
1002      * The main function called when started through the zygote process. This could be unified with
1003      * main(), if the native code in nativeFinishInit() were rationalized with Zygote startup.<p>
1004      *
1005      * Current recognized args:
1006      * <ul>
1007      * <li> <code> [--] &lt;start class name&gt;  &lt;args&gt;
1008      * </ul>
1009      *
1010      * @param targetSdkVersion target SDK version
1011      * @param disabledCompatChanges set of disabled compat changes for the process (all others
1012      *                              are enabled)
1013      * @param argv             arg strings
1014      */
zygoteInit(int targetSdkVersion, long[] disabledCompatChanges, String[] argv, ClassLoader classLoader)1015     public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
1016             String[] argv, ClassLoader classLoader) {
1017         if (RuntimeInit.DEBUG) {
1018             Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
1019         }
1020 
1021         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
1022         RuntimeInit.redirectLogStreams();
1023 
1024         RuntimeInit.commonInit();
1025         ZygoteInit.nativeZygoteInit();
1026         return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
1027                 classLoader);
1028     }
1029 
1030     /**
1031      * The main function called when starting a child zygote process. This is used as an alternative
1032      * to zygoteInit(), which skips calling into initialization routines that start the Binder
1033      * threadpool.
1034      */
childZygoteInit(String[] argv)1035     static Runnable childZygoteInit(String[] argv) {
1036         RuntimeInit.Arguments args = new RuntimeInit.Arguments(argv);
1037         return RuntimeInit.findStaticMain(args.startClass, args.startArgs, /* classLoader= */null);
1038     }
1039 
nativeZygoteInit()1040     private static native void nativeZygoteInit();
1041 }
1042