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