1 /* 2 * Copyright (C) 2013 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.server; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.UserIdInt; 22 import android.app.ActivityManager; 23 import android.content.Context; 24 import android.content.pm.ApplicationInfo; 25 import android.content.pm.PackageInfo; 26 import android.content.pm.PackageManager; 27 import android.content.pm.UserInfo; 28 import android.os.Environment; 29 import android.os.SystemClock; 30 import android.os.Trace; 31 import android.os.UserHandle; 32 import android.util.ArraySet; 33 import android.util.Dumpable; 34 import android.util.EventLog; 35 import android.util.Slog; 36 import android.util.SparseArray; 37 38 import com.android.internal.annotations.GuardedBy; 39 import com.android.internal.os.SystemServerClassLoaderFactory; 40 import com.android.internal.util.Preconditions; 41 import com.android.server.SystemService.TargetUser; 42 import com.android.server.SystemService.UserCompletedEventType; 43 import com.android.server.am.EventLogTags; 44 import com.android.server.pm.ApexManager; 45 import com.android.server.pm.UserManagerInternal; 46 import com.android.server.utils.TimingsTraceAndSlog; 47 import com.android.tools.r8.keepanno.annotations.KeepTarget; 48 import com.android.tools.r8.keepanno.annotations.TypePattern; 49 import com.android.tools.r8.keepanno.annotations.UsesReflection; 50 51 import dalvik.system.PathClassLoader; 52 53 import java.io.File; 54 import java.io.PrintWriter; 55 import java.lang.reflect.Constructor; 56 import java.lang.reflect.InvocationTargetException; 57 import java.nio.file.Path; 58 import java.nio.file.Paths; 59 import java.util.ArrayList; 60 import java.util.Collections; 61 import java.util.List; 62 import java.util.Set; 63 import java.util.concurrent.ExecutorService; 64 import java.util.concurrent.Executors; 65 import java.util.concurrent.TimeUnit; 66 67 /** 68 * Manages creating, starting, and other lifecycle events of 69 * {@link com.android.server.SystemService system services}. 70 * 71 * {@hide} 72 */ 73 @android.ravenwood.annotation.RavenwoodKeepPartialClass 74 @android.ravenwood.annotation.RavenwoodKeepStaticInitializer 75 public final class SystemServiceManager implements Dumpable { 76 private static final String TAG = SystemServiceManager.class.getSimpleName(); 77 private static final boolean DEBUG = false; 78 private static final int SERVICE_CALL_WARN_TIME_MS = 50; 79 80 // Constants used on onUser(...) 81 // NOTE: do not change their values, as they're used on Trace calls and changes might break 82 // performance tests that rely on them. 83 private static final String USER_STARTING = "Start"; // Logged as onUserStarting() 84 private static final String USER_UNLOCKING = "Unlocking"; // Logged as onUserUnlocking() 85 private static final String USER_UNLOCKED = "Unlocked"; // Logged as onUserUnlocked() 86 private static final String USER_SWITCHING = "Switch"; // Logged as onUserSwitching() 87 private static final String USER_STOPPING = "Stop"; // Logged as onUserStopping() 88 private static final String USER_STOPPED = "Cleanup"; // Logged as onUserStopped() 89 private static final String USER_COMPLETED_EVENT = "CompletedEvent"; // onUserCompletedEvent() 90 91 // The default number of threads to use if lifecycle thread pool is enabled. 92 private static final int DEFAULT_MAX_USER_POOL_THREADS = 3; 93 // The number of threads to use if lifecycle thread pool is enabled, dependent on the number of 94 // available cores on the device. 95 private final int mNumUserPoolThreads; 96 // Maximum time to wait for a particular lifecycle phase to finish. 97 private static final long USER_POOL_SHUTDOWN_TIMEOUT_SECONDS = 30; 98 // Indirectly indicates how many services belong in the bootstrap and core service categories. 99 // This is used to decide which services the user lifecycle phases should be parallelized for. 100 private static volatile int sOtherServicesStartIndex; 101 102 private static File sSystemDir; 103 private final Context mContext; 104 private boolean mSafeMode; 105 private boolean mRuntimeRestarted; 106 private long mRuntimeStartElapsedTime; 107 private long mRuntimeStartUptime; 108 109 // Services that should receive lifecycle events. 110 private List<SystemService> mServices; 111 private Set<String> mServiceClassnames; 112 113 private int mCurrentPhase = -1; 114 115 private UserManagerInternal mUserManagerInternal; 116 117 /** 118 * Map of started {@link TargetUser TargetUsers} by user id; users are added on start and 119 * removed after they're completely shut down. 120 */ 121 @GuardedBy("mTargetUsers") 122 private final SparseArray<TargetUser> mTargetUsers = new SparseArray<>(); 123 124 /** 125 * Reference to the current user, it's used to set the {@link TargetUser} on 126 * {@link #onUserSwitching(int, int)} as the previous user might have been removed already. 127 */ 128 @GuardedBy("mTargetUsers") 129 @Nullable private TargetUser mCurrentUser; 130 131 @android.ravenwood.annotation.RavenwoodKeep SystemServiceManager(Context context)132 public SystemServiceManager(Context context) { 133 mContext = context; 134 mServices = new ArrayList<>(); 135 mServiceClassnames = new ArraySet<>(); 136 mNumUserPoolThreads = Math.min(Runtime.getRuntime().availableProcessors(), 137 DEFAULT_MAX_USER_POOL_THREADS); 138 } 139 140 /** 141 * Starts a service by class name from the current {@code SYSTEMSERVERCLASSPATH}. 142 * 143 * In general, this should only be used for services in the classpath that cannot 144 * be resolved by {@code services.jar} at build time, e.g., those defined in an apex jar from 145 * {@code PRODUCT_APEX_SYSTEM_SERVER_JARS} or a downstream jar in 146 * {@code PRODUCT_SYSTEM_SERVER_JARS}. Otherwise prefer the explicit type variant 147 * {@link #startService(Class)}. 148 * 149 * @return The service instance. 150 */ 151 @android.ravenwood.annotation.RavenwoodKeep startService(String className)152 public SystemService startService(String className) { 153 final Class<SystemService> serviceClass = loadClassFromLoader(className, 154 this.getClass().getClassLoader()); 155 return startService(serviceClass); 156 } 157 158 /** 159 * Starts a service by class name and standalone jar path where the service lives. 160 * 161 * In general, this should only be used for services in {@code STANDALONE_SYSTEMSERVER_JARS}, 162 * which in turn derives from {@code PRODUCT_STANDALONE_SYSTEM_SERVER_JARS} and 163 * {@code PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS}. 164 * 165 * @return The service instance. 166 */ startServiceFromJar(String className, String path)167 public SystemService startServiceFromJar(String className, String path) { 168 PathClassLoader pathClassLoader = 169 SystemServerClassLoaderFactory.getOrCreateClassLoader( 170 path, this.getClass().getClassLoader(), isJarInTestApex(path)); 171 final Class<SystemService> serviceClass = loadClassFromLoader(className, pathClassLoader); 172 return startService(serviceClass); 173 } 174 175 /** 176 * Returns true if the jar is in a test APEX. 177 */ isJarInTestApex(String pathStr)178 private boolean isJarInTestApex(String pathStr) { 179 Path path = Paths.get(pathStr); 180 if (path.getNameCount() >= 2 && path.getName(0).toString().equals("apex")) { 181 String apexModuleName = path.getName(1).toString(); 182 ApexManager apexManager = ApexManager.getInstance(); 183 String packageName = apexManager.getActivePackageNameForApexModuleName(apexModuleName); 184 try { 185 PackageInfo packageInfo = mContext.getPackageManager().getPackageInfo(packageName, 186 PackageManager.PackageInfoFlags.of(PackageManager.MATCH_APEX)); 187 return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_TEST_ONLY) != 0; 188 } catch (Exception ignore) { 189 } 190 } 191 return false; 192 } 193 194 /* 195 * Loads and initializes a class from the given classLoader. Returns the class. 196 */ 197 @SuppressWarnings("unchecked") 198 @android.ravenwood.annotation.RavenwoodKeep loadClassFromLoader(String className, ClassLoader classLoader)199 private static Class<SystemService> loadClassFromLoader(String className, 200 ClassLoader classLoader) { 201 try { 202 return (Class<SystemService>) Class.forName(className, true, classLoader); 203 } catch (ClassNotFoundException ex) { 204 throw new RuntimeException("Failed to create service " + className 205 + " from class loader " + classLoader.toString() + ": service class not " 206 + "found, usually indicates that the caller should " 207 + "have called PackageManager.hasSystemFeature() to check whether the " 208 + "feature is available on this device before trying to start the " 209 + "services that implement it. Also ensure that the correct path for the " 210 + "classloader is supplied, if applicable.", ex); 211 } 212 } 213 214 /** 215 * Creates and starts a system service. The class must be a subclass of 216 * {@link com.android.server.SystemService}. 217 * 218 * @param serviceClass A Java class that implements the SystemService interface. 219 * @return The service instance, never null. 220 * @throws RuntimeException if the service fails to start. 221 */ 222 @android.ravenwood.annotation.RavenwoodKeep 223 @UsesReflection( 224 @KeepTarget( 225 instanceOfClassConstantExclusive = SystemService.class, 226 methodName = "<init>", 227 methodParameterTypePatterns = {@TypePattern(constant = Context.class)})) startService(Class<T> serviceClass)228 public <T extends SystemService> T startService(Class<T> serviceClass) { 229 try { 230 final String name = serviceClass.getName(); 231 Slog.i(TAG, "Starting " + name); 232 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name); 233 234 // Create the service. 235 if (!SystemService.class.isAssignableFrom(serviceClass)) { 236 throw new RuntimeException("Failed to create " + name 237 + ": service must extend " + SystemService.class.getName()); 238 } 239 final T service; 240 try { 241 Constructor<T> constructor = serviceClass.getConstructor(Context.class); 242 service = constructor.newInstance(mContext); 243 } catch (InstantiationException ex) { 244 throw new RuntimeException("Failed to create service " + name 245 + ": service could not be instantiated", ex); 246 } catch (IllegalAccessException ex) { 247 throw new RuntimeException("Failed to create service " + name 248 + ": service must have a public constructor with a Context argument", ex); 249 } catch (NoSuchMethodException ex) { 250 throw new RuntimeException("Failed to create service " + name 251 + ": service must have a public constructor with a Context argument", ex); 252 } catch (InvocationTargetException ex) { 253 throw new RuntimeException("Failed to create service " + name 254 + ": service constructor threw an exception", ex); 255 } 256 257 startService(service); 258 return service; 259 } finally { 260 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); 261 } 262 } 263 264 @android.ravenwood.annotation.RavenwoodKeep startService(@onNull final SystemService service)265 public void startService(@NonNull final SystemService service) { 266 // Check if already started 267 String className = service.getClass().getName(); 268 if (mServiceClassnames.contains(className)) { 269 Slog.i(TAG, "Not starting an already started service " + className); 270 return; 271 } 272 mServiceClassnames.add(className); 273 274 // Register it. 275 mServices.add(service); 276 277 // Start it. 278 long time = SystemClock.elapsedRealtime(); 279 try { 280 service.onStart(); 281 } catch (RuntimeException ex) { 282 throw new RuntimeException("Failed to start service " + service.getClass().getName() 283 + ": onStart threw an exception", ex); 284 } 285 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart"); 286 } 287 288 /** Disallow starting new services after this call. */ 289 @android.ravenwood.annotation.RavenwoodKeep sealStartedServices()290 public void sealStartedServices() { 291 mServiceClassnames = Collections.emptySet(); 292 mServices = Collections.unmodifiableList(mServices); 293 } 294 295 /** 296 * Starts the specified boot phase for all system services that have been started up to 297 * this point. 298 * 299 * @param t trace logger 300 * @param phase The boot phase to start. 301 */ 302 @android.ravenwood.annotation.RavenwoodKeep startBootPhase(@onNull TimingsTraceAndSlog t, int phase)303 public void startBootPhase(@NonNull TimingsTraceAndSlog t, int phase) { 304 if (phase <= mCurrentPhase) { 305 throw new IllegalArgumentException("Next phase must be larger than previous"); 306 } 307 mCurrentPhase = phase; 308 309 Slog.i(TAG, "Starting phase " + mCurrentPhase); 310 try { 311 t.traceBegin("OnBootPhase_" + phase); 312 final int serviceLen = mServices.size(); 313 for (int i = 0; i < serviceLen; i++) { 314 final SystemService service = mServices.get(i); 315 long time = SystemClock.elapsedRealtime(); 316 t.traceBegin("OnBootPhase_" + phase + "_" + service.getClass().getName()); 317 try { 318 service.onBootPhase(mCurrentPhase); 319 } catch (Exception ex) { 320 throw new RuntimeException("Failed to boot service " 321 + service.getClass().getName() 322 + ": onBootPhase threw an exception during phase " 323 + mCurrentPhase, ex); 324 } 325 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onBootPhase"); 326 t.traceEnd(); 327 } 328 } finally { 329 t.traceEnd(); 330 } 331 332 if (phase == SystemService.PHASE_BOOT_COMPLETED) { 333 final long totalBootTime = SystemClock.uptimeMillis() - mRuntimeStartUptime; 334 t.logDuration("TotalBootTime", totalBootTime); 335 shutdownInitThreadPool(); 336 } 337 } 338 339 @android.ravenwood.annotation.RavenwoodReplace shutdownInitThreadPool()340 private void shutdownInitThreadPool() { 341 SystemServerInitThreadPool.shutdown(); 342 } 343 shutdownInitThreadPool$ravenwood()344 private void shutdownInitThreadPool$ravenwood() { 345 // Thread pool not configured yet on Ravenwood; ignored 346 } 347 348 /** 349 * @return true if system has completed the boot; false otherwise. 350 */ 351 @android.ravenwood.annotation.RavenwoodKeep isBootCompleted()352 public boolean isBootCompleted() { 353 return mCurrentPhase >= SystemService.PHASE_BOOT_COMPLETED; 354 } 355 356 /** 357 * Called from SystemServer to indicate that services in the other category are now starting. 358 * This is used to keep track of how many services are in the bootstrap and core service 359 * categories for the purposes of user lifecycle parallelization. 360 */ updateOtherServicesStartIndex()361 public void updateOtherServicesStartIndex() { 362 // Only update the index if the boot phase has not been completed yet 363 if (!isBootCompleted()) { 364 sOtherServicesStartIndex = mServices.size(); 365 } 366 } 367 368 /** 369 * Called at the beginning of {@code ActivityManagerService.systemReady()}. 370 */ preSystemReady()371 public void preSystemReady() { 372 mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); 373 } 374 getTargetUser(@serIdInt int userId)375 @Nullable private TargetUser getTargetUser(@UserIdInt int userId) { 376 synchronized (mTargetUsers) { 377 return mTargetUsers.get(userId); 378 } 379 } 380 newTargetUser(@serIdInt int userId)381 private @NonNull TargetUser newTargetUser(@UserIdInt int userId) { 382 final UserInfo userInfo = mUserManagerInternal.getUserInfo(userId); 383 Preconditions.checkState(userInfo != null, "No UserInfo for " + userId); 384 return new TargetUser(userInfo); 385 } 386 387 /** 388 * Starts the given user. 389 */ onUserStarting(@onNull TimingsTraceAndSlog t, @UserIdInt int userId)390 public void onUserStarting(@NonNull TimingsTraceAndSlog t, @UserIdInt int userId) { 391 final TargetUser targetUser = newTargetUser(userId); 392 synchronized (mTargetUsers) { 393 // On Automotive / Headless System User Mode, the system user will be started twice: 394 // - Once by some external or local service that switches the system user to 395 // the background. 396 // - Once by the ActivityManagerService, when the system is marked ready. 397 // These two events are not synchronized and the order of execution is 398 // non-deterministic. To avoid starting the system user twice, verify whether 399 // the system user has already been started by checking the mTargetUsers. 400 // TODO(b/242195409): this workaround shouldn't be necessary once we move 401 // the headless-user start logic to UserManager-land. 402 if (userId == UserHandle.USER_SYSTEM && mTargetUsers.contains(userId)) { 403 Slog.e(TAG, "Skipping starting system user twice"); 404 return; 405 } 406 mTargetUsers.put(userId, targetUser); 407 } 408 EventLog.writeEvent(EventLogTags.SSM_USER_STARTING, userId); 409 onUser(t, USER_STARTING, /* prevUser= */ null, targetUser); 410 } 411 412 /** 413 * Unlocks the given user. 414 */ onUserUnlocking(@serIdInt int userId)415 public void onUserUnlocking(@UserIdInt int userId) { 416 EventLog.writeEvent(EventLogTags.SSM_USER_UNLOCKING, userId); 417 onUser(USER_UNLOCKING, userId); 418 } 419 420 /** 421 * Called after the user was unlocked. 422 */ onUserUnlocked(@serIdInt int userId)423 public void onUserUnlocked(@UserIdInt int userId) { 424 EventLog.writeEvent(EventLogTags.SSM_USER_UNLOCKED, userId); 425 onUser(USER_UNLOCKED, userId); 426 } 427 428 /** 429 * Switches to the given user. 430 */ onUserSwitching(@serIdInt int from, @UserIdInt int to)431 public void onUserSwitching(@UserIdInt int from, @UserIdInt int to) { 432 EventLog.writeEvent(EventLogTags.SSM_USER_SWITCHING, from, to); 433 final TargetUser curUser, prevUser; 434 synchronized (mTargetUsers) { 435 if (mCurrentUser == null) { 436 if (DEBUG) { 437 Slog.d(TAG, "First user switch: from " + from + " to " + to); 438 } 439 prevUser = newTargetUser(from); 440 } else { 441 if (from != mCurrentUser.getUserIdentifier()) { 442 Slog.wtf(TAG, "switchUser(" + from + "," + to + "): mCurrentUser is " 443 + mCurrentUser + ", it should be " + from); 444 } 445 prevUser = mCurrentUser; 446 } 447 curUser = mCurrentUser = getTargetUser(to); 448 Preconditions.checkState(curUser != null, "No TargetUser for " + to); 449 if (DEBUG) { 450 Slog.d(TAG, "Set mCurrentUser to " + mCurrentUser); 451 } 452 } 453 onUser(TimingsTraceAndSlog.newAsyncLog(), USER_SWITCHING, prevUser, curUser); 454 } 455 456 /** 457 * Stops the given user. 458 */ onUserStopping(@serIdInt int userId)459 public void onUserStopping(@UserIdInt int userId) { 460 EventLog.writeEvent(EventLogTags.SSM_USER_STOPPING, userId); 461 onUser(USER_STOPPING, userId); 462 } 463 464 /** 465 * Cleans up the given user. 466 */ onUserStopped(@serIdInt int userId)467 public void onUserStopped(@UserIdInt int userId) { 468 EventLog.writeEvent(EventLogTags.SSM_USER_STOPPED, userId); 469 onUser(USER_STOPPED, userId); 470 471 // Remove cached TargetUser 472 synchronized (mTargetUsers) { 473 mTargetUsers.remove(userId); 474 } 475 } 476 477 /** 478 * Called some time <i>after</i> an onUser... event has completed, for the events delineated in 479 * {@link UserCompletedEventType}. 480 * 481 * @param eventFlags the events that completed, per {@link UserCompletedEventType}, or 0. 482 * @see SystemService#onUserCompletedEvent 483 */ onUserCompletedEvent(@serIdInt int userId, @UserCompletedEventType.EventTypesFlag int eventFlags)484 public void onUserCompletedEvent(@UserIdInt int userId, 485 @UserCompletedEventType.EventTypesFlag int eventFlags) { 486 EventLog.writeEvent(EventLogTags.SSM_USER_COMPLETED_EVENT, userId, eventFlags); 487 if (eventFlags == 0) { 488 return; 489 } 490 491 TargetUser targetUser = getTargetUser(userId); 492 if (targetUser == null) { 493 return; 494 } 495 496 onUser(TimingsTraceAndSlog.newAsyncLog(), 497 USER_COMPLETED_EVENT, 498 /* prevUser= */ null, 499 targetUser, 500 new UserCompletedEventType(eventFlags)); 501 } 502 onUser(@onNull String onWhat, @UserIdInt int userId)503 private void onUser(@NonNull String onWhat, @UserIdInt int userId) { 504 TargetUser targetUser = getTargetUser(userId); 505 Preconditions.checkState(targetUser != null, "No TargetUser for " + userId); 506 507 onUser(TimingsTraceAndSlog.newAsyncLog(), onWhat, /* prevUser= */ null, targetUser); 508 } 509 onUser(@onNull TimingsTraceAndSlog t, @NonNull String onWhat, @Nullable TargetUser prevUser, @NonNull TargetUser curUser)510 private void onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat, 511 @Nullable TargetUser prevUser, @NonNull TargetUser curUser) { 512 onUser(t, onWhat, prevUser, curUser, /* completedEventType= */ null); 513 } 514 onUser(@onNull TimingsTraceAndSlog t, @NonNull String onWhat, @Nullable TargetUser prevUser, @NonNull TargetUser curUser, @Nullable UserCompletedEventType completedEventType)515 private void onUser(@NonNull TimingsTraceAndSlog t, @NonNull String onWhat, 516 @Nullable TargetUser prevUser, @NonNull TargetUser curUser, 517 @Nullable UserCompletedEventType completedEventType) { 518 final int curUserId = curUser.getUserIdentifier(); 519 // NOTE: do not change label below, or it might break performance tests that rely on it. 520 t.traceBegin("ssm." + onWhat + "User-" + curUserId); 521 Slog.i(TAG, "Calling on" + onWhat + "User " + curUserId 522 + (prevUser != null ? " (from " + prevUser + ")" : "")); 523 524 final boolean useThreadPool = useThreadPool(curUserId, onWhat); 525 final ExecutorService threadPool = 526 useThreadPool ? Executors.newFixedThreadPool(mNumUserPoolThreads) : null; 527 528 final int serviceLen = mServices.size(); 529 for (int i = 0; i < serviceLen; i++) { 530 final SystemService service = mServices.get(i); 531 final String serviceName = service.getClass().getName(); 532 boolean supported = service.isUserSupported(curUser); 533 534 // Must check if either curUser or prevUser is supported (for example, if switching from 535 // unsupported to supported, we still need to notify the services) 536 if (!supported && prevUser != null) { 537 supported = service.isUserSupported(prevUser); 538 } 539 540 if (!supported) { 541 if (DEBUG) { 542 Slog.d(TAG, "Skipping " + onWhat + "User-" + curUserId + " on service " 543 + serviceName + " because it's not supported (curUser: " 544 + curUser + ", prevUser:" + prevUser + ")"); 545 } else { 546 Slog.i(TAG, "Skipping " + onWhat + "User-" + curUserId + " on " 547 + serviceName); 548 } 549 continue; 550 } 551 final boolean submitToThreadPool = useThreadPool && useThreadPoolForService(onWhat, i); 552 if (!submitToThreadPool) { 553 t.traceBegin("ssm.on" + onWhat + "User-" + curUserId + "_" + serviceName); 554 } 555 long time = SystemClock.elapsedRealtime(); 556 try { 557 switch (onWhat) { 558 case USER_SWITCHING: 559 service.onUserSwitching(prevUser, curUser); 560 break; 561 case USER_STARTING: 562 if (submitToThreadPool) { 563 threadPool.submit(getOnUserStartingRunnable(t, service, curUser)); 564 } else { 565 service.onUserStarting(curUser); 566 } 567 break; 568 case USER_UNLOCKING: 569 service.onUserUnlocking(curUser); 570 break; 571 case USER_UNLOCKED: 572 service.onUserUnlocked(curUser); 573 break; 574 case USER_STOPPING: 575 service.onUserStopping(curUser); 576 break; 577 case USER_STOPPED: 578 service.onUserStopped(curUser); 579 break; 580 case USER_COMPLETED_EVENT: 581 threadPool.submit(getOnUserCompletedEventRunnable( 582 t, service, serviceName, curUser, completedEventType)); 583 break; 584 default: 585 throw new IllegalArgumentException(onWhat + " what?"); 586 } 587 } catch (Exception ex) { 588 logFailure(onWhat, curUser, serviceName, ex); 589 } 590 if (!submitToThreadPool) { 591 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, 592 "on" + onWhat + "User-" + curUserId); 593 t.traceEnd(); // what on service 594 } 595 } 596 if (useThreadPool) { 597 boolean terminated = false; 598 threadPool.shutdown(); 599 try { 600 terminated = threadPool.awaitTermination( 601 USER_POOL_SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS); 602 } catch (InterruptedException e) { 603 logFailure(onWhat, curUser, "(user lifecycle threadpool was interrupted)", e); 604 } 605 if (!terminated) { 606 logFailure(onWhat, curUser, "(user lifecycle threadpool was not terminated)", null); 607 } 608 } 609 t.traceEnd(); // main entry 610 } 611 612 /** 613 * Whether the given onWhat should use a thread pool. 614 * IMPORTANT: changing the logic to return true won't necessarily make it multi-threaded. 615 * There needs to be a corresponding logic change in onUser() to actually submit 616 * to a threadPool for the given onWhat. 617 */ useThreadPool(int userId, @NonNull String onWhat)618 private boolean useThreadPool(int userId, @NonNull String onWhat) { 619 switch (onWhat) { 620 case USER_STARTING: 621 // Don't allow lifecycle parallelization for user start on low ram devices and 622 // the system user. 623 return !ActivityManager.isLowRamDeviceStatic() && userId != UserHandle.USER_SYSTEM; 624 case USER_COMPLETED_EVENT: 625 return true; 626 default: 627 return false; 628 } 629 } 630 useThreadPoolForService(@onNull String onWhat, int serviceIndex)631 private boolean useThreadPoolForService(@NonNull String onWhat, int serviceIndex) { 632 switch (onWhat) { 633 case USER_STARTING: 634 // Only submit this service to the thread pool if it's in the "other" category. 635 return serviceIndex >= sOtherServicesStartIndex; 636 case USER_COMPLETED_EVENT: 637 return true; 638 default: 639 return false; 640 } 641 } 642 getOnUserStartingRunnable(TimingsTraceAndSlog oldTrace, SystemService service, TargetUser curUser)643 private Runnable getOnUserStartingRunnable(TimingsTraceAndSlog oldTrace, SystemService service, 644 TargetUser curUser) { 645 return () -> { 646 final TimingsTraceAndSlog t = new TimingsTraceAndSlog(oldTrace); 647 final String serviceName = service.getClass().getName(); 648 final int curUserId = curUser.getUserIdentifier(); 649 t.traceBegin("ssm.on" + USER_STARTING + "User-" + curUserId + "_" + serviceName); 650 try { 651 long time = SystemClock.elapsedRealtime(); 652 service.onUserStarting(curUser); 653 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, 654 "on" + USER_STARTING + "User-" + curUserId); 655 } catch (Exception e) { 656 logFailure(USER_STARTING, curUser, serviceName, e); 657 } finally { 658 t.traceEnd(); 659 } 660 }; 661 } 662 getOnUserCompletedEventRunnable(TimingsTraceAndSlog oldTrace, SystemService service, String serviceName, TargetUser curUser, UserCompletedEventType eventType)663 private Runnable getOnUserCompletedEventRunnable(TimingsTraceAndSlog oldTrace, 664 SystemService service, String serviceName, TargetUser curUser, 665 UserCompletedEventType eventType) { 666 return () -> { 667 final TimingsTraceAndSlog t = new TimingsTraceAndSlog(oldTrace); 668 final int curUserId = curUser.getUserIdentifier(); 669 t.traceBegin("ssm.on" + USER_COMPLETED_EVENT + "User-" + curUserId 670 + "_" + eventType + "_" + serviceName); 671 try { 672 long time = SystemClock.elapsedRealtime(); 673 service.onUserCompletedEvent(curUser, eventType); 674 warnIfTooLong(SystemClock.elapsedRealtime() - time, service, 675 "on" + USER_COMPLETED_EVENT + "User-" + curUserId); 676 } catch (Exception e) { 677 logFailure(USER_COMPLETED_EVENT, curUser, serviceName, e); 678 throw e; 679 } finally { 680 t.traceEnd(); 681 } 682 }; 683 } 684 685 /** Logs the failure. That's all. Tests may rely on parsing it, so only modify carefully. */ 686 @android.ravenwood.annotation.RavenwoodKeep 687 private void logFailure(String onWhat, TargetUser curUser, String serviceName, Exception ex) { 688 Slog.wtf(TAG, "SystemService failure: Failure reporting " + onWhat + " of user " 689 + curUser + " to service " + serviceName, ex); 690 } 691 692 /** Sets the safe mode flag for services to query. */ 693 @android.ravenwood.annotation.RavenwoodKeep 694 void setSafeMode(boolean safeMode) { 695 mSafeMode = safeMode; 696 } 697 698 /** 699 * Returns whether we are booting into safe mode. 700 * 701 * @return safe mode flag 702 */ 703 @android.ravenwood.annotation.RavenwoodKeep 704 public boolean isSafeMode() { 705 return mSafeMode; 706 } 707 708 /** 709 * @return true if runtime was restarted, false if it's normal boot 710 */ 711 @android.ravenwood.annotation.RavenwoodKeep 712 public boolean isRuntimeRestarted() { 713 return mRuntimeRestarted; 714 } 715 716 /** 717 * @return Time when SystemServer was started, in elapsed realtime. 718 */ 719 @android.ravenwood.annotation.RavenwoodKeep 720 public long getRuntimeStartElapsedTime() { 721 return mRuntimeStartElapsedTime; 722 } 723 724 /** 725 * @return Time when SystemServer was started, in uptime. 726 */ 727 @android.ravenwood.annotation.RavenwoodKeep 728 public long getRuntimeStartUptime() { 729 return mRuntimeStartUptime; 730 } 731 732 @android.ravenwood.annotation.RavenwoodKeep 733 public void setStartInfo(boolean runtimeRestarted, 734 long runtimeStartElapsedTime, long runtimeStartUptime) { 735 mRuntimeRestarted = runtimeRestarted; 736 mRuntimeStartElapsedTime = runtimeStartElapsedTime; 737 mRuntimeStartUptime = runtimeStartUptime; 738 } 739 740 @android.ravenwood.annotation.RavenwoodKeep 741 private void warnIfTooLong(long duration, SystemService service, String operation) { 742 if (duration > SERVICE_CALL_WARN_TIME_MS) { 743 Slog.w(TAG, "Service " + service.getClass().getName() + " took " + duration + " ms in " 744 + operation); 745 } 746 } 747 748 /** 749 * Ensures that the system directory exist creating one if needed. 750 * 751 * @return The system directory. 752 * @deprecated Use {@link Environment#getDataSystemCeDirectory()} 753 * or {@link Environment#getDataSystemDeDirectory()} instead. 754 */ 755 @Deprecated 756 public static File ensureSystemDir() { 757 if (sSystemDir == null) { 758 File dataDir = Environment.getDataDirectory(); 759 sSystemDir = new File(dataDir, "system"); 760 sSystemDir.mkdirs(); 761 } 762 return sSystemDir; 763 } 764 765 @Override 766 public String getDumpableName() { 767 return SystemServiceManager.class.getSimpleName(); 768 } 769 770 @Override 771 public void dump(PrintWriter pw, String[] args) { 772 pw.printf("Current phase: %d\n", mCurrentPhase); 773 synchronized (mTargetUsers) { 774 if (mCurrentUser != null) { 775 pw.print("Current user: "); 776 mCurrentUser.dump(pw); 777 pw.println(); 778 } else { 779 pw.println("Current user not set!"); 780 } 781 782 final int targetUsersSize = mTargetUsers.size(); 783 if (targetUsersSize > 0) { 784 pw.printf("%d target users: ", targetUsersSize); 785 for (int i = 0; i < targetUsersSize; i++) { 786 mTargetUsers.valueAt(i).dump(pw); 787 if (i != targetUsersSize - 1) pw.print(", "); 788 } 789 pw.println(); 790 } else { 791 pw.println("No target users"); 792 } 793 } 794 final int startedLen = mServices.size(); 795 String prefix = " "; 796 if (startedLen > 0) { 797 pw.printf("%d started services:\n", startedLen); 798 for (int i = 0; i < startedLen; i++) { 799 final SystemService service = mServices.get(i); 800 pw.print(prefix); pw.println(service.getClass().getCanonicalName()); 801 } 802 } else { 803 pw.println("No started services"); 804 } 805 } 806 } 807