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