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