ZygoteInit.java revision 3d44ed0dfe33da3b9f08d102723d7fc842e18f74
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 17package com.android.internal.os; 18 19import static android.system.OsConstants.S_IRWXG; 20import static android.system.OsConstants.S_IRWXO; 21 22import android.content.res.Resources; 23import android.content.res.TypedArray; 24import android.icu.impl.CacheValue; 25import android.icu.text.DecimalFormatSymbols; 26import android.icu.util.ULocale; 27import android.opengl.EGL14; 28import android.os.Build; 29import android.os.IInstalld; 30import android.os.Environment; 31import android.os.Process; 32import android.os.RemoteException; 33import android.os.Seccomp; 34import android.os.ServiceManager; 35import android.os.ServiceSpecificException; 36import android.os.SystemClock; 37import android.os.SystemProperties; 38import android.os.Trace; 39import android.os.ZygoteProcess; 40import android.os.storage.StorageManager; 41import android.security.keystore.AndroidKeyStoreProvider; 42import android.system.ErrnoException; 43import android.system.Os; 44import android.system.OsConstants; 45import android.system.StructCapUserData; 46import android.system.StructCapUserHeader; 47import android.text.Hyphenator; 48import android.util.TimingsTraceLog; 49import android.util.EventLog; 50import android.util.Log; 51import android.util.Slog; 52import android.webkit.WebViewFactory; 53import android.widget.TextView; 54 55import com.android.internal.logging.MetricsLogger; 56 57import com.android.internal.util.Preconditions; 58import dalvik.system.DexFile; 59import dalvik.system.VMRuntime; 60import dalvik.system.ZygoteHooks; 61 62import libcore.io.IoUtils; 63 64import java.io.BufferedReader; 65import java.io.File; 66import java.io.FileInputStream; 67import java.io.FileNotFoundException; 68import java.io.IOException; 69import java.io.InputStream; 70import java.io.InputStreamReader; 71import java.security.Security; 72import java.security.Provider; 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 */ 86public 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 File profileDir = Environment.getDataProfilesDePackageDirectory( 471 Process.SYSTEM_UID, "system_server"); 472 File profile = new File(profileDir, "primary.prof"); 473 profile.getParentFile().mkdirs(); 474 profile.createNewFile(); 475 String[] codePaths = systemServerClasspath.split(":"); 476 VMRuntime.registerAppInfo(profile.getPath(), codePaths); 477 } catch (Exception e) { 478 Log.wtf(TAG, "Failed to set up system server profile", e); 479 } 480 } 481 } 482 483 if (parsedArgs.invokeWith != null) { 484 String[] args = parsedArgs.remainingArgs; 485 // If we have a non-null system server class path, we'll have to duplicate the 486 // existing arguments and append the classpath to it. ART will handle the classpath 487 // correctly when we exec a new process. 488 if (systemServerClasspath != null) { 489 String[] amendedArgs = new String[args.length + 2]; 490 amendedArgs[0] = "-cp"; 491 amendedArgs[1] = systemServerClasspath; 492 System.arraycopy(args, 0, amendedArgs, 2, args.length); 493 args = amendedArgs; 494 } 495 496 WrapperInit.execApplication(parsedArgs.invokeWith, 497 parsedArgs.niceName, parsedArgs.targetSdkVersion, 498 VMRuntime.getCurrentInstructionSet(), null, args); 499 500 throw new IllegalStateException("Unexpected return from WrapperInit.execApplication"); 501 } else { 502 ClassLoader cl = null; 503 if (systemServerClasspath != null) { 504 cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion); 505 506 Thread.currentThread().setContextClassLoader(cl); 507 } 508 509 /* 510 * Pass the remaining arguments to SystemServer. 511 */ 512 return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); 513 } 514 515 /* should never reach here */ 516 } 517 518 /** 519 * Creates a PathClassLoader for the given class path that is associated with a shared 520 * namespace, i.e., this classloader can access platform-private native libraries. The 521 * classloader will use java.library.path as the native library path. 522 */ 523 static ClassLoader createPathClassLoader(String classPath, int targetSdkVersion) { 524 String libraryPath = System.getProperty("java.library.path"); 525 526 return ClassLoaderFactory.createClassLoader(classPath, libraryPath, libraryPath, 527 ClassLoader.getSystemClassLoader(), targetSdkVersion, true /* isNamespaceShared */, 528 null /* classLoaderName */); 529 } 530 531 /** 532 * Performs dex-opt on the elements of {@code classPath}, if needed. We 533 * choose the instruction set of the current runtime. 534 */ 535 private static void performSystemServerDexOpt(String classPath) { 536 final String[] classPathElements = classPath.split(":"); 537 final IInstalld installd = IInstalld.Stub 538 .asInterface(ServiceManager.getService("installd")); 539 final String instructionSet = VMRuntime.getRuntime().vmInstructionSet(); 540 541 String classPathForElement = ""; 542 for (String classPathElement : classPathElements) { 543 // System server is fully AOTed and never profiled 544 // for profile guided compilation. 545 String systemServerFilter = SystemProperties.get( 546 "dalvik.vm.systemservercompilerfilter", "speed"); 547 548 int dexoptNeeded; 549 try { 550 dexoptNeeded = DexFile.getDexOptNeeded( 551 classPathElement, instructionSet, systemServerFilter, 552 null /* classLoaderContext */, false /* newProfile */, false /* downgrade */); 553 } catch (FileNotFoundException ignored) { 554 // Do not add to the classpath. 555 Log.w(TAG, "Missing classpath element for system server: " + classPathElement); 556 continue; 557 } catch (IOException e) { 558 // Not fully clear what to do here as we don't know the cause of the 559 // IO exception. Add to the classpath to be conservative, but don't 560 // attempt to compile it. 561 Log.w(TAG, "Error checking classpath element for system server: " 562 + classPathElement, e); 563 dexoptNeeded = DexFile.NO_DEXOPT_NEEDED; 564 } 565 566 if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) { 567 final String packageName = "*"; 568 final String outputPath = null; 569 final int dexFlags = 0; 570 final String compilerFilter = systemServerFilter; 571 final String uuid = StorageManager.UUID_PRIVATE_INTERNAL; 572 final String seInfo = null; 573 final String classLoaderContext = 574 getSystemServerClassLoaderContext(classPathForElement); 575 final int targetSdkVersion = 0; // SystemServer targets the system's SDK version 576 try { 577 installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName, 578 instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter, 579 uuid, classLoaderContext, seInfo, false /* downgrade */, 580 targetSdkVersion); 581 } catch (RemoteException | ServiceSpecificException e) { 582 // Ignore (but log), we need this on the classpath for fallback mode. 583 Log.w(TAG, "Failed compiling classpath element for system server: " 584 + classPathElement, e); 585 } 586 } 587 588 classPathForElement = encodeSystemServerClassPath( 589 classPathForElement, classPathElement); 590 } 591 } 592 593 /** 594 * Encodes the system server class loader context in a format that is accepted by dexopt. 595 * This assumes the system server is always loaded with a {@link dalvik.system.PathClassLoader}. 596 * 597 * Note that ideally we would use the {@code DexoptUtils} to compute this. However we have no 598 * dependency here on the server so we hard code the logic again. 599 */ 600 private static String getSystemServerClassLoaderContext(String classPath) { 601 return classPath == null ? "PCL[]" : "PCL[" + classPath + "]"; 602 } 603 604 /** 605 * Encodes the class path in a format accepted by dexopt. 606 * @param classPath the old class path (may be empty). 607 * @param newElement the new class path elements 608 * @return the class path encoding resulted from appending {@code newElement} to 609 * {@code classPath}. 610 */ 611 private static String encodeSystemServerClassPath(String classPath, String newElement) { 612 return (classPath == null || classPath.isEmpty()) 613 ? newElement 614 : classPath + ":" + newElement; 615 } 616 617 /** 618 * Prepare the arguments and forks for the system server process. 619 * 620 * Returns an {@code Runnable} that provides an entrypoint into system_server code in the 621 * child process, and {@code null} in the parent. 622 */ 623 private static Runnable forkSystemServer(String abiList, String socketName, 624 ZygoteServer zygoteServer) { 625 long capabilities = posixCapabilitiesAsBits( 626 OsConstants.CAP_IPC_LOCK, 627 OsConstants.CAP_KILL, 628 OsConstants.CAP_NET_ADMIN, 629 OsConstants.CAP_NET_BIND_SERVICE, 630 OsConstants.CAP_NET_BROADCAST, 631 OsConstants.CAP_NET_RAW, 632 OsConstants.CAP_SYS_MODULE, 633 OsConstants.CAP_SYS_NICE, 634 OsConstants.CAP_SYS_PTRACE, 635 OsConstants.CAP_SYS_TIME, 636 OsConstants.CAP_SYS_TTY_CONFIG, 637 OsConstants.CAP_WAKE_ALARM, 638 OsConstants.CAP_BLOCK_SUSPEND 639 ); 640 /* Containers run without some capabilities, so drop any caps that are not available. */ 641 StructCapUserHeader header = new StructCapUserHeader( 642 OsConstants._LINUX_CAPABILITY_VERSION_3, 0); 643 StructCapUserData[] data; 644 try { 645 data = Os.capget(header); 646 } catch (ErrnoException ex) { 647 throw new RuntimeException("Failed to capget()", ex); 648 } 649 capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32); 650 651 /* Hardcoded command line to start the system server */ 652 String args[] = { 653 "--setuid=1000", 654 "--setgid=1000", 655 "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010", 656 "--capabilities=" + capabilities + "," + capabilities, 657 "--nice-name=system_server", 658 "--runtime-args", 659 "com.android.server.SystemServer", 660 }; 661 ZygoteConnection.Arguments parsedArgs = null; 662 663 int pid; 664 665 try { 666 parsedArgs = new ZygoteConnection.Arguments(args); 667 ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); 668 ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); 669 670 /* Request to fork the system server process */ 671 pid = Zygote.forkSystemServer( 672 parsedArgs.uid, parsedArgs.gid, 673 parsedArgs.gids, 674 parsedArgs.runtimeFlags, 675 null, 676 parsedArgs.permittedCapabilities, 677 parsedArgs.effectiveCapabilities); 678 } catch (IllegalArgumentException ex) { 679 throw new RuntimeException(ex); 680 } 681 682 /* For child process */ 683 if (pid == 0) { 684 if (hasSecondZygote(abiList)) { 685 waitForSecondaryZygote(socketName); 686 } 687 688 zygoteServer.closeServerSocket(); 689 return handleSystemServerProcess(parsedArgs); 690 } 691 692 return null; 693 } 694 695 /** 696 * Gets the bit array representation of the provided list of POSIX capabilities. 697 */ 698 private static long posixCapabilitiesAsBits(int... capabilities) { 699 long result = 0; 700 for (int capability : capabilities) { 701 if ((capability < 0) || (capability > OsConstants.CAP_LAST_CAP)) { 702 throw new IllegalArgumentException(String.valueOf(capability)); 703 } 704 result |= (1L << capability); 705 } 706 return result; 707 } 708 709 public static void main(String argv[]) { 710 ZygoteServer zygoteServer = new ZygoteServer(); 711 712 // Mark zygote start. This ensures that thread creation will throw 713 // an error. 714 ZygoteHooks.startZygoteNoThreadCreation(); 715 716 // Zygote goes into its own process group. 717 try { 718 Os.setpgid(0, 0); 719 } catch (ErrnoException ex) { 720 throw new RuntimeException("Failed to setpgid(0,0)", ex); 721 } 722 723 final Runnable caller; 724 try { 725 // Report Zygote start time to tron unless it is a runtime restart 726 if (!"1".equals(SystemProperties.get("sys.boot_completed"))) { 727 MetricsLogger.histogram(null, "boot_zygote_init", 728 (int) SystemClock.elapsedRealtime()); 729 } 730 731 String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing"; 732 TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag, 733 Trace.TRACE_TAG_DALVIK); 734 bootTimingsTraceLog.traceBegin("ZygoteInit"); 735 RuntimeInit.enableDdms(); 736 737 boolean startSystemServer = false; 738 String socketName = "zygote"; 739 String abiList = null; 740 boolean enableLazyPreload = false; 741 for (int i = 1; i < argv.length; i++) { 742 if ("start-system-server".equals(argv[i])) { 743 startSystemServer = true; 744 } else if ("--enable-lazy-preload".equals(argv[i])) { 745 enableLazyPreload = true; 746 } else if (argv[i].startsWith(ABI_LIST_ARG)) { 747 abiList = argv[i].substring(ABI_LIST_ARG.length()); 748 } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { 749 socketName = argv[i].substring(SOCKET_NAME_ARG.length()); 750 } else { 751 throw new RuntimeException("Unknown command line argument: " + argv[i]); 752 } 753 } 754 755 if (abiList == null) { 756 throw new RuntimeException("No ABI list supplied."); 757 } 758 759 zygoteServer.registerServerSocket(socketName); 760 // In some configurations, we avoid preloading resources and classes eagerly. 761 // In such cases, we will preload things prior to our first fork. 762 if (!enableLazyPreload) { 763 bootTimingsTraceLog.traceBegin("ZygotePreload"); 764 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, 765 SystemClock.uptimeMillis()); 766 preload(bootTimingsTraceLog); 767 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, 768 SystemClock.uptimeMillis()); 769 bootTimingsTraceLog.traceEnd(); // ZygotePreload 770 } else { 771 Zygote.resetNicePriority(); 772 } 773 774 // Do an initial gc to clean up after startup 775 bootTimingsTraceLog.traceBegin("PostZygoteInitGC"); 776 gcAndFinalize(); 777 bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC 778 779 bootTimingsTraceLog.traceEnd(); // ZygoteInit 780 // Disable tracing so that forked processes do not inherit stale tracing tags from 781 // Zygote. 782 Trace.setTracingEnabled(false, 0); 783 784 // Zygote process unmounts root storage spaces. 785 Zygote.nativeUnmountStorageOnInit(); 786 787 // Set seccomp policy 788 Seccomp.setPolicy(); 789 790 ZygoteHooks.stopZygoteNoThreadCreation(); 791 792 if (startSystemServer) { 793 Runnable r = forkSystemServer(abiList, socketName, zygoteServer); 794 795 // {@code r == null} in the parent (zygote) process, and {@code r != null} in the 796 // child (system_server) process. 797 if (r != null) { 798 r.run(); 799 return; 800 } 801 } 802 803 Log.i(TAG, "Accepting command socket connections"); 804 805 // The select loop returns early in the child process after a fork and 806 // loops forever in the zygote. 807 caller = zygoteServer.runSelectLoop(abiList); 808 } catch (Throwable ex) { 809 Log.e(TAG, "System zygote died with exception", ex); 810 throw ex; 811 } finally { 812 zygoteServer.closeServerSocket(); 813 } 814 815 // We're in the child process and have exited the select loop. Proceed to execute the 816 // command. 817 if (caller != null) { 818 caller.run(); 819 } 820 } 821 822 /** 823 * Return {@code true} if this device configuration has another zygote. 824 * 825 * We determine this by comparing the device ABI list with this zygotes 826 * list. If this zygote supports all ABIs this device supports, there won't 827 * be another zygote. 828 */ 829 private static boolean hasSecondZygote(String abiList) { 830 return !SystemProperties.get("ro.product.cpu.abilist").equals(abiList); 831 } 832 833 private static void waitForSecondaryZygote(String socketName) { 834 String otherZygoteName = Process.ZYGOTE_SOCKET.equals(socketName) ? 835 Process.SECONDARY_ZYGOTE_SOCKET : Process.ZYGOTE_SOCKET; 836 ZygoteProcess.waitForConnectionToZygote(otherZygoteName); 837 } 838 839 static boolean isPreloadComplete() { 840 return sPreloadComplete; 841 } 842 843 /** 844 * Class not instantiable. 845 */ 846 private ZygoteInit() { 847 } 848 849 /** 850 * The main function called when started through the zygote process. This 851 * could be unified with main(), if the native code in nativeFinishInit() 852 * were rationalized with Zygote startup.<p> 853 * 854 * Current recognized args: 855 * <ul> 856 * <li> <code> [--] <start class name> <args> 857 * </ul> 858 * 859 * @param targetSdkVersion target SDK version 860 * @param argv arg strings 861 */ 862 public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) { 863 if (RuntimeInit.DEBUG) { 864 Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote"); 865 } 866 867 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit"); 868 RuntimeInit.redirectLogStreams(); 869 870 RuntimeInit.commonInit(); 871 ZygoteInit.nativeZygoteInit(); 872 return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); 873 } 874 875 private static final native void nativeZygoteInit(); 876} 877