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