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