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