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