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.net.LocalServerSocket; 28 import android.opengl.EGL14; 29 import android.os.Build; 30 import android.os.IInstalld; 31 import android.os.Environment; 32 import android.os.Process; 33 import android.os.RemoteException; 34 import android.os.Seccomp; 35 import android.os.ServiceManager; 36 import android.os.ServiceSpecificException; 37 import android.os.SystemClock; 38 import android.os.SystemProperties; 39 import android.os.Trace; 40 import android.os.ZygoteProcess; 41 import android.os.storage.StorageManager; 42 import android.security.keystore.AndroidKeyStoreProvider; 43 import android.system.ErrnoException; 44 import android.system.Os; 45 import android.system.OsConstants; 46 import android.text.Hyphenator; 47 import android.util.BootTimingsTraceLog; 48 import android.util.EventLog; 49 import android.util.Log; 50 import android.util.Slog; 51 import android.webkit.WebViewFactory; 52 import android.widget.TextView; 53 54 import com.android.internal.logging.MetricsLogger; 55 56 import com.android.internal.util.Preconditions; 57 import dalvik.system.DexFile; 58 import dalvik.system.PathClassLoader; 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.Security; 72 import 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 */ 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 private static final String PROPERTY_RUNNING_IN_CONTAINER = "ro.boot.container"; 92 93 private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020; 94 private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030; 95 96 /** when preloading, GC after allocating this many bytes */ 97 private static final int PRELOAD_GC_THRESHOLD = 50000; 98 99 private static final String ABI_LIST_ARG = "--abi-list="; 100 101 private static final String SOCKET_NAME_ARG = "--socket-name="; 102 103 /** 104 * Used to pre-load resources. 105 */ 106 private static Resources mResources; 107 108 /** 109 * The path of a file that contains classes to preload. 110 */ 111 private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes"; 112 113 /** Controls whether we should preload resources during zygote init. */ 114 public static final boolean PRELOAD_RESOURCES = true; 115 116 private static final int UNPRIVILEGED_UID = 9999; 117 private static final int UNPRIVILEGED_GID = 9999; 118 119 private static final int ROOT_UID = 0; 120 private static final int ROOT_GID = 0; 121 122 private static boolean sPreloadComplete; 123 preload(BootTimingsTraceLog bootTimingsTraceLog)124 static void preload(BootTimingsTraceLog bootTimingsTraceLog) { 125 Log.d(TAG, "begin preload"); 126 bootTimingsTraceLog.traceBegin("BeginIcuCachePinning"); 127 beginIcuCachePinning(); 128 bootTimingsTraceLog.traceEnd(); // BeginIcuCachePinning 129 bootTimingsTraceLog.traceBegin("PreloadClasses"); 130 preloadClasses(); 131 bootTimingsTraceLog.traceEnd(); // PreloadClasses 132 bootTimingsTraceLog.traceBegin("PreloadResources"); 133 preloadResources(); 134 bootTimingsTraceLog.traceEnd(); // PreloadResources 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 lazyPreload()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 beginIcuCachePinning()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 endIcuCachePinning()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 preloadSharedLibraries()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 preloadOpenGL()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 preloadTextResources()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 */ warmUpJcaProviders()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 */ preloadClasses()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 */ preloadResources()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 preloadColorStateLists(TypedArray ar)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 preloadDrawables(TypedArray ar)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 */ gcAndFinalize()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 */ handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs)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 // Capturing profiles is only supported for debug or eng builds since selinux normally 464 // prevents it. 465 boolean profileSystemServer = SystemProperties.getBoolean( 466 "dalvik.vm.profilesystemserver", false); 467 if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) { 468 try { 469 File profileDir = Environment.getDataProfilesDePackageDirectory( 470 Process.SYSTEM_UID, "system_server"); 471 File profile = new File(profileDir, "primary.prof"); 472 profile.getParentFile().mkdirs(); 473 profile.createNewFile(); 474 String[] codePaths = systemServerClasspath.split(":"); 475 VMRuntime.registerAppInfo(profile.getPath(), codePaths); 476 } catch (Exception e) { 477 Log.wtf(TAG, "Failed to set up system server profile", e); 478 } 479 } 480 } 481 482 if (parsedArgs.invokeWith != null) { 483 String[] args = parsedArgs.remainingArgs; 484 // If we have a non-null system server class path, we'll have to duplicate the 485 // existing arguments and append the classpath to it. ART will handle the classpath 486 // correctly when we exec a new process. 487 if (systemServerClasspath != null) { 488 String[] amendedArgs = new String[args.length + 2]; 489 amendedArgs[0] = "-cp"; 490 amendedArgs[1] = systemServerClasspath; 491 System.arraycopy(args, 0, amendedArgs, 2, args.length); 492 args = amendedArgs; 493 } 494 495 WrapperInit.execApplication(parsedArgs.invokeWith, 496 parsedArgs.niceName, parsedArgs.targetSdkVersion, 497 VMRuntime.getCurrentInstructionSet(), null, args); 498 } else { 499 ClassLoader cl = null; 500 if (systemServerClasspath != null) { 501 cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion); 502 503 Thread.currentThread().setContextClassLoader(cl); 504 } 505 506 /* 507 * Pass the remaining arguments to SystemServer. 508 */ 509 ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); 510 } 511 512 /* should never reach here */ 513 } 514 515 /** 516 * Creates a PathClassLoader for the given class path that is associated with a shared 517 * namespace, i.e., this classloader can access platform-private native libraries. The 518 * classloader will use java.library.path as the native library path. 519 */ createPathClassLoader(String classPath, int targetSdkVersion)520 static PathClassLoader createPathClassLoader(String classPath, int targetSdkVersion) { 521 String libraryPath = System.getProperty("java.library.path"); 522 523 return PathClassLoaderFactory.createClassLoader(classPath, 524 libraryPath, 525 libraryPath, 526 ClassLoader.getSystemClassLoader(), 527 targetSdkVersion, 528 true /* isNamespaceShared */); 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 */ performSystemServerDexOpt(String classPath)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 sharedLibraries = ""; 542 for (String classPathElement : classPathElements) { 543 // System server is fully AOTed and never profiled 544 // for profile guided compilation. 545 // TODO: Make this configurable between INTERPRET_ONLY, SPEED, SPACE and EVERYTHING? 546 547 int dexoptNeeded; 548 try { 549 dexoptNeeded = DexFile.getDexOptNeeded( 550 classPathElement, instructionSet, "speed", 551 false /* newProfile */); 552 } catch (FileNotFoundException ignored) { 553 // Do not add to the classpath. 554 Log.w(TAG, "Missing classpath element for system server: " + classPathElement); 555 continue; 556 } catch (IOException e) { 557 // Not fully clear what to do here as we don't know the cause of the 558 // IO exception. Add to the classpath to be conservative, but don't 559 // attempt to compile it. 560 Log.w(TAG, "Error checking classpath element for system server: " 561 + classPathElement, e); 562 dexoptNeeded = DexFile.NO_DEXOPT_NEEDED; 563 } 564 565 if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) { 566 final String packageName = "*"; 567 final String outputPath = null; 568 final int dexFlags = 0; 569 final String compilerFilter = "speed"; 570 final String uuid = StorageManager.UUID_PRIVATE_INTERNAL; 571 final String seInfo = null; 572 try { 573 installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName, 574 instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter, 575 uuid, sharedLibraries, seInfo); 576 } catch (RemoteException | ServiceSpecificException e) { 577 // Ignore (but log), we need this on the classpath for fallback mode. 578 Log.w(TAG, "Failed compiling classpath element for system server: " 579 + classPathElement, e); 580 } 581 } 582 583 if (!sharedLibraries.isEmpty()) { 584 sharedLibraries += ":"; 585 } 586 sharedLibraries += classPathElement; 587 } 588 } 589 590 /** 591 * Prepare the arguments and fork for the system server process. 592 */ startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)593 private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) 594 throws Zygote.MethodAndArgsCaller, RuntimeException { 595 long capabilities = posixCapabilitiesAsBits( 596 OsConstants.CAP_IPC_LOCK, 597 OsConstants.CAP_KILL, 598 OsConstants.CAP_NET_ADMIN, 599 OsConstants.CAP_NET_BIND_SERVICE, 600 OsConstants.CAP_NET_BROADCAST, 601 OsConstants.CAP_NET_RAW, 602 OsConstants.CAP_SYS_MODULE, 603 OsConstants.CAP_SYS_NICE, 604 OsConstants.CAP_SYS_PTRACE, 605 OsConstants.CAP_SYS_TIME, 606 OsConstants.CAP_SYS_TTY_CONFIG, 607 OsConstants.CAP_WAKE_ALARM 608 ); 609 /* Containers run without this capability, so avoid setting it in that case */ 610 if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) { 611 capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND); 612 } 613 /* Hardcoded command line to start the system server */ 614 String args[] = { 615 "--setuid=1000", 616 "--setgid=1000", 617 "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010", 618 "--capabilities=" + capabilities + "," + capabilities, 619 "--nice-name=system_server", 620 "--runtime-args", 621 "com.android.server.SystemServer", 622 }; 623 ZygoteConnection.Arguments parsedArgs = null; 624 625 int pid; 626 627 try { 628 parsedArgs = new ZygoteConnection.Arguments(args); 629 ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); 630 ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); 631 632 /* Request to fork the system server process */ 633 pid = Zygote.forkSystemServer( 634 parsedArgs.uid, parsedArgs.gid, 635 parsedArgs.gids, 636 parsedArgs.debugFlags, 637 null, 638 parsedArgs.permittedCapabilities, 639 parsedArgs.effectiveCapabilities); 640 } catch (IllegalArgumentException ex) { 641 throw new RuntimeException(ex); 642 } 643 644 /* For child process */ 645 if (pid == 0) { 646 if (hasSecondZygote(abiList)) { 647 waitForSecondaryZygote(socketName); 648 } 649 650 zygoteServer.closeServerSocket(); 651 handleSystemServerProcess(parsedArgs); 652 } 653 654 return true; 655 } 656 657 /** 658 * Gets the bit array representation of the provided list of POSIX capabilities. 659 */ posixCapabilitiesAsBits(int... capabilities)660 private static long posixCapabilitiesAsBits(int... capabilities) { 661 long result = 0; 662 for (int capability : capabilities) { 663 if ((capability < 0) || (capability > OsConstants.CAP_LAST_CAP)) { 664 throw new IllegalArgumentException(String.valueOf(capability)); 665 } 666 result |= (1L << capability); 667 } 668 return result; 669 } 670 main(String argv[])671 public static void main(String argv[]) { 672 ZygoteServer zygoteServer = new ZygoteServer(); 673 674 // Mark zygote start. This ensures that thread creation will throw 675 // an error. 676 ZygoteHooks.startZygoteNoThreadCreation(); 677 678 // Zygote goes into its own process group. 679 try { 680 Os.setpgid(0, 0); 681 } catch (ErrnoException ex) { 682 throw new RuntimeException("Failed to setpgid(0,0)", ex); 683 } 684 685 try { 686 // Report Zygote start time to tron unless it is a runtime restart 687 if (!"1".equals(SystemProperties.get("sys.boot_completed"))) { 688 MetricsLogger.histogram(null, "boot_zygote_init", 689 (int) SystemClock.elapsedRealtime()); 690 } 691 692 String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing"; 693 BootTimingsTraceLog bootTimingsTraceLog = new BootTimingsTraceLog(bootTimeTag, 694 Trace.TRACE_TAG_DALVIK); 695 bootTimingsTraceLog.traceBegin("ZygoteInit"); 696 RuntimeInit.enableDdms(); 697 // Start profiling the zygote initialization. 698 SamplingProfilerIntegration.start(); 699 700 boolean startSystemServer = false; 701 String socketName = "zygote"; 702 String abiList = null; 703 boolean enableLazyPreload = false; 704 for (int i = 1; i < argv.length; i++) { 705 if ("start-system-server".equals(argv[i])) { 706 startSystemServer = true; 707 } else if ("--enable-lazy-preload".equals(argv[i])) { 708 enableLazyPreload = true; 709 } else if (argv[i].startsWith(ABI_LIST_ARG)) { 710 abiList = argv[i].substring(ABI_LIST_ARG.length()); 711 } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { 712 socketName = argv[i].substring(SOCKET_NAME_ARG.length()); 713 } else { 714 throw new RuntimeException("Unknown command line argument: " + argv[i]); 715 } 716 } 717 718 if (abiList == null) { 719 throw new RuntimeException("No ABI list supplied."); 720 } 721 722 zygoteServer.registerServerSocket(socketName); 723 // In some configurations, we avoid preloading resources and classes eagerly. 724 // In such cases, we will preload things prior to our first fork. 725 if (!enableLazyPreload) { 726 bootTimingsTraceLog.traceBegin("ZygotePreload"); 727 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, 728 SystemClock.uptimeMillis()); 729 preload(bootTimingsTraceLog); 730 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, 731 SystemClock.uptimeMillis()); 732 bootTimingsTraceLog.traceEnd(); // ZygotePreload 733 } else { 734 Zygote.resetNicePriority(); 735 } 736 737 // Finish profiling the zygote initialization. 738 SamplingProfilerIntegration.writeZygoteSnapshot(); 739 740 // Do an initial gc to clean up after startup 741 bootTimingsTraceLog.traceBegin("PostZygoteInitGC"); 742 gcAndFinalize(); 743 bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC 744 745 bootTimingsTraceLog.traceEnd(); // ZygoteInit 746 // Disable tracing so that forked processes do not inherit stale tracing tags from 747 // Zygote. 748 Trace.setTracingEnabled(false); 749 750 // Zygote process unmounts root storage spaces. 751 Zygote.nativeUnmountStorageOnInit(); 752 753 // Set seccomp policy 754 Seccomp.setPolicy(); 755 756 ZygoteHooks.stopZygoteNoThreadCreation(); 757 758 if (startSystemServer) { 759 startSystemServer(abiList, socketName, zygoteServer); 760 } 761 762 Log.i(TAG, "Accepting command socket connections"); 763 zygoteServer.runSelectLoop(abiList); 764 765 zygoteServer.closeServerSocket(); 766 } catch (Zygote.MethodAndArgsCaller caller) { 767 caller.run(); 768 } catch (Throwable ex) { 769 Log.e(TAG, "System zygote died with exception", ex); 770 zygoteServer.closeServerSocket(); 771 throw ex; 772 } 773 } 774 775 /** 776 * Return {@code true} if this device configuration has another zygote. 777 * 778 * We determine this by comparing the device ABI list with this zygotes 779 * list. If this zygote supports all ABIs this device supports, there won't 780 * be another zygote. 781 */ hasSecondZygote(String abiList)782 private static boolean hasSecondZygote(String abiList) { 783 return !SystemProperties.get("ro.product.cpu.abilist").equals(abiList); 784 } 785 waitForSecondaryZygote(String socketName)786 private static void waitForSecondaryZygote(String socketName) { 787 String otherZygoteName = Process.ZYGOTE_SOCKET.equals(socketName) ? 788 Process.SECONDARY_ZYGOTE_SOCKET : Process.ZYGOTE_SOCKET; 789 while (true) { 790 try { 791 final ZygoteProcess.ZygoteState zs = 792 ZygoteProcess.ZygoteState.connect(otherZygoteName); 793 zs.close(); 794 break; 795 } catch (IOException ioe) { 796 Log.w(TAG, "Got error connecting to zygote, retrying. msg= " + ioe.getMessage()); 797 } 798 799 try { 800 Thread.sleep(1000); 801 } catch (InterruptedException ie) { 802 } 803 } 804 } 805 isPreloadComplete()806 static boolean isPreloadComplete() { 807 return sPreloadComplete; 808 } 809 810 /** 811 * Class not instantiable. 812 */ ZygoteInit()813 private ZygoteInit() { 814 } 815 816 /** 817 * The main function called when started through the zygote process. This 818 * could be unified with main(), if the native code in nativeFinishInit() 819 * were rationalized with Zygote startup.<p> 820 * 821 * Current recognized args: 822 * <ul> 823 * <li> <code> [--] <start class name> <args> 824 * </ul> 825 * 826 * @param targetSdkVersion target SDK version 827 * @param argv arg strings 828 */ zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)829 public static final void zygoteInit(int targetSdkVersion, String[] argv, 830 ClassLoader classLoader) throws Zygote.MethodAndArgsCaller { 831 if (RuntimeInit.DEBUG) { 832 Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote"); 833 } 834 835 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit"); 836 RuntimeInit.redirectLogStreams(); 837 838 RuntimeInit.commonInit(); 839 ZygoteInit.nativeZygoteInit(); 840 RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); 841 } 842 nativeZygoteInit()843 private static final native void nativeZygoteInit(); 844 } 845