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