1 /* 2 * Copyright (C) 2018 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 package com.android.server.infra; 17 18 import android.annotation.IntDef; 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.UserIdInt; 22 import android.app.ActivityManager; 23 import android.content.ComponentName; 24 import android.content.ContentResolver; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.pm.UserInfo; 28 import android.database.ContentObserver; 29 import android.net.Uri; 30 import android.os.Binder; 31 import android.os.Handler; 32 import android.os.UserHandle; 33 import android.os.UserManager; 34 import android.provider.Settings; 35 import android.util.Slog; 36 import android.util.SparseArray; 37 import android.util.SparseBooleanArray; 38 39 import com.android.internal.annotations.GuardedBy; 40 import com.android.internal.content.PackageMonitor; 41 import com.android.internal.infra.AbstractRemoteService; 42 import com.android.internal.os.BackgroundThread; 43 import com.android.server.LocalServices; 44 import com.android.server.SystemService; 45 import com.android.server.pm.UserManagerInternal; 46 47 import java.io.PrintWriter; 48 import java.lang.annotation.Retention; 49 import java.lang.annotation.RetentionPolicy; 50 import java.util.ArrayList; 51 import java.util.Arrays; 52 import java.util.List; 53 import java.util.Objects; 54 55 /** 56 * Base class for {@link SystemService SystemServices} that support multi user. 57 * 58 * <p>Subclasses of this service are just a facade for the service binder calls - the "real" work 59 * is done by the {@link AbstractPerUserSystemService} subclasses, which are automatically managed 60 * through an user -> service cache. 61 * 62 * <p>It also takes care of other plumbing tasks such as: 63 * 64 * <ul> 65 * <li>Disabling the service when {@link UserManager} restrictions change. 66 * <li>Refreshing the service when its underlying 67 * {@link #getServiceSettingsProperty() Settings property} changed. 68 * <li>Calling the service when other Settings properties changed. 69 * </ul> 70 * 71 * <p>See {@code com.android.server.autofill.AutofillManagerService} for a concrete 72 * (no pun intended) example of how to use it. 73 * 74 * @param <M> "main" service class. 75 * @param <S> "real" service class. 76 * 77 * @hide 78 */ 79 // TODO(b/117779333): improve javadoc above instead of using Autofill as an example 80 public abstract class AbstractMasterSystemService<M extends AbstractMasterSystemService<M, S>, 81 S extends AbstractPerUserSystemService<S, M>> extends SystemService { 82 83 /** On a package update, does not refresh the per-user service in the cache. */ 84 public static final int PACKAGE_UPDATE_POLICY_NO_REFRESH = 0x00000001; 85 86 /** 87 * On a package update, removes any existing per-user services in the cache. 88 * 89 * <p>This does not immediately recreate these services. It is assumed they will be recreated 90 * for the next user request. 91 */ 92 public static final int PACKAGE_UPDATE_POLICY_REFRESH_LAZY = 0x00000002; 93 94 /** 95 * On a package update, removes and recreates any existing per-user services in the cache. 96 */ 97 public static final int PACKAGE_UPDATE_POLICY_REFRESH_EAGER = 0x00000004; 98 99 /** On a package restart, does not refresh the per-user service in the cache. */ 100 public static final int PACKAGE_RESTART_POLICY_NO_REFRESH = 0x00000010; 101 102 /** 103 * On a package restart, removes any existing per-user services in the cache. 104 * 105 * <p>This does not immediately recreate these services. It is assumed they will be recreated 106 * for the next user request. 107 */ 108 public static final int PACKAGE_RESTART_POLICY_REFRESH_LAZY = 0x00000020; 109 110 /** 111 * On a package restart, removes and recreates any existing per-user services in the cache. 112 */ 113 public static final int PACKAGE_RESTART_POLICY_REFRESH_EAGER = 0x00000040; 114 115 @IntDef(flag = true, prefix = { "PACKAGE_" }, value = { 116 PACKAGE_UPDATE_POLICY_NO_REFRESH, 117 PACKAGE_UPDATE_POLICY_REFRESH_LAZY, 118 PACKAGE_UPDATE_POLICY_REFRESH_EAGER, 119 PACKAGE_RESTART_POLICY_NO_REFRESH, 120 PACKAGE_RESTART_POLICY_REFRESH_LAZY, 121 PACKAGE_RESTART_POLICY_REFRESH_EAGER 122 }) 123 124 @Retention(RetentionPolicy.SOURCE) 125 public @interface ServicePackagePolicyFlags {} 126 127 /** 128 * Log tag 129 */ 130 protected final String mTag = getClass().getSimpleName(); 131 132 /** 133 * Lock used to synchronize access to internal state; should be acquired before calling a 134 * method whose name ends with {@code locked}. 135 */ 136 protected final Object mLock = new Object(); 137 138 /** 139 * Object used to define the name of the service component used to create 140 * {@link com.android.internal.infra.AbstractRemoteService} instances. 141 */ 142 @Nullable 143 protected final ServiceNameResolver mServiceNameResolver; 144 145 /** 146 * Whether the service should log debug statements. 147 */ 148 //TODO(b/117779333): consider using constants for these guards 149 public boolean verbose = false; 150 151 /** 152 * Whether the service should log verbose statements. 153 */ 154 //TODO(b/117779333): consider using constants for these guards 155 public boolean debug = false; 156 157 /** 158 * Whether the service is allowed to bind to an instant-app. 159 */ 160 @GuardedBy("mLock") 161 protected boolean mAllowInstantService; 162 163 /** 164 * Users disabled due to {@link UserManager} restrictions, or {@code null} if the service cannot 165 * be disabled through {@link UserManager}. 166 */ 167 @GuardedBy("mLock") 168 @Nullable 169 private final SparseBooleanArray mDisabledByUserRestriction; 170 171 /** 172 * Cache of service list per user id. 173 */ 174 @GuardedBy("mLock") 175 private final SparseArray<List<S>> mServicesCacheList = new SparseArray<>(); 176 177 /** 178 * Value that determines whether the per-user service should be removed from the cache when its 179 * apk is updated or restarted. 180 */ 181 private final @ServicePackagePolicyFlags int mServicePackagePolicyFlags; 182 183 /** 184 * Name of the service packages whose APK are being updated, keyed by user id. 185 */ 186 @GuardedBy("mLock") 187 private SparseArray<String> mUpdatingPackageNames; 188 189 /** 190 * Lazy-loadable reference to {@link UserManagerInternal}. 191 */ 192 @Nullable 193 private UserManagerInternal mUm; 194 195 /** 196 * Default constructor. 197 * 198 * <p>When using this constructor, the {@link AbstractPerUserSystemService} is removed from 199 * the cache (and re-added) when the service package is updated. 200 * 201 * @param context system context. 202 * @param serviceNameResolver resolver for 203 * {@link com.android.internal.infra.AbstractRemoteService} instances, or 204 * {@code null} when the service doesn't bind to remote services. 205 * @param disallowProperty when not {@code null}, defines a {@link UserManager} restriction that 206 * disables the service. <b>NOTE: </b> you'll also need to add it to 207 * {@code UserRestrictionsUtils.USER_RESTRICTIONS}. 208 */ AbstractMasterSystemService(@onNull Context context, @Nullable ServiceNameResolver serviceNameResolver, @Nullable String disallowProperty)209 protected AbstractMasterSystemService(@NonNull Context context, 210 @Nullable ServiceNameResolver serviceNameResolver, 211 @Nullable String disallowProperty) { 212 this(context, serviceNameResolver, disallowProperty, 213 PACKAGE_UPDATE_POLICY_REFRESH_LAZY | PACKAGE_RESTART_POLICY_REFRESH_LAZY); 214 } 215 216 /** 217 * Full Constructor. 218 * 219 * @param context system context. 220 * @param serviceNameResolver resolver for 221 * {@link com.android.internal.infra.AbstractRemoteService} instances, or 222 * {@code null} when the service doesn't bind to remote services. 223 * @param disallowProperty when not {@code null}, defines a {@link UserManager} restriction that 224 * disables the service. <b>NOTE: </b> you'll also need to add it to 225 * {@code UserRestrictionsUtils.USER_RESTRICTIONS}. 226 * @param servicePackagePolicyFlags a combination of 227 * {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH}, 228 * {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY}, 229 * {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}, 230 * {@link #PACKAGE_RESTART_POLICY_NO_REFRESH}, 231 * {@link #PACKAGE_RESTART_POLICY_REFRESH_LAZY} or 232 * {@link #PACKAGE_RESTART_POLICY_REFRESH_EAGER} 233 */ AbstractMasterSystemService(@onNull Context context, @Nullable ServiceNameResolver serviceNameResolver, @Nullable String disallowProperty, @ServicePackagePolicyFlags int servicePackagePolicyFlags)234 protected AbstractMasterSystemService(@NonNull Context context, 235 @Nullable ServiceNameResolver serviceNameResolver, @Nullable String disallowProperty, 236 @ServicePackagePolicyFlags int servicePackagePolicyFlags) { 237 super(context); 238 239 final int updatePolicyMask = PACKAGE_UPDATE_POLICY_NO_REFRESH 240 | PACKAGE_UPDATE_POLICY_REFRESH_LAZY | PACKAGE_UPDATE_POLICY_REFRESH_EAGER; 241 if ((servicePackagePolicyFlags & updatePolicyMask) == 0) { 242 // If the package update policy is not set, add the default flag 243 servicePackagePolicyFlags |= PACKAGE_UPDATE_POLICY_REFRESH_LAZY; 244 } 245 final int restartPolicyMask = PACKAGE_RESTART_POLICY_NO_REFRESH 246 | PACKAGE_RESTART_POLICY_REFRESH_LAZY | PACKAGE_RESTART_POLICY_REFRESH_EAGER; 247 if ((servicePackagePolicyFlags & restartPolicyMask) == 0) { 248 // If the package restart policy is not set, add the default flag 249 servicePackagePolicyFlags |= PACKAGE_RESTART_POLICY_REFRESH_LAZY; 250 } 251 mServicePackagePolicyFlags = servicePackagePolicyFlags; 252 253 mServiceNameResolver = serviceNameResolver; 254 if (mServiceNameResolver != null) { 255 mServiceNameResolver.setOnTemporaryServiceNameChangedCallback( 256 this::onServiceNameChanged); 257 } 258 if (disallowProperty == null) { 259 mDisabledByUserRestriction = null; 260 } else { 261 mDisabledByUserRestriction = new SparseBooleanArray(); 262 // Hookup with UserManager to disable service when necessary. 263 final UserManagerInternal umi = getUserManagerInternal(); 264 final List<UserInfo> users = getSupportedUsers(); 265 for (int i = 0; i < users.size(); i++) { 266 final int userId = users.get(i).id; 267 final boolean disabled = umi.getUserRestriction(userId, disallowProperty); 268 if (disabled) { 269 Slog.i(mTag, "Disabling by restrictions user " + userId); 270 mDisabledByUserRestriction.put(userId, disabled); 271 } 272 } 273 umi.addUserRestrictionsListener((userId, newRestrictions, prevRestrictions) -> { 274 final boolean disabledNow = 275 newRestrictions.getBoolean(disallowProperty, false); 276 synchronized (mLock) { 277 final boolean disabledBefore = mDisabledByUserRestriction.get(userId); 278 if (disabledBefore == disabledNow) { 279 // Nothing changed, do nothing. 280 if (debug) { 281 Slog.d(mTag, "Restriction did not change for user " + userId); 282 return; 283 } 284 } 285 Slog.i(mTag, "Updating for user " + userId + ": disabled=" + disabledNow); 286 mDisabledByUserRestriction.put(userId, disabledNow); 287 updateCachedServiceLocked(userId, disabledNow); 288 } 289 }); 290 } 291 startTrackingPackageChanges(); 292 } 293 294 @Override // from SystemService onBootPhase(int phase)295 public void onBootPhase(int phase) { 296 if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { 297 new SettingsObserver(BackgroundThread.getHandler()); 298 } 299 } 300 301 @Override // from SystemService onUserUnlocking(@onNull TargetUser user)302 public void onUserUnlocking(@NonNull TargetUser user) { 303 synchronized (mLock) { 304 updateCachedServiceLocked(user.getUserIdentifier()); 305 } 306 } 307 308 @Override // from SystemService onUserStopped(@onNull TargetUser user)309 public void onUserStopped(@NonNull TargetUser user) { 310 synchronized (mLock) { 311 removeCachedServiceListLocked(user.getUserIdentifier()); 312 } 313 } 314 315 /** 316 * Gets whether the service is allowed to bind to an instant-app. 317 * 318 * <p>Typically called by {@code ShellCommand} during CTS tests. 319 * 320 * @throws SecurityException if caller is not allowed to manage this service's settings. 321 */ getAllowInstantService()322 public final boolean getAllowInstantService() { 323 enforceCallingPermissionForManagement(); 324 synchronized (mLock) { 325 return mAllowInstantService; 326 } 327 } 328 329 /** 330 * Checks whether the service is allowed to bind to an instant-app. 331 * 332 * <p>Typically called by subclasses when creating {@link AbstractRemoteService} instances. 333 * 334 * <p><b>NOTE: </b>must not be called by {@code ShellCommand} as it does not check for 335 * permission. 336 */ isBindInstantServiceAllowed()337 public final boolean isBindInstantServiceAllowed() { 338 synchronized (mLock) { 339 return mAllowInstantService; 340 } 341 } 342 343 /** 344 * Sets whether the service is allowed to bind to an instant-app. 345 * 346 * <p>Typically called by {@code ShellCommand} during CTS tests. 347 * 348 * @throws SecurityException if caller is not allowed to manage this service's settings. 349 */ setAllowInstantService(boolean mode)350 public final void setAllowInstantService(boolean mode) { 351 Slog.i(mTag, "setAllowInstantService(): " + mode); 352 enforceCallingPermissionForManagement(); 353 synchronized (mLock) { 354 mAllowInstantService = mode; 355 } 356 } 357 358 /** 359 * Temporarily sets the service implementation. 360 * 361 * <p>Typically used by Shell command and/or CTS tests. 362 * 363 * @param componentName name of the new component 364 * @param durationMs how long the change will be valid (the service will be automatically reset 365 * to the default component after this timeout expires). 366 * @throws SecurityException if caller is not allowed to manage this service's settings. 367 * @throws IllegalArgumentException if value of {@code durationMs} is higher than 368 * {@link #getMaximumTemporaryServiceDurationMs()}. 369 */ setTemporaryService(@serIdInt int userId, @NonNull String componentName, int durationMs)370 public final void setTemporaryService(@UserIdInt int userId, @NonNull String componentName, 371 int durationMs) { 372 Slog.i(mTag, "setTemporaryService(" + userId + ") to " + componentName + " for " 373 + durationMs + "ms"); 374 if (mServiceNameResolver == null) { 375 return; 376 } 377 enforceCallingPermissionForManagement(); 378 379 Objects.requireNonNull(componentName); 380 final int maxDurationMs = getMaximumTemporaryServiceDurationMs(); 381 if (durationMs > maxDurationMs) { 382 throw new IllegalArgumentException( 383 "Max duration is " + maxDurationMs + " (called with " + durationMs + ")"); 384 } 385 386 synchronized (mLock) { 387 final S oldService = peekServiceForUserLocked(userId); 388 if (oldService != null) { 389 oldService.removeSelfFromCache(); 390 } 391 mServiceNameResolver.setTemporaryService(userId, componentName, durationMs); 392 } 393 } 394 395 /** 396 * Temporarily sets the service implementation. 397 * 398 * <p>Typically used by Shell command and/or CTS tests. 399 * 400 * @param componentNames list of the names of the new component 401 * @param durationMs how long the change will be valid (the service will be automatically 402 * reset 403 * to the default component after this timeout expires). 404 * @throws SecurityException if caller is not allowed to manage this service's settings. 405 * @throws IllegalArgumentException if value of {@code durationMs} is higher than 406 * {@link #getMaximumTemporaryServiceDurationMs()}. 407 */ setTemporaryServices(@serIdInt int userId, @NonNull String[] componentNames, int durationMs)408 public final void setTemporaryServices(@UserIdInt int userId, @NonNull String[] componentNames, 409 int durationMs) { 410 Slog.i(mTag, "setTemporaryService(" + userId + ") to " + Arrays.toString(componentNames) 411 + " for " + durationMs + "ms"); 412 if (mServiceNameResolver == null) { 413 return; 414 } 415 enforceCallingPermissionForManagement(); 416 417 Objects.requireNonNull(componentNames); 418 final int maxDurationMs = getMaximumTemporaryServiceDurationMs(); 419 if (durationMs > maxDurationMs) { 420 throw new IllegalArgumentException( 421 "Max duration is " + maxDurationMs + " (called with " + durationMs + ")"); 422 } 423 424 synchronized (mLock) { 425 final S oldService = peekServiceForUserLocked(userId); 426 if (oldService != null) { 427 oldService.removeSelfFromCache(); 428 } 429 mServiceNameResolver.setTemporaryServices(userId, componentNames, durationMs); 430 } 431 } 432 433 /** 434 * Sets whether the default service should be used. 435 * 436 * <p>Typically used during CTS tests to make sure only the default service doesn't interfere 437 * with the test results. 438 * 439 * @return whether the enabled state changed. 440 * @throws SecurityException if caller is not allowed to manage this service's settings. 441 */ setDefaultServiceEnabled(@serIdInt int userId, boolean enabled)442 public final boolean setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) { 443 Slog.i(mTag, "setDefaultServiceEnabled() for userId " + userId + ": " + enabled); 444 enforceCallingPermissionForManagement(); 445 446 synchronized (mLock) { 447 if (mServiceNameResolver == null) { 448 return false; 449 } 450 final boolean changed = mServiceNameResolver.setDefaultServiceEnabled(userId, enabled); 451 if (!changed) { 452 if (verbose) { 453 Slog.v(mTag, "setDefaultServiceEnabled(" + userId + "): already " + enabled); 454 } 455 return false; 456 } 457 458 final S oldService = peekServiceForUserLocked(userId); 459 if (oldService != null) { 460 oldService.removeSelfFromCache(); 461 } 462 463 // Must update the service on cache so its initialization code is triggered 464 updateCachedServiceLocked(userId); 465 } 466 return true; 467 } 468 469 /** 470 * Checks whether the default service should be used. 471 * 472 * <p>Typically used during CTS tests to make sure only the default service doesn't interfere 473 * with the test results. 474 * 475 * @throws SecurityException if caller is not allowed to manage this service's settings. 476 */ isDefaultServiceEnabled(@serIdInt int userId)477 public final boolean isDefaultServiceEnabled(@UserIdInt int userId) { 478 enforceCallingPermissionForManagement(); 479 480 if (mServiceNameResolver == null) { 481 return false; 482 } 483 484 synchronized (mLock) { 485 return mServiceNameResolver.isDefaultServiceEnabled(userId); 486 } 487 } 488 489 /** 490 * Gets the maximum time the service implementation can be changed. 491 * 492 * @throws UnsupportedOperationException if subclass doesn't override it. 493 */ getMaximumTemporaryServiceDurationMs()494 protected int getMaximumTemporaryServiceDurationMs() { 495 throw new UnsupportedOperationException("Not implemented by " + getClass()); 496 } 497 498 /** 499 * Resets the temporary service implementation to the default component. 500 * 501 * <p>Typically used by Shell command and/or CTS tests. 502 * 503 * @throws SecurityException if caller is not allowed to manage this service's settings. 504 */ resetTemporaryService(@serIdInt int userId)505 public final void resetTemporaryService(@UserIdInt int userId) { 506 Slog.i(mTag, "resetTemporaryService(): " + userId); 507 enforceCallingPermissionForManagement(); 508 synchronized (mLock) { 509 final S service = getServiceForUserLocked(userId); 510 if (service != null) { 511 service.resetTemporaryServiceLocked(); 512 } 513 } 514 } 515 516 /** 517 * Asserts that the caller has permissions to manage this service. 518 * 519 * <p>Typically called by {@code ShellCommand} implementations. 520 * 521 * @throws UnsupportedOperationException if subclass doesn't override it. 522 * @throws SecurityException if caller is not allowed to manage this service's settings. 523 */ enforceCallingPermissionForManagement()524 protected void enforceCallingPermissionForManagement() { 525 throw new UnsupportedOperationException("Not implemented by " + getClass()); 526 } 527 528 /** 529 * Creates a new service that will be added to the cache. 530 * 531 * @param resolvedUserId the resolved user id for the service. 532 * @param disabled whether the service is currently disabled (due to {@link UserManager} 533 * restrictions). 534 * 535 * @return a new instance. 536 */ 537 @Nullable newServiceLocked(@serIdInt int resolvedUserId, boolean disabled)538 protected abstract S newServiceLocked(@UserIdInt int resolvedUserId, boolean disabled); 539 540 /** 541 * Creates a new service list that will be added to the cache. 542 * 543 * @param resolvedUserId the resolved user id for the service. 544 * @param disabled whether the service is currently disabled (due to {@link UserManager} 545 * restrictions). 546 * @return a new instance. 547 */ 548 @Nullable 549 @GuardedBy("mLock") newServiceListLocked(@serIdInt int resolvedUserId, boolean disabled, String[] serviceNames)550 protected List<S> newServiceListLocked(@UserIdInt int resolvedUserId, boolean disabled, 551 String[] serviceNames) { 552 throw new UnsupportedOperationException("newServiceListLocked not implemented. "); 553 } 554 555 /** 556 * Register the service for extra Settings changes (i.e., other than 557 * {@link android.provider.Settings.Secure#USER_SETUP_COMPLETE} or 558 * {@link #getServiceSettingsProperty()}, which are automatically handled). 559 * 560 * <p> Example: 561 * 562 * <pre><code> 563 * resolver.registerContentObserver(Settings.Global.getUriFor( 564 * Settings.Global.AUTOFILL_LOGGING_LEVEL), false, observer, 565 * UserHandle.USER_ALL); 566 * </code></pre> 567 * 568 * <p><b>NOTE: </p>it doesn't need to register for 569 * {@link android.provider.Settings.Secure#USER_SETUP_COMPLETE} or 570 * {@link #getServiceSettingsProperty()}. 571 */ 572 @SuppressWarnings("unused") registerForExtraSettingsChanges(@onNull ContentResolver resolver, @NonNull ContentObserver observer)573 protected void registerForExtraSettingsChanges(@NonNull ContentResolver resolver, 574 @NonNull ContentObserver observer) { 575 } 576 577 /** 578 * Callback for Settings changes that were registered though 579 * {@link #registerForExtraSettingsChanges(ContentResolver, ContentObserver)}. 580 * 581 * @param userId user associated with the change 582 * @param property Settings property changed. 583 */ onSettingsChanged(@serIdInt int userId, @NonNull String property)584 protected void onSettingsChanged(@UserIdInt int userId, @NonNull String property) { 585 } 586 587 /** 588 * Gets the service instance for an user, creating an instance if not present in the cache. 589 */ 590 @GuardedBy("mLock") 591 @NonNull getServiceForUserLocked(@serIdInt int userId)592 protected S getServiceForUserLocked(@UserIdInt int userId) { 593 List<S> services = getServiceListForUserLocked(userId); 594 return services == null || services.size() == 0 ? null : services.get(0); 595 } 596 597 /** 598 * Gets the service instance list for a user, creating instances if not present in the cache. 599 */ 600 @GuardedBy("mLock") getServiceListForUserLocked(@serIdInt int userId)601 protected List<S> getServiceListForUserLocked(@UserIdInt int userId) { 602 final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 603 Binder.getCallingUid(), userId, false, false, null, null); 604 List<S> services = mServicesCacheList.get(resolvedUserId); 605 if (services == null || services.size() == 0) { 606 final boolean disabled = isDisabledLocked(userId); 607 if (mServiceNameResolver != null && mServiceNameResolver.isConfiguredInMultipleMode()) { 608 services = newServiceListLocked(resolvedUserId, disabled, 609 mServiceNameResolver.getServiceNameList(userId)); 610 } else { 611 services = new ArrayList<>(); 612 services.add(newServiceLocked(resolvedUserId, disabled)); 613 } 614 if (!disabled) { 615 for (int i = 0; i < services.size(); i++) { 616 onServiceEnabledLocked(services.get(i), resolvedUserId); 617 } 618 } 619 mServicesCacheList.put(userId, services); 620 } 621 return services; 622 } 623 624 /** 625 * Gets the <b>existing</b> service instance for a user, returning {@code null} if not already 626 * present in the cache. 627 */ 628 @GuardedBy("mLock") 629 @Nullable peekServiceForUserLocked(@serIdInt int userId)630 protected S peekServiceForUserLocked(@UserIdInt int userId) { 631 List<S> serviceList = peekServiceListForUserLocked(userId); 632 return serviceList == null || serviceList.size() == 0 ? null : serviceList.get(0); 633 } 634 635 /** 636 * Gets the <b>existing</b> service instance for a user, returning {@code null} if not already 637 * present in the cache. 638 */ 639 @GuardedBy("mLock") 640 @Nullable peekServiceListForUserLocked(@serIdInt int userId)641 protected List<S> peekServiceListForUserLocked(@UserIdInt int userId) { 642 final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 643 Binder.getCallingUid(), userId, false, false, null, null); 644 return mServicesCacheList.get(resolvedUserId); 645 } 646 647 /** 648 * Updates a cached service for a given user. 649 */ 650 @GuardedBy("mLock") updateCachedServiceLocked(@serIdInt int userId)651 protected void updateCachedServiceLocked(@UserIdInt int userId) { 652 updateCachedServiceListLocked(userId, isDisabledLocked(userId)); 653 } 654 655 /** 656 * Checks whether the service is disabled (through {@link UserManager} restrictions) for the 657 * given user. 658 */ 659 @GuardedBy("mLock") isDisabledLocked(@serIdInt int userId)660 protected boolean isDisabledLocked(@UserIdInt int userId) { 661 return mDisabledByUserRestriction != null && mDisabledByUserRestriction.get(userId); 662 } 663 664 /** 665 * Updates a cached service for a given user. 666 * 667 * @param userId user handle. 668 * @param disabled whether the user is disabled. 669 * @return service for the user. 670 */ 671 @GuardedBy("mLock") updateCachedServiceLocked(@serIdInt int userId, boolean disabled)672 protected S updateCachedServiceLocked(@UserIdInt int userId, boolean disabled) { 673 final S service = getServiceForUserLocked(userId); 674 updateCachedServiceListLocked(userId, disabled); 675 return service; 676 } 677 678 /** 679 * Updates a cached service for a given user. 680 * 681 * @param userId user handle. 682 * @param disabled whether the user is disabled. 683 * @return service for the user. 684 */ 685 @GuardedBy("mLock") updateCachedServiceListLocked(@serIdInt int userId, boolean disabled)686 protected List<S> updateCachedServiceListLocked(@UserIdInt int userId, boolean disabled) { 687 if (mServiceNameResolver != null 688 && mServiceNameResolver.isConfiguredInMultipleMode()) { 689 // In multiple mode, we have multiple instances of AbstractPerUserSystemService, per 690 // user where each instance holds information needed to connect to a backend. An 691 // update operation in this mode needs to account for addition, deletion, change 692 // of backends and cannot be executed in the scope of a given 693 // AbstractPerUserSystemService. 694 return updateCachedServiceListMultiModeLocked(userId, disabled); 695 } 696 // isConfiguredInMultipleMode is false 697 final List<S> services = getServiceListForUserLocked(userId); 698 if (services == null) { 699 return null; 700 } 701 for (int i = 0; i < services.size(); i++) { 702 S service = services.get(i); 703 if (service != null) { 704 synchronized (service.mLock) { 705 service.updateLocked(disabled); 706 if (!service.isEnabledLocked()) { 707 removeCachedServiceListLocked(userId); 708 } else { 709 onServiceEnabledLocked(services.get(i), userId); 710 } 711 } 712 } 713 } 714 return services; 715 } 716 717 @GuardedBy("mLock") updateCachedServiceListMultiModeLocked(int userId, boolean disabled)718 private List<S> updateCachedServiceListMultiModeLocked(int userId, boolean disabled) { 719 final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 720 Binder.getCallingUid(), userId, false, false, null, 721 null); 722 List<S> services = new ArrayList<>(); 723 synchronized (mLock) { 724 removeCachedServiceListLocked(resolvedUserId); 725 services = getServiceListForUserLocked(userId); 726 } 727 return services; 728 } 729 730 /** 731 * Gets the Settings property that defines the name of the component name used to bind this 732 * service to an external service, or {@code null} when the service is not defined by such 733 * property (for example, if it's a system service defined by framework resources). 734 */ 735 @Nullable getServiceSettingsProperty()736 protected String getServiceSettingsProperty() { 737 return null; 738 } 739 740 /** 741 * Callback called after a new service was added to the cache, or an existing service that was 742 * previously disabled gets enabled. 743 * 744 * <p>By default doesn't do anything, but can be overridden by subclasses. 745 */ 746 @SuppressWarnings("unused") 747 @GuardedBy("mLock") onServiceEnabledLocked(@onNull S service, @UserIdInt int userId)748 protected void onServiceEnabledLocked(@NonNull S service, @UserIdInt int userId) { 749 } 750 751 /** 752 * Removes a cached service list for a given user. 753 * 754 * @return the removed service. 755 */ 756 @GuardedBy("mLock") 757 @NonNull removeCachedServiceListLocked(@serIdInt int userId)758 protected final List<S> removeCachedServiceListLocked(@UserIdInt int userId) { 759 final List<S> services = peekServiceListForUserLocked(userId); 760 if (services != null) { 761 mServicesCacheList.delete(userId); 762 for (int i = 0; i < services.size(); i++) { 763 onServiceRemoved(services.get(i), userId); 764 } 765 } 766 return services; 767 } 768 769 /** 770 * Called before the package that provides the service for the given user is being updated. 771 */ 772 @GuardedBy("mLock") onServicePackageUpdatingLocked(@serIdInt int userId)773 protected void onServicePackageUpdatingLocked(@UserIdInt int userId) { 774 if (verbose) Slog.v(mTag, "onServicePackageUpdatingLocked(" + userId + ")"); 775 } 776 777 /** 778 * Called after the package that provides the service for the given user is being updated. 779 */ 780 @GuardedBy("mLock") onServicePackageUpdatedLocked(@serIdInt int userId)781 protected void onServicePackageUpdatedLocked(@UserIdInt int userId) { 782 if (verbose) Slog.v(mTag, "onServicePackageUpdated(" + userId + ")"); 783 } 784 785 /** 786 * Called after the package data that provides the service for the given user is cleared. 787 */ 788 @GuardedBy("mLock") onServicePackageDataClearedLocked(@serIdInt int userId)789 protected void onServicePackageDataClearedLocked(@UserIdInt int userId) { 790 if (verbose) Slog.v(mTag, "onServicePackageDataCleared(" + userId + ")"); 791 } 792 793 /** 794 * Called after the package that provides the service for the given user is restarted. 795 */ 796 @GuardedBy("mLock") onServicePackageRestartedLocked(@serIdInt int userId)797 protected void onServicePackageRestartedLocked(@UserIdInt int userId) { 798 if (verbose) Slog.v(mTag, "onServicePackageRestarted(" + userId + ")"); 799 } 800 801 /** 802 * Called after the service is removed from the cache. 803 */ 804 @SuppressWarnings("unused") onServiceRemoved(@onNull S service, @UserIdInt int userId)805 protected void onServiceRemoved(@NonNull S service, @UserIdInt int userId) { 806 } 807 808 /** 809 * Called when the service name changed (typically when using temporary services). 810 * 811 * <p>By default, it calls {@link #updateCachedServiceLocked(int)}; subclasses must either call 812 * that same method, or {@code super.onServiceNameChanged()}. 813 * 814 * @param userId user handle. 815 * @param serviceName the new service name. 816 * @param isTemporary whether the new service is temporary. 817 */ onServiceNameChanged(@serIdInt int userId, @Nullable String serviceName, boolean isTemporary)818 protected void onServiceNameChanged(@UserIdInt int userId, @Nullable String serviceName, 819 boolean isTemporary) { 820 synchronized (mLock) { 821 updateCachedServiceListLocked(userId, isDisabledLocked(userId)); 822 } 823 } 824 825 /** 826 * Called when the service name list has changed (typically when using temporary services). 827 * 828 * <p>By default, it calls {@link #updateCachedServiceLocked(int)}; subclasses must either call 829 * that same method, or {@code super.onServiceNameChanged()}. 830 * 831 * @param userId user handle. 832 * @param serviceNames the new service name list. 833 * @param isTemporary whether the new service is temporary. 834 */ onServiceNameListChanged(@serIdInt int userId, @Nullable String[] serviceNames, boolean isTemporary)835 protected void onServiceNameListChanged(@UserIdInt int userId, @Nullable String[] serviceNames, 836 boolean isTemporary) { 837 synchronized (mLock) { 838 updateCachedServiceListLocked(userId, isDisabledLocked(userId)); 839 } 840 } 841 842 /** 843 * Visits all services in the cache. 844 */ 845 @GuardedBy("mLock") visitServicesLocked(@onNull Visitor<S> visitor)846 protected void visitServicesLocked(@NonNull Visitor<S> visitor) { 847 final int size = mServicesCacheList.size(); 848 for (int i = 0; i < size; i++) { 849 List<S> services = mServicesCacheList.valueAt(i); 850 for (int j = 0; j < services.size(); j++) { 851 visitor.visit(services.get(j)); 852 } 853 } 854 } 855 856 /** 857 * Clear the cache by removing all services. 858 */ 859 @GuardedBy("mLock") clearCacheLocked()860 protected void clearCacheLocked() { 861 mServicesCacheList.clear(); 862 } 863 864 /** 865 * Gets a cached reference to {@link UserManagerInternal}. 866 */ 867 @NonNull getUserManagerInternal()868 protected UserManagerInternal getUserManagerInternal() { 869 if (mUm == null) { 870 if (verbose) Slog.v(mTag, "lazy-loading UserManagerInternal"); 871 mUm = LocalServices.getService(UserManagerInternal.class); 872 } 873 return mUm; 874 } 875 876 /** 877 * Gets a list of all supported users (i.e., those that pass the 878 * {@link #isUserSupported(TargetUser)}check). 879 */ 880 @NonNull getSupportedUsers()881 protected List<UserInfo> getSupportedUsers() { 882 final UserInfo[] allUsers = getUserManagerInternal().getUserInfos(); 883 final int size = allUsers.length; 884 final List<UserInfo> supportedUsers = new ArrayList<>(size); 885 for (int i = 0; i < size; i++) { 886 final UserInfo userInfo = allUsers[i]; 887 if (isUserSupported(new TargetUser(userInfo))) { 888 supportedUsers.add(userInfo); 889 } 890 } 891 return supportedUsers; 892 } 893 894 /** 895 * Asserts that the given package name is owned by the UID making this call. 896 * 897 * @throws SecurityException when it's not... 898 */ assertCalledByPackageOwner(@onNull String packageName)899 protected void assertCalledByPackageOwner(@NonNull String packageName) { 900 Objects.requireNonNull(packageName); 901 final int uid = Binder.getCallingUid(); 902 final String[] packages = getContext().getPackageManager().getPackagesForUid(uid); 903 if (packages != null) { 904 for (String candidate : packages) { 905 if (packageName.equals(candidate)) return; // Found it 906 } 907 } 908 throw new SecurityException("UID " + uid + " does not own " + packageName); 909 } 910 911 // TODO(b/117779333): support proto 912 @GuardedBy("mLock") dumpLocked(@onNull String prefix, @NonNull PrintWriter pw)913 protected void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) { 914 boolean realDebug = debug; 915 boolean realVerbose = verbose; 916 final String prefix2 = " "; 917 918 try { 919 // Temporarily turn on full logging; 920 debug = verbose = true; 921 final int size = mServicesCacheList.size(); 922 pw.print(prefix); 923 pw.print("Debug: "); 924 pw.print(realDebug); 925 pw.print(" Verbose: "); 926 pw.println(realVerbose); 927 pw.print("Package policy flags: "); 928 pw.println(mServicePackagePolicyFlags); 929 if (mUpdatingPackageNames != null) { 930 pw.print("Packages being updated: "); 931 pw.println(mUpdatingPackageNames); 932 } 933 dumpSupportedUsers(pw, prefix); 934 if (mServiceNameResolver != null) { 935 pw.print(prefix); 936 pw.print("Name resolver: "); 937 mServiceNameResolver.dumpShort(pw); 938 pw.println(); 939 final List<UserInfo> users = getSupportedUsers(); 940 for (int i = 0; i < users.size(); i++) { 941 final int userId = users.get(i).id; 942 pw.print(prefix2); 943 pw.print(userId); 944 pw.print(": "); 945 mServiceNameResolver.dumpShort(pw, userId); 946 pw.println(); 947 } 948 } 949 pw.print(prefix); 950 pw.print("Users disabled by restriction: "); 951 pw.println(mDisabledByUserRestriction); 952 pw.print(prefix); 953 pw.print("Allow instant service: "); 954 pw.println(mAllowInstantService); 955 final String settingsProperty = getServiceSettingsProperty(); 956 if (settingsProperty != null) { 957 pw.print(prefix); 958 pw.print("Settings property: "); 959 pw.println(settingsProperty); 960 } 961 pw.print(prefix); 962 pw.print("Cached services: "); 963 if (size == 0) { 964 pw.println("none"); 965 } else { 966 pw.println(size); 967 for (int i = 0; i < size; i++) { 968 pw.print(prefix); 969 pw.print("Service at "); 970 pw.print(i); 971 pw.println(": "); 972 final List<S> services = mServicesCacheList.valueAt(i); 973 for (int j = 0; j < services.size(); j++) { 974 S service = services.get(j); 975 synchronized (service.mLock) { 976 service.dumpLocked(prefix2, pw); 977 } 978 } 979 pw.println(); 980 } 981 } 982 } finally { 983 debug = realDebug; 984 verbose = realVerbose; 985 } 986 } 987 startTrackingPackageChanges()988 private void startTrackingPackageChanges() { 989 final PackageMonitor monitor = new PackageMonitor(true) { 990 991 @Override 992 public void onPackageUpdateStarted(@NonNull String packageName, int uid) { 993 if (verbose) Slog.v(mTag, "onPackageUpdateStarted(): " + packageName); 994 final String activePackageName = getActiveServicePackageNameLocked(); 995 if (!packageName.equals(activePackageName)) return; 996 997 final int userId = getChangingUserId(); 998 synchronized (mLock) { 999 if (mUpdatingPackageNames == null) { 1000 mUpdatingPackageNames = new SparseArray<String>(mServicesCacheList.size()); 1001 } 1002 mUpdatingPackageNames.put(userId, packageName); 1003 onServicePackageUpdatingLocked(userId); 1004 if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_NO_REFRESH) != 0) { 1005 if (debug) { 1006 Slog.d(mTag, "Holding service for user " + userId + " while package " 1007 + activePackageName + " is being updated"); 1008 } 1009 } else { 1010 if (debug) { 1011 Slog.d(mTag, "Removing service for user " + userId 1012 + " because package " + activePackageName 1013 + " is being updated"); 1014 } 1015 removeCachedServiceListLocked(userId); 1016 1017 if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_REFRESH_EAGER) 1018 != 0) { 1019 if (debug) { 1020 Slog.d(mTag, "Eagerly recreating service for user " 1021 + userId); 1022 } 1023 getServiceForUserLocked(userId); 1024 } 1025 } 1026 } 1027 } 1028 1029 @Override 1030 public void onPackageUpdateFinished(@NonNull String packageName, int uid) { 1031 if (verbose) Slog.v(mTag, "onPackageUpdateFinished(): " + packageName); 1032 final int userId = getChangingUserId(); 1033 synchronized (mLock) { 1034 final String activePackageName = mUpdatingPackageNames == null ? null 1035 : mUpdatingPackageNames.get(userId); 1036 if (packageName.equals(activePackageName)) { 1037 if (mUpdatingPackageNames != null) { 1038 mUpdatingPackageNames.remove(userId); 1039 if (mUpdatingPackageNames.size() == 0) { 1040 mUpdatingPackageNames = null; 1041 } 1042 } 1043 onServicePackageUpdatedLocked(userId); 1044 } else { 1045 handlePackageUpdateLocked(packageName); 1046 } 1047 } 1048 } 1049 1050 @Override 1051 public void onPackageRemoved(String packageName, int uid) { 1052 if (mServiceNameResolver != null 1053 && mServiceNameResolver.isConfiguredInMultipleMode()) { 1054 final int userId = getChangingUserId(); 1055 synchronized (mLock) { 1056 handlePackageRemovedMultiModeLocked(packageName, userId); 1057 } 1058 return; 1059 } 1060 1061 synchronized (mLock) { 1062 final int userId = getChangingUserId(); 1063 final S service = peekServiceForUserLocked(userId); 1064 if (service != null) { 1065 final ComponentName componentName = service.getServiceComponentName(); 1066 if (componentName != null) { 1067 if (packageName.equals(componentName.getPackageName())) { 1068 handleActiveServiceRemoved(userId); 1069 } 1070 } 1071 } 1072 } 1073 } 1074 1075 @Override 1076 public boolean onHandleForceStop(Intent intent, String[] packages, 1077 int uid, boolean doit) { 1078 synchronized (mLock) { 1079 final String activePackageName = getActiveServicePackageNameLocked(); 1080 for (String pkg : packages) { 1081 if (pkg.equals(activePackageName)) { 1082 if (!doit) { 1083 return true; 1084 } 1085 final String action = intent.getAction(); 1086 final int userId = getChangingUserId(); 1087 if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) { 1088 handleActiveServiceRestartedLocked(activePackageName, userId); 1089 } else { 1090 removeCachedServiceListLocked(userId); 1091 } 1092 } else { 1093 handlePackageUpdateLocked(pkg); 1094 } 1095 } 1096 } 1097 return false; 1098 } 1099 1100 @Override 1101 public void onPackageDataCleared(String packageName, int uid) { 1102 if (verbose) Slog.v(mTag, "onPackageDataCleared(): " + packageName); 1103 final int userId = getChangingUserId(); 1104 1105 if (mServiceNameResolver != null 1106 && mServiceNameResolver.isConfiguredInMultipleMode()) { 1107 synchronized (mLock) { 1108 onServicePackageDataClearedMultiModeLocked(packageName, userId); 1109 } 1110 return; 1111 } 1112 1113 synchronized (mLock) { 1114 final S service = peekServiceForUserLocked(userId); 1115 if (service != null) { 1116 final ComponentName componentName = service.getServiceComponentName(); 1117 if (componentName != null) { 1118 if (packageName.equals(componentName.getPackageName())) { 1119 onServicePackageDataClearedLocked(userId); 1120 } 1121 } 1122 } 1123 } 1124 } 1125 1126 private void handleActiveServiceRemoved(@UserIdInt int userId) { 1127 synchronized (mLock) { 1128 removeCachedServiceListLocked(userId); 1129 } 1130 final String serviceSettingsProperty = getServiceSettingsProperty(); 1131 if (serviceSettingsProperty != null) { 1132 Settings.Secure.putStringForUser(getContext().getContentResolver(), 1133 serviceSettingsProperty, null, userId); 1134 } 1135 } 1136 1137 @GuardedBy("mLock") 1138 private void handleActiveServiceRestartedLocked(String activePackageName, 1139 @UserIdInt int userId) { 1140 if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_NO_REFRESH) != 0) { 1141 if (debug) { 1142 Slog.d(mTag, "Holding service for user " + userId + " while package " 1143 + activePackageName + " is being restarted"); 1144 } 1145 } else { 1146 if (debug) { 1147 Slog.d(mTag, "Removing service for user " + userId 1148 + " because package " + activePackageName 1149 + " is being restarted"); 1150 } 1151 removeCachedServiceListLocked(userId); 1152 1153 if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_REFRESH_EAGER) != 0) { 1154 if (debug) { 1155 Slog.d(mTag, "Eagerly recreating service for user " + userId); 1156 } 1157 updateCachedServiceLocked(userId); 1158 } 1159 } 1160 onServicePackageRestartedLocked(userId); 1161 } 1162 1163 @Override 1164 public void onPackageModified(String packageName) { 1165 synchronized (mLock) { 1166 if (verbose) Slog.v(mTag, "onPackageModified(): " + packageName); 1167 1168 if (mServiceNameResolver == null) { 1169 return; 1170 } 1171 1172 final int userId = getChangingUserId(); 1173 final String[] serviceNames = mServiceNameResolver.getDefaultServiceNameList( 1174 userId); 1175 if (serviceNames != null) { 1176 for (int i = 0; i < serviceNames.length; i++) { 1177 peekAndUpdateCachedServiceLocked(packageName, userId, serviceNames[i]); 1178 } 1179 } 1180 } 1181 } 1182 1183 @GuardedBy("mLock") 1184 private void peekAndUpdateCachedServiceLocked(String packageName, int userId, 1185 String serviceName) { 1186 if (serviceName == null) { 1187 return; 1188 } 1189 1190 final ComponentName serviceComponentName = 1191 ComponentName.unflattenFromString(serviceName); 1192 if (serviceComponentName == null 1193 || !serviceComponentName.getPackageName().equals(packageName)) { 1194 return; 1195 } 1196 1197 // The default service package has changed, update the cached if the service 1198 // exists but no active component. 1199 final S service = peekServiceForUserLocked(userId); 1200 if (service != null) { 1201 final ComponentName componentName = service.getServiceComponentName(); 1202 if (componentName == null) { 1203 if (verbose) Slog.v(mTag, "update cached"); 1204 updateCachedServiceLocked(userId); 1205 } 1206 } 1207 } 1208 1209 @GuardedBy("mLock") 1210 private String getActiveServicePackageNameLocked() { 1211 final int userId = getChangingUserId(); 1212 final S service = peekServiceForUserLocked(userId); 1213 if (service == null) { 1214 return null; 1215 } 1216 final ComponentName serviceComponent = service.getServiceComponentName(); 1217 if (serviceComponent == null) { 1218 return null; 1219 } 1220 return serviceComponent.getPackageName(); 1221 } 1222 1223 @GuardedBy("mLock") 1224 private void handlePackageUpdateLocked(String packageName) { 1225 visitServicesLocked((s) -> s.handlePackageUpdateLocked(packageName)); 1226 } 1227 }; 1228 1229 // package changes 1230 monitor.register(getContext(), null, UserHandle.ALL, true); 1231 } 1232 1233 @GuardedBy("mLock") 1234 @SuppressWarnings("unused") onServicePackageDataClearedMultiModeLocked(String packageName, int userId)1235 protected void onServicePackageDataClearedMultiModeLocked(String packageName, int userId) { 1236 if (verbose) { 1237 Slog.v(mTag, "onServicePackageDataClearedMultiModeLocked(" 1238 + userId + ")"); 1239 } 1240 } 1241 1242 @GuardedBy("mLock") 1243 @SuppressWarnings("unused") handlePackageRemovedMultiModeLocked(String packageName, int userId)1244 protected void handlePackageRemovedMultiModeLocked(String packageName, int userId) { 1245 if (verbose) Slog.v(mTag, "handlePackageRemovedMultiModeLocked(" + userId + ")"); 1246 } 1247 1248 @GuardedBy("mLock") removeServiceFromCache(@onNull S service, int userId)1249 protected void removeServiceFromCache(@NonNull S service, int userId) { 1250 if (mServicesCacheList.get(userId) != null) { 1251 mServicesCacheList.get(userId).remove(service); 1252 } 1253 } 1254 1255 @GuardedBy("mLock") removeServiceFromMultiModeSettings(String serviceComponentName, int userId)1256 protected void removeServiceFromMultiModeSettings(String serviceComponentName, int userId) { 1257 final String serviceSettingsProperty = getServiceSettingsProperty(); 1258 if (serviceSettingsProperty == null || mServiceNameResolver == null 1259 || !mServiceNameResolver.isConfiguredInMultipleMode()) { 1260 if (verbose) { 1261 Slog.v(mTag, "removeServiceFromSettings not implemented " 1262 + " for single backend implementation"); 1263 } 1264 return; 1265 } 1266 String[] settingComponentNames = mServiceNameResolver.getServiceNameList(userId); 1267 List<String> remainingServices = new ArrayList<>(); 1268 for (String settingComponentName : settingComponentNames) { 1269 if (!settingComponentName.equals(serviceComponentName)) { 1270 remainingServices.add(settingComponentName); 1271 } 1272 } 1273 mServiceNameResolver.setServiceNameList(remainingServices, userId); 1274 } 1275 1276 /** 1277 * Visitor pattern. 1278 * 1279 * @param <S> visited class. 1280 */ 1281 public interface Visitor<S> { 1282 /** 1283 * Visits a service. 1284 * 1285 * @param service the service to be visited. 1286 */ visit(@onNull S service)1287 void visit(@NonNull S service); 1288 } 1289 1290 private final class SettingsObserver extends ContentObserver { SettingsObserver(Handler handler)1291 SettingsObserver(Handler handler) { 1292 super(handler); 1293 ContentResolver resolver = getContext().getContentResolver(); 1294 final String serviceProperty = getServiceSettingsProperty(); 1295 if (serviceProperty != null) { 1296 resolver.registerContentObserver(Settings.Secure.getUriFor( 1297 serviceProperty), false, this, UserHandle.USER_ALL); 1298 } 1299 resolver.registerContentObserver(Settings.Secure.getUriFor( 1300 Settings.Secure.USER_SETUP_COMPLETE), false, this, UserHandle.USER_ALL); 1301 registerForExtraSettingsChanges(resolver, this); 1302 } 1303 1304 @Override onChange(boolean selfChange, Uri uri, @UserIdInt int userId)1305 public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) { 1306 if (verbose) Slog.v(mTag, "onChange(): uri=" + uri + ", userId=" + userId); 1307 final String property = uri.getLastPathSegment(); 1308 if (property == null) { 1309 return; 1310 } 1311 if (property.equals(getServiceSettingsProperty()) 1312 || property.equals(Settings.Secure.USER_SETUP_COMPLETE)) { 1313 synchronized (mLock) { 1314 updateCachedServiceLocked(userId); 1315 } 1316 } else { 1317 onSettingsChanged(userId, property); 1318 } 1319 } 1320 } 1321 } 1322