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