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