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.os.UserManagerInternal;
35 import android.provider.Settings;
36 import android.util.Slog;
37 import android.util.SparseArray;
38 import android.util.SparseBooleanArray;
39 
40 import com.android.internal.annotations.GuardedBy;
41 import com.android.internal.content.PackageMonitor;
42 import com.android.internal.infra.AbstractRemoteService;
43 import com.android.internal.os.BackgroundThread;
44 import com.android.internal.util.Preconditions;
45 import com.android.server.LocalServices;
46 import com.android.server.SystemService;
47 
48 import java.io.PrintWriter;
49 import java.lang.annotation.Retention;
50 import java.lang.annotation.RetentionPolicy;
51 import java.util.List;
52 
53 /**
54  * Base class for {@link SystemService SystemServices} that support multi user.
55  *
56  * <p>Subclasses of this service are just a facade for the service binder calls - the "real" work
57  * is done by the {@link AbstractPerUserSystemService} subclasses, which are automatically managed
58  * through an user -> service cache.
59  *
60  * <p>It also takes care of other plumbing tasks such as:
61  *
62  * <ul>
63  *   <li>Disabling the service when {@link UserManager} restrictions change.
64  *   <li>Refreshing the service when its underlying
65  *   {@link #getServiceSettingsProperty() Settings property} changed.
66  *   <li>Calling the service when other Settings properties changed.
67  * </ul>
68  *
69  * <p>See {@code com.android.server.autofill.AutofillManagerService} for a concrete
70  * (no pun intended) example of how to use it.
71  *
72  * @param <M> "master" service class.
73  * @param <S> "real" service class.
74  *
75  * @hide
76  */
77 // TODO(b/117779333): improve javadoc above instead of using Autofill as an example
78 public abstract class AbstractMasterSystemService<M extends AbstractMasterSystemService<M, S>,
79         S extends AbstractPerUserSystemService<S, M>> extends SystemService {
80 
81     /** On a package update, does not refresh the per-user service in the cache. */
82     public static final int PACKAGE_UPDATE_POLICY_NO_REFRESH = 0;
83 
84     /**
85      * On a package update, removes any existing per-user services in the cache.
86      *
87      * <p>This does not immediately recreate these services. It is assumed they will be recreated
88      * for the next user request.
89      */
90     public static final int PACKAGE_UPDATE_POLICY_REFRESH_LAZY = 1;
91 
92     /**
93      * On a package update, removes and recreates any existing per-user services in the cache.
94      */
95     public static final int PACKAGE_UPDATE_POLICY_REFRESH_EAGER = 2;
96 
97     @IntDef(flag = true, prefix = { "PACKAGE_UPDATE_POLICY_" }, value = {
98             PACKAGE_UPDATE_POLICY_NO_REFRESH,
99             PACKAGE_UPDATE_POLICY_REFRESH_LAZY,
100             PACKAGE_UPDATE_POLICY_REFRESH_EAGER
101     })
102     @Retention(RetentionPolicy.SOURCE)
103     public @interface PackageUpdatePolicy {}
104 
105     /**
106      * Log tag
107      */
108     protected final String mTag = getClass().getSimpleName();
109 
110     /**
111      * Lock used to synchronize access to internal state; should be acquired before calling a
112      * method whose name ends with {@code locked}.
113      */
114     protected final Object mLock = new Object();
115 
116     /**
117      * Object used to define the name of the service component used to create
118      * {@link com.android.internal.infra.AbstractRemoteService} instances.
119      */
120     @Nullable
121     protected final ServiceNameResolver mServiceNameResolver;
122 
123     /**
124      * Whether the service should log debug statements.
125      */
126     //TODO(b/117779333): consider using constants for these guards
127     public boolean verbose = false;
128 
129     /**
130      * Whether the service should log verbose statements.
131      */
132     //TODO(b/117779333): consider using constants for these guards
133     public boolean debug = false;
134 
135     /**
136      * Whether the service is allowed to bind to an instant-app.
137      */
138     @GuardedBy("mLock")
139     protected boolean mAllowInstantService;
140 
141     /**
142      * Users disabled due to {@link UserManager} restrictions, or {@code null} if the service cannot
143      * be disabled through {@link UserManager}.
144      */
145     @GuardedBy("mLock")
146     @Nullable
147     private final SparseBooleanArray mDisabledByUserRestriction;
148 
149     /**
150      * Cache of services per user id.
151      */
152     @GuardedBy("mLock")
153     private final SparseArray<S> mServicesCache = new SparseArray<>();
154 
155     /**
156      * Whether the per-user service should be removed from the cache when its apk is updated.
157      *
158      * <p>One of {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH},
159      * {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY} or {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}.
160      */
161     private final @PackageUpdatePolicy int mPackageUpdatePolicy;
162 
163     /**
164      * Name of the service packages whose APK are being updated, keyed by user id.
165      */
166     @GuardedBy("mLock")
167     private SparseArray<String> mUpdatingPackageNames;
168 
169     /**
170      * Default constructor.
171      *
172      * <p>When using this constructor, the {@link AbstractPerUserSystemService} is removed from
173      * the cache (and re-added) when the service package is updated.
174      *
175      * @param context system context.
176      * @param serviceNameResolver resolver for
177      * {@link com.android.internal.infra.AbstractRemoteService} instances, or
178      * {@code null} when the service doesn't bind to remote services.
179      * @param disallowProperty when not {@code null}, defines a {@link UserManager} restriction that
180      *        disables the service. <b>NOTE: </b> you'll also need to add it to
181      *        {@code UserRestrictionsUtils.USER_RESTRICTIONS}.
182      */
AbstractMasterSystemService(@onNull Context context, @Nullable ServiceNameResolver serviceNameResolver, @Nullable String disallowProperty)183     protected AbstractMasterSystemService(@NonNull Context context,
184             @Nullable ServiceNameResolver serviceNameResolver,
185             @Nullable String disallowProperty) {
186         this(context, serviceNameResolver, disallowProperty,
187                 /*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_REFRESH_LAZY);
188     }
189 
190     /**
191      * Full constructor.
192      *
193      * @param context system context.
194      * @param serviceNameResolver resolver for
195      * {@link com.android.internal.infra.AbstractRemoteService} instances, or
196      * {@code null} when the service doesn't bind to remote services.
197      * @param disallowProperty when not {@code null}, defines a {@link UserManager} restriction that
198      *        disables the service. <b>NOTE: </b> you'll also need to add it to
199      *        {@code UserRestrictionsUtils.USER_RESTRICTIONS}.
200      * @param packageUpdatePolicy when {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY}, the
201      *        {@link AbstractPerUserSystemService} is removed from the cache when the service
202      *        package is updated; when {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}, the
203      *        {@link AbstractPerUserSystemService} is removed from the cache and immediately
204      *        re-added when the service package is updated; when
205      *        {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH}, the service is untouched during the update.
206      */
AbstractMasterSystemService(@onNull Context context, @Nullable ServiceNameResolver serviceNameResolver, @Nullable String disallowProperty, @PackageUpdatePolicy int packageUpdatePolicy)207     protected AbstractMasterSystemService(@NonNull Context context,
208             @Nullable ServiceNameResolver serviceNameResolver,
209             @Nullable String disallowProperty, @PackageUpdatePolicy int packageUpdatePolicy) {
210         super(context);
211 
212         mPackageUpdatePolicy = packageUpdatePolicy;
213 
214         mServiceNameResolver = serviceNameResolver;
215         if (mServiceNameResolver != null) {
216             mServiceNameResolver.setOnTemporaryServiceNameChangedCallback(
217                     (u, s, t) -> onServiceNameChanged(u, s, t));
218 
219         }
220         if (disallowProperty == null) {
221             mDisabledByUserRestriction = null;
222         } else {
223             mDisabledByUserRestriction = new SparseBooleanArray();
224             // Hookup with UserManager to disable service when necessary.
225             final UserManager um = context.getSystemService(UserManager.class);
226             final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
227             final List<UserInfo> users = um.getUsers();
228             for (int i = 0; i < users.size(); i++) {
229                 final int userId = users.get(i).id;
230                 final boolean disabled = umi.getUserRestriction(userId, disallowProperty);
231                 if (disabled) {
232                     Slog.i(mTag, "Disabling by restrictions user " + userId);
233                     mDisabledByUserRestriction.put(userId, disabled);
234                 }
235             }
236             umi.addUserRestrictionsListener((userId, newRestrictions, prevRestrictions) -> {
237                 final boolean disabledNow =
238                         newRestrictions.getBoolean(disallowProperty, false);
239                 synchronized (mLock) {
240                     final boolean disabledBefore = mDisabledByUserRestriction.get(userId);
241                     if (disabledBefore == disabledNow) {
242                         // Nothing changed, do nothing.
243                         if (debug) {
244                             Slog.d(mTag, "Restriction did not change for user " + userId);
245                             return;
246                         }
247                     }
248                     Slog.i(mTag, "Updating for user " + userId + ": disabled=" + disabledNow);
249                     mDisabledByUserRestriction.put(userId, disabledNow);
250                     updateCachedServiceLocked(userId, disabledNow);
251                 }
252             });
253         }
254         startTrackingPackageChanges();
255     }
256 
257     @Override // from SystemService
onBootPhase(int phase)258     public void onBootPhase(int phase) {
259         if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
260             new SettingsObserver(BackgroundThread.getHandler());
261         }
262     }
263 
264     @Override // from SystemService
onUnlockUser(int userId)265     public void onUnlockUser(int userId) {
266         synchronized (mLock) {
267             updateCachedServiceLocked(userId);
268         }
269     }
270 
271     @Override // from SystemService
onCleanupUser(int userId)272     public void onCleanupUser(int userId) {
273         synchronized (mLock) {
274             removeCachedServiceLocked(userId);
275         }
276     }
277 
278     /**
279      * Gets whether the service is allowed to bind to an instant-app.
280      *
281      * <p>Typically called by {@code ShellCommand} during CTS tests.
282      *
283      * @throws SecurityException if caller is not allowed to manage this service's settings.
284      */
getAllowInstantService()285     public final boolean getAllowInstantService() {
286         enforceCallingPermissionForManagement();
287         synchronized (mLock) {
288             return mAllowInstantService;
289         }
290     }
291 
292     /**
293      * Checks whether the service is allowed to bind to an instant-app.
294      *
295      * <p>Typically called by subclasses when creating {@link AbstractRemoteService} instances.
296      *
297      * <p><b>NOTE: </b>must not be called by {@code ShellCommand} as it does not check for
298      * permission.
299      */
isBindInstantServiceAllowed()300     public final boolean isBindInstantServiceAllowed() {
301         synchronized (mLock) {
302             return mAllowInstantService;
303         }
304     }
305 
306     /**
307      * Sets whether the service is allowed to bind to an instant-app.
308      *
309      * <p>Typically called by {@code ShellCommand} during CTS tests.
310      *
311      * @throws SecurityException if caller is not allowed to manage this service's settings.
312      */
setAllowInstantService(boolean mode)313     public final void setAllowInstantService(boolean mode) {
314         Slog.i(mTag, "setAllowInstantService(): " + mode);
315         enforceCallingPermissionForManagement();
316         synchronized (mLock) {
317             mAllowInstantService = mode;
318         }
319     }
320 
321     /**
322      * Temporarily sets the service implementation.
323      *
324      * <p>Typically used by Shell command and/or CTS tests.
325      *
326      * @param componentName name of the new component
327      * @param durationMs how long the change will be valid (the service will be automatically reset
328      *            to the default component after this timeout expires).
329      * @throws SecurityException if caller is not allowed to manage this service's settings.
330      * @throws IllegalArgumentException if value of {@code durationMs} is higher than
331      *             {@link #getMaximumTemporaryServiceDurationMs()}.
332      */
setTemporaryService(@serIdInt int userId, @NonNull String componentName, int durationMs)333     public final void setTemporaryService(@UserIdInt int userId, @NonNull String componentName,
334             int durationMs) {
335         Slog.i(mTag, "setTemporaryService(" + userId + ") to " + componentName + " for "
336                 + durationMs + "ms");
337         enforceCallingPermissionForManagement();
338 
339         Preconditions.checkNotNull(componentName);
340         final int maxDurationMs = getMaximumTemporaryServiceDurationMs();
341         if (durationMs > maxDurationMs) {
342             throw new IllegalArgumentException(
343                     "Max duration is " + maxDurationMs + " (called with " + durationMs + ")");
344         }
345 
346         synchronized (mLock) {
347             final S oldService = peekServiceForUserLocked(userId);
348             if (oldService != null) {
349                 oldService.removeSelfFromCacheLocked();
350             }
351             mServiceNameResolver.setTemporaryService(userId, componentName, durationMs);
352         }
353     }
354 
355     /**
356      * Sets whether the default service should be used.
357      *
358      * <p>Typically used during CTS tests to make sure only the default service doesn't interfere
359      * with the test results.
360      *
361      * @throws SecurityException if caller is not allowed to manage this service's settings.
362      *
363      * @return whether the enabled state changed.
364      */
setDefaultServiceEnabled(@serIdInt int userId, boolean enabled)365     public final boolean setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) {
366         Slog.i(mTag, "setDefaultServiceEnabled() for userId " + userId + ": " + enabled);
367         enforceCallingPermissionForManagement();
368 
369         synchronized (mLock) {
370             final boolean changed = mServiceNameResolver.setDefaultServiceEnabled(userId, enabled);
371             if (!changed) {
372                 if (verbose) {
373                     Slog.v(mTag, "setDefaultServiceEnabled(" + userId + "): already " + enabled);
374                 }
375                 return false;
376             }
377 
378             final S oldService = peekServiceForUserLocked(userId);
379             if (oldService != null) {
380                 oldService.removeSelfFromCacheLocked();
381             }
382 
383             // Must update the service on cache so its initialization code is triggered
384             updateCachedServiceLocked(userId);
385         }
386         return true;
387     }
388 
389     /**
390      * Checks whether the default service should be used.
391      *
392      * <p>Typically used during CTS tests to make sure only the default service doesn't interfere
393      * with the test results.
394      *
395      * @throws SecurityException if caller is not allowed to manage this service's settings.
396      */
isDefaultServiceEnabled(@serIdInt int userId)397     public final boolean isDefaultServiceEnabled(@UserIdInt int userId) {
398         enforceCallingPermissionForManagement();
399 
400         synchronized (mLock) {
401             return mServiceNameResolver.isDefaultServiceEnabled(userId);
402         }
403     }
404 
405     /**
406      * Gets the maximum time the service implementation can be changed.
407      *
408      * @throws UnsupportedOperationException if subclass doesn't override it.
409      */
getMaximumTemporaryServiceDurationMs()410     protected int getMaximumTemporaryServiceDurationMs() {
411         throw new UnsupportedOperationException("Not implemented by " + getClass());
412     }
413 
414     /**
415      * Resets the temporary service implementation to the default component.
416      *
417      * <p>Typically used by Shell command and/or CTS tests.
418      *
419      * @throws SecurityException if caller is not allowed to manage this service's settings.
420      */
resetTemporaryService(@serIdInt int userId)421     public final void resetTemporaryService(@UserIdInt int userId) {
422         Slog.i(mTag, "resetTemporaryService(): " + userId);
423         enforceCallingPermissionForManagement();
424         synchronized (mLock) {
425             final S service = getServiceForUserLocked(userId);
426             if (service != null) {
427                 service.resetTemporaryServiceLocked();
428             }
429         }
430     }
431 
432     /**
433      * Asserts that the caller has permissions to manage this service.
434      *
435      * <p>Typically called by {@code ShellCommand} implementations.
436      *
437      * @throws UnsupportedOperationException if subclass doesn't override it.
438      * @throws SecurityException if caller is not allowed to manage this service's settings.
439      */
enforceCallingPermissionForManagement()440     protected void enforceCallingPermissionForManagement() {
441         throw new UnsupportedOperationException("Not implemented by " + getClass());
442     }
443 
444     /**
445      * Creates a new service that will be added to the cache.
446      *
447      * @param resolvedUserId the resolved user id for the service.
448      * @param disabled whether the service is currently disabled (due to {@link UserManager}
449      * restrictions).
450      *
451      * @return a new instance.
452      */
453     @Nullable
newServiceLocked(@serIdInt int resolvedUserId, boolean disabled)454     protected abstract S newServiceLocked(@UserIdInt int resolvedUserId, boolean disabled);
455 
456     /**
457      * Register the service for extra Settings changes (i.e., other than
458      * {@link android.provider.Settings.Secure#USER_SETUP_COMPLETE} or
459      * {@link #getServiceSettingsProperty()}, which are automatically handled).
460      *
461      * <p> Example:
462      *
463      * <pre><code>
464      * resolver.registerContentObserver(Settings.Global.getUriFor(
465      *     Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES), false, observer,
466      *     UserHandle.USER_ALL);
467      * </code></pre>
468      *
469      * <p><b>NOTE: </p>it doesn't need to register for
470      * {@link android.provider.Settings.Secure#USER_SETUP_COMPLETE} or
471      * {@link #getServiceSettingsProperty()}.
472      *
473      */
474     @SuppressWarnings("unused")
registerForExtraSettingsChanges(@onNull ContentResolver resolver, @NonNull ContentObserver observer)475     protected void registerForExtraSettingsChanges(@NonNull ContentResolver resolver,
476             @NonNull ContentObserver observer) {
477     }
478 
479     /**
480      * Callback for Settings changes that were registered though
481      * {@link #registerForExtraSettingsChanges(ContentResolver, ContentObserver)}.
482      *
483      * @param userId user associated with the change
484      * @param property Settings property changed.
485      */
onSettingsChanged(@serIdInt int userId, @NonNull String property)486     protected void onSettingsChanged(@UserIdInt int userId, @NonNull String property) {
487     }
488 
489     /**
490      * Gets the service instance for an user, creating an instance if not present in the cache.
491      */
492     @GuardedBy("mLock")
493     @NonNull
getServiceForUserLocked(@serIdInt int userId)494     protected S getServiceForUserLocked(@UserIdInt int userId) {
495         final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
496                 Binder.getCallingUid(), userId, false, false, null, null);
497         S service = mServicesCache.get(resolvedUserId);
498         if (service == null) {
499             final boolean disabled = isDisabledLocked(userId);
500             service = newServiceLocked(resolvedUserId, disabled);
501             if (!disabled) {
502                 onServiceEnabledLocked(service, resolvedUserId);
503             }
504             mServicesCache.put(userId, service);
505         }
506         return service;
507     }
508 
509     /**
510      * Gets the <b>existing</b> service instance for a user, returning {@code null} if not already
511      * present in the cache.
512      */
513     @GuardedBy("mLock")
514     @Nullable
peekServiceForUserLocked(@serIdInt int userId)515     protected S peekServiceForUserLocked(@UserIdInt int userId) {
516         final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
517                 Binder.getCallingUid(), userId, false, false, null, null);
518         return mServicesCache.get(resolvedUserId);
519     }
520 
521     /**
522      * Updates a cached service for a given user.
523      */
524     @GuardedBy("mLock")
updateCachedServiceLocked(@serIdInt int userId)525     protected void updateCachedServiceLocked(@UserIdInt int userId) {
526         updateCachedServiceLocked(userId, isDisabledLocked(userId));
527     }
528 
529     /**
530      * Checks whether the service is disabled (through {@link UserManager} restrictions) for the
531      * given user.
532      */
isDisabledLocked(@serIdInt int userId)533     protected boolean isDisabledLocked(@UserIdInt int userId) {
534         return mDisabledByUserRestriction == null ? false : mDisabledByUserRestriction.get(userId);
535     }
536 
537     /**
538      * Updates a cached service for a given user.
539      *
540      * @param userId user handle.
541      * @param disabled whether the user is disabled.
542      * @return service for the user.
543      */
544     @GuardedBy("mLock")
updateCachedServiceLocked(@serIdInt int userId, boolean disabled)545     protected S updateCachedServiceLocked(@UserIdInt int userId, boolean disabled) {
546         final S service = getServiceForUserLocked(userId);
547         if (service != null) {
548             service.updateLocked(disabled);
549             if (!service.isEnabledLocked()) {
550                 removeCachedServiceLocked(userId);
551             } else {
552                 onServiceEnabledLocked(service, userId);
553             }
554         }
555         return service;
556     }
557 
558     /**
559      * Gets the Settings property that defines the name of the component name used to bind this
560      * service to an external service, or {@code null} when the service is not defined by such
561      * property (for example, if it's a system service defined by framework resources).
562      */
563     @Nullable
getServiceSettingsProperty()564     protected String getServiceSettingsProperty() {
565         return null;
566     }
567 
568     /**
569      * Callback called after a new service was added to the cache, or an existing service that was
570      * previously disabled gets enabled.
571      *
572      * <p>By default doesn't do anything, but can be overridden by subclasses.
573      */
574     @SuppressWarnings("unused")
onServiceEnabledLocked(@onNull S service, @UserIdInt int userId)575     protected void onServiceEnabledLocked(@NonNull S service, @UserIdInt int userId) {
576     }
577 
578     /**
579      * Removes a cached service for a given user.
580      *
581      * @return the removed service.
582      */
583     @GuardedBy("mLock")
584     @NonNull
removeCachedServiceLocked(@serIdInt int userId)585     protected final S removeCachedServiceLocked(@UserIdInt int userId) {
586         final S service = peekServiceForUserLocked(userId);
587         if (service != null) {
588             mServicesCache.delete(userId);
589             onServiceRemoved(service, userId);
590         }
591         return service;
592     }
593 
594     /**
595      * Called before the package that provides the service for the given user is being updated.
596      */
onServicePackageUpdatingLocked(@serIdInt int userId)597     protected void onServicePackageUpdatingLocked(@UserIdInt int userId) {
598         if (verbose) Slog.v(mTag, "onServicePackageUpdatingLocked(" + userId + ")");
599     }
600 
601     /**
602      * Called after the package that provides the service for the given user is being updated.
603      */
onServicePackageUpdatedLocked(@serIdInt int userId)604     protected void onServicePackageUpdatedLocked(@UserIdInt int userId) {
605         if (verbose) Slog.v(mTag, "onServicePackageUpdated(" + userId + ")");
606     }
607 
608     /**
609      * Called after the service is removed from the cache.
610      */
611     @SuppressWarnings("unused")
onServiceRemoved(@onNull S service, @UserIdInt int userId)612     protected void onServiceRemoved(@NonNull S service, @UserIdInt int userId) {
613     }
614 
615     /**
616      * Called when the service name changed (typically when using temporary services).
617      *
618      * <p>By default, it calls {@link #updateCachedServiceLocked(int)}; subclasses must either call
619      * that same method, or {@code super.onServiceNameChanged()}.
620      *
621      * @param userId user handle.
622      * @param serviceName the new service name.
623      * @param isTemporary whether the new service is temporary.
624      */
onServiceNameChanged(@serIdInt int userId, @Nullable String serviceName, boolean isTemporary)625     protected void onServiceNameChanged(@UserIdInt int userId, @Nullable String serviceName,
626             boolean isTemporary) {
627         synchronized (mLock) {
628             updateCachedServiceLocked(userId);
629         }
630     }
631 
632     /**
633      * Visits all services in the cache.
634      */
635     @GuardedBy("mLock")
visitServicesLocked(@onNull Visitor<S> visitor)636     protected void visitServicesLocked(@NonNull Visitor<S> visitor) {
637         final int size = mServicesCache.size();
638         for (int i = 0; i < size; i++) {
639             visitor.visit(mServicesCache.valueAt(i));
640         }
641     }
642 
643     /**
644      * Clear the cache by removing all services.
645      */
646     @GuardedBy("mLock")
clearCacheLocked()647     protected void clearCacheLocked() {
648         mServicesCache.clear();
649     }
650 
651     /**
652      * Asserts that the given package name is owned by the UID making this call.
653      *
654      * @throws SecurityException when it's not...
655      */
assertCalledByPackageOwner(@onNull String packageName)656     protected final void assertCalledByPackageOwner(@NonNull String packageName) {
657         Preconditions.checkNotNull(packageName);
658         final int uid = Binder.getCallingUid();
659         final String[] packages = getContext().getPackageManager().getPackagesForUid(uid);
660         if (packages != null) {
661             for (String candidate : packages) {
662                 if (packageName.equals(candidate)) return; // Found it
663             }
664         }
665         throw new SecurityException("UID " + uid + " does not own " + packageName);
666     }
667 
668     // TODO(b/117779333): support proto
dumpLocked(@onNull String prefix, @NonNull PrintWriter pw)669     protected void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
670         boolean realDebug = debug;
671         boolean realVerbose = verbose;
672         final String prefix2 = "    ";
673 
674         try {
675             // Temporarily turn on full logging;
676             debug = verbose = true;
677             final int size = mServicesCache.size();
678             pw.print(prefix); pw.print("Debug: "); pw.print(realDebug);
679             pw.print(" Verbose: "); pw.println(realVerbose);
680             pw.print("Refresh on package update: "); pw.println(mPackageUpdatePolicy);
681             if (mUpdatingPackageNames != null) {
682                 pw.print("Packages being updated: "); pw.println(mUpdatingPackageNames);
683             }
684             if (mServiceNameResolver != null) {
685                 pw.print(prefix); pw.print("Name resolver: ");
686                 mServiceNameResolver.dumpShort(pw); pw.println();
687                 final UserManager um = getContext().getSystemService(UserManager.class);
688                 final List<UserInfo> users = um.getUsers();
689                 for (int i = 0; i < users.size(); i++) {
690                     final int userId = users.get(i).id;
691                     pw.print(prefix2); pw.print(userId); pw.print(": ");
692                     mServiceNameResolver.dumpShort(pw, userId); pw.println();
693                 }
694             }
695             pw.print(prefix); pw.print("Users disabled by restriction: ");
696             pw.println(mDisabledByUserRestriction);
697             pw.print(prefix); pw.print("Allow instant service: "); pw.println(mAllowInstantService);
698             final String settingsProperty = getServiceSettingsProperty();
699             if (settingsProperty != null) {
700                 pw.print(prefix); pw.print("Settings property: "); pw.println(settingsProperty);
701             }
702             pw.print(prefix); pw.print("Cached services: ");
703             if (size == 0) {
704                 pw.println("none");
705             } else {
706                 pw.println(size);
707                 for (int i = 0; i < size; i++) {
708                     pw.print(prefix); pw.print("Service at "); pw.print(i); pw.println(": ");
709                     final S service = mServicesCache.valueAt(i);
710                     service.dumpLocked(prefix2, pw);
711                     pw.println();
712                 }
713             }
714         } finally {
715             debug = realDebug;
716             verbose = realVerbose;
717         }
718     }
719 
startTrackingPackageChanges()720     private void startTrackingPackageChanges() {
721         final PackageMonitor monitor = new PackageMonitor() {
722 
723             @Override
724             public void onPackageUpdateStarted(@NonNull String packageName, int uid) {
725                 if (verbose) Slog.v(mTag, "onPackageUpdateStarted(): " + packageName);
726                 final String activePackageName = getActiveServicePackageNameLocked();
727                 if (!packageName.equals(activePackageName)) return;
728 
729                 final int userId = getChangingUserId();
730                 synchronized (mLock) {
731                     if (mUpdatingPackageNames == null) {
732                         mUpdatingPackageNames = new SparseArray<String>(mServicesCache.size());
733                     }
734                     mUpdatingPackageNames.put(userId, packageName);
735                     onServicePackageUpdatingLocked(userId);
736                     if (mPackageUpdatePolicy != PACKAGE_UPDATE_POLICY_NO_REFRESH) {
737                         if (debug) {
738                             Slog.d(mTag, "Removing service for user " + userId
739                                     + " because package " + activePackageName
740                                     + " is being updated");
741                         }
742                         removeCachedServiceLocked(userId);
743 
744                         if (mPackageUpdatePolicy == PACKAGE_UPDATE_POLICY_REFRESH_EAGER) {
745                             if (debug) {
746                                 Slog.d(mTag, "Eagerly recreating service for user "
747                                         + userId);
748                             }
749                             getServiceForUserLocked(userId);
750                         }
751                     } else {
752                         if (debug) {
753                             Slog.d(mTag, "Holding service for user " + userId + " while package "
754                                     + activePackageName + " is being updated");
755                         }
756                     }
757                 }
758             }
759 
760             @Override
761             public void onPackageUpdateFinished(@NonNull String packageName, int uid) {
762                 if (verbose) Slog.v(mTag, "onPackageUpdateFinished(): " + packageName);
763                 final int userId = getChangingUserId();
764                 synchronized (mLock) {
765                     final String activePackageName = mUpdatingPackageNames == null ? null
766                             : mUpdatingPackageNames.get(userId);
767                     if (packageName.equals(activePackageName)) {
768                         if (mUpdatingPackageNames != null) {
769                             mUpdatingPackageNames.remove(userId);
770                             if (mUpdatingPackageNames.size() == 0) {
771                                 mUpdatingPackageNames = null;
772                             }
773                         }
774                         onServicePackageUpdatedLocked(userId);
775                     } else {
776                         handlePackageUpdateLocked(packageName);
777                     }
778                 }
779             }
780 
781             @Override
782             public void onPackageRemoved(String packageName, int uid) {
783                 synchronized (mLock) {
784                     final int userId = getChangingUserId();
785                     final S service = peekServiceForUserLocked(userId);
786                     if (service != null) {
787                         final ComponentName componentName = service.getServiceComponentName();
788                         if (componentName != null) {
789                             if (packageName.equals(componentName.getPackageName())) {
790                                 handleActiveServiceRemoved(userId);
791                             }
792                         }
793                     }
794                 }
795             }
796 
797             @Override
798             public boolean onHandleForceStop(Intent intent, String[] packages,
799                     int uid, boolean doit) {
800                 synchronized (mLock) {
801                     final String activePackageName = getActiveServicePackageNameLocked();
802                     for (String pkg : packages) {
803                         if (pkg.equals(activePackageName)) {
804                             if (!doit) {
805                                 return true;
806                             }
807                             removeCachedServiceLocked(getChangingUserId());
808                         } else {
809                             handlePackageUpdateLocked(pkg);
810                         }
811                     }
812                 }
813                 return false;
814             }
815 
816             private void handleActiveServiceRemoved(@UserIdInt int userId) {
817                 synchronized (mLock) {
818                     removeCachedServiceLocked(userId);
819                 }
820                 final String serviceSettingsProperty = getServiceSettingsProperty();
821                 if (serviceSettingsProperty != null) {
822                     Settings.Secure.putStringForUser(getContext().getContentResolver(),
823                             serviceSettingsProperty, null, userId);
824                 }
825             }
826 
827             private String getActiveServicePackageNameLocked() {
828                 final int userId = getChangingUserId();
829                 final S service = peekServiceForUserLocked(userId);
830                 if (service == null) {
831                     return null;
832                 }
833                 final ComponentName serviceComponent = service.getServiceComponentName();
834                 if (serviceComponent == null) {
835                     return null;
836                 }
837                 return serviceComponent.getPackageName();
838             }
839 
840             @GuardedBy("mLock")
841             private void handlePackageUpdateLocked(String packageName) {
842                 visitServicesLocked((s) -> s.handlePackageUpdateLocked(packageName));
843             }
844         };
845 
846         // package changes
847         monitor.register(getContext(), null,  UserHandle.ALL, true);
848     }
849 
850     /**
851      * Visitor pattern.
852      *
853      * @param <S> visited class.
854      */
855     public interface Visitor<S> {
856         /**
857          * Visits a service.
858          *
859          * @param service the service to be visited.
860          */
visit(@onNull S service)861         void visit(@NonNull S service);
862     }
863 
864     private final class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler)865         SettingsObserver(Handler handler) {
866             super(handler);
867             ContentResolver resolver = getContext().getContentResolver();
868             final String serviceProperty = getServiceSettingsProperty();
869             if (serviceProperty != null) {
870                 resolver.registerContentObserver(Settings.Secure.getUriFor(
871                         serviceProperty), false, this, UserHandle.USER_ALL);
872             }
873             resolver.registerContentObserver(Settings.Secure.getUriFor(
874                     Settings.Secure.USER_SETUP_COMPLETE), false, this, UserHandle.USER_ALL);
875             registerForExtraSettingsChanges(resolver, this);
876         }
877 
878         @Override
onChange(boolean selfChange, Uri uri, @UserIdInt int userId)879         public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) {
880             if (verbose) Slog.v(mTag, "onChange(): uri=" + uri + ", userId=" + userId);
881             final String property = uri.getLastPathSegment();
882             if (property.equals(getServiceSettingsProperty())
883                     || property.equals(Settings.Secure.USER_SETUP_COMPLETE)) {
884                 synchronized (mLock) {
885                     updateCachedServiceLocked(userId);
886                 }
887             } else {
888                 onSettingsChanged(userId, property);
889             }
890         }
891     }
892 }
893