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