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