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