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