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