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