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