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