• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.server.LocalServices;
45 import com.android.server.SystemService;
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.List;
52 import java.util.Objects;
53 
54 /**
55  * Base class for {@link SystemService SystemServices} that support multi user.
56  *
57  * <p>Subclasses of this service are just a facade for the service binder calls - the "real" work
58  * is done by the {@link AbstractPerUserSystemService} subclasses, which are automatically managed
59  * through an user -> service cache.
60  *
61  * <p>It also takes care of other plumbing tasks such as:
62  *
63  * <ul>
64  *   <li>Disabling the service when {@link UserManager} restrictions change.
65  *   <li>Refreshing the service when its underlying
66  *   {@link #getServiceSettingsProperty() Settings property} changed.
67  *   <li>Calling the service when other Settings properties changed.
68  * </ul>
69  *
70  * <p>See {@code com.android.server.autofill.AutofillManagerService} for a concrete
71  * (no pun intended) example of how to use it.
72  *
73  * @param <M> "master" service class.
74  * @param <S> "real" service class.
75  *
76  * @hide
77  */
78 // TODO(b/117779333): improve javadoc above instead of using Autofill as an example
79 public abstract class AbstractMasterSystemService<M extends AbstractMasterSystemService<M, S>,
80         S extends AbstractPerUserSystemService<S, M>> extends SystemService {
81 
82     /** On a package update, does not refresh the per-user service in the cache. */
83     public static final int PACKAGE_UPDATE_POLICY_NO_REFRESH = 0x00000001;
84 
85     /**
86      * On a package update, removes any existing per-user services in the cache.
87      *
88      * <p>This does not immediately recreate these services. It is assumed they will be recreated
89      * for the next user request.
90      */
91     public static final int PACKAGE_UPDATE_POLICY_REFRESH_LAZY = 0x00000002;
92 
93     /**
94      * On a package update, removes and recreates any existing per-user services in the cache.
95      */
96     public static final int PACKAGE_UPDATE_POLICY_REFRESH_EAGER = 0x00000004;
97 
98     /** On a package restart, does not refresh the per-user service in the cache. */
99     public static final int PACKAGE_RESTART_POLICY_NO_REFRESH = 0x00000010;
100 
101     /**
102      * On a package restart, removes any existing per-user services in the cache.
103      *
104      * <p>This does not immediately recreate these services. It is assumed they will be recreated
105      * for the next user request.
106      */
107     public static final int PACKAGE_RESTART_POLICY_REFRESH_LAZY = 0x00000020;
108 
109     /**
110      * On a package restart, removes and recreates any existing per-user services in the cache.
111      */
112     public static final int PACKAGE_RESTART_POLICY_REFRESH_EAGER = 0x00000040;
113 
114     @IntDef(flag = true, prefix = { "PACKAGE_" }, value = {
115             PACKAGE_UPDATE_POLICY_NO_REFRESH,
116             PACKAGE_UPDATE_POLICY_REFRESH_LAZY,
117             PACKAGE_UPDATE_POLICY_REFRESH_EAGER,
118             PACKAGE_RESTART_POLICY_NO_REFRESH,
119             PACKAGE_RESTART_POLICY_REFRESH_LAZY,
120             PACKAGE_RESTART_POLICY_REFRESH_EAGER
121     })
122 
123     @Retention(RetentionPolicy.SOURCE)
124     public @interface ServicePackagePolicyFlags {}
125 
126     /**
127      * Log tag
128      */
129     protected final String mTag = getClass().getSimpleName();
130 
131     /**
132      * Lock used to synchronize access to internal state; should be acquired before calling a
133      * method whose name ends with {@code locked}.
134      */
135     protected final Object mLock = new Object();
136 
137     /**
138      * Object used to define the name of the service component used to create
139      * {@link com.android.internal.infra.AbstractRemoteService} instances.
140      */
141     @Nullable
142     protected final ServiceNameResolver mServiceNameResolver;
143 
144     /**
145      * Whether the service should log debug statements.
146      */
147     //TODO(b/117779333): consider using constants for these guards
148     public boolean verbose = false;
149 
150     /**
151      * Whether the service should log verbose statements.
152      */
153     //TODO(b/117779333): consider using constants for these guards
154     public boolean debug = false;
155 
156     /**
157      * Whether the service is allowed to bind to an instant-app.
158      */
159     @GuardedBy("mLock")
160     protected boolean mAllowInstantService;
161 
162     /**
163      * Users disabled due to {@link UserManager} restrictions, or {@code null} if the service cannot
164      * be disabled through {@link UserManager}.
165      */
166     @GuardedBy("mLock")
167     @Nullable
168     private final SparseBooleanArray mDisabledByUserRestriction;
169 
170     /**
171      * Cache of services per user id.
172      */
173     @GuardedBy("mLock")
174     private final SparseArray<S> mServicesCache = new SparseArray<>();
175 
176     /**
177      * Value that determines whether the per-user service should be removed from the cache when its
178      * apk is updated or restarted.
179      */
180     private final @ServicePackagePolicyFlags int mServicePackagePolicyFlags;
181 
182     /**
183      * Name of the service packages whose APK are being updated, keyed by user id.
184      */
185     @GuardedBy("mLock")
186     private SparseArray<String> mUpdatingPackageNames;
187 
188     /**
189      * Lazy-loadable reference to {@link UserManagerInternal}.
190      */
191     @Nullable
192     private UserManagerInternal mUm;
193 
194     /**
195      * Default constructor.
196      *
197      * <p>When using this constructor, the {@link AbstractPerUserSystemService} is removed from
198      * the cache (and re-added) when the service package is updated.
199      *
200      * @param context system context.
201      * @param serviceNameResolver resolver for
202      * {@link com.android.internal.infra.AbstractRemoteService} instances, or
203      * {@code null} when the service doesn't bind to remote services.
204      * @param disallowProperty when not {@code null}, defines a {@link UserManager} restriction that
205      *        disables the service. <b>NOTE: </b> you'll also need to add it to
206      *        {@code UserRestrictionsUtils.USER_RESTRICTIONS}.
207      */
AbstractMasterSystemService(@onNull Context context, @Nullable ServiceNameResolver serviceNameResolver, @Nullable String disallowProperty)208     protected AbstractMasterSystemService(@NonNull Context context,
209             @Nullable ServiceNameResolver serviceNameResolver,
210             @Nullable String disallowProperty) {
211         this(context, serviceNameResolver, disallowProperty,
212                 PACKAGE_UPDATE_POLICY_REFRESH_LAZY | PACKAGE_RESTART_POLICY_REFRESH_LAZY);
213     }
214 
215     /**
216      * Full Constructor.
217      *
218      * @param context system context.
219      * @param serviceNameResolver resolver for
220      * {@link com.android.internal.infra.AbstractRemoteService} instances, or
221      * {@code null} when the service doesn't bind to remote services.
222      * @param disallowProperty when not {@code null}, defines a {@link UserManager} restriction that
223      *        disables the service. <b>NOTE: </b> you'll also need to add it to
224      *        {@code UserRestrictionsUtils.USER_RESTRICTIONS}.
225      * @param servicePackagePolicyFlags a combination of
226      *        {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH},
227      *        {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY},
228      *        {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER},
229      *        {@link #PACKAGE_RESTART_POLICY_NO_REFRESH},
230      *        {@link #PACKAGE_RESTART_POLICY_REFRESH_LAZY} or
231      *        {@link #PACKAGE_RESTART_POLICY_REFRESH_EAGER}
232      */
AbstractMasterSystemService(@onNull Context context, @Nullable ServiceNameResolver serviceNameResolver, @Nullable String disallowProperty, @ServicePackagePolicyFlags int servicePackagePolicyFlags)233     protected AbstractMasterSystemService(@NonNull Context context,
234             @Nullable ServiceNameResolver serviceNameResolver, @Nullable String disallowProperty,
235             @ServicePackagePolicyFlags int servicePackagePolicyFlags) {
236         super(context);
237 
238         final int updatePolicyMask = PACKAGE_UPDATE_POLICY_NO_REFRESH
239                 | PACKAGE_UPDATE_POLICY_REFRESH_LAZY | PACKAGE_UPDATE_POLICY_REFRESH_EAGER;
240         if ((servicePackagePolicyFlags & updatePolicyMask) == 0) {
241             // If the package update policy is not set, add the default flag
242             servicePackagePolicyFlags |= PACKAGE_UPDATE_POLICY_REFRESH_LAZY;
243         }
244         final int restartPolicyMask = PACKAGE_RESTART_POLICY_NO_REFRESH
245                 | PACKAGE_RESTART_POLICY_REFRESH_LAZY | PACKAGE_RESTART_POLICY_REFRESH_EAGER;
246         if ((servicePackagePolicyFlags & restartPolicyMask) == 0) {
247             // If the package restart policy is not set, add the default flag
248             servicePackagePolicyFlags |= PACKAGE_RESTART_POLICY_REFRESH_LAZY;
249         }
250         mServicePackagePolicyFlags = servicePackagePolicyFlags;
251 
252         mServiceNameResolver = serviceNameResolver;
253         if (mServiceNameResolver != null) {
254             mServiceNameResolver.setOnTemporaryServiceNameChangedCallback(
255                     (u, s, t) -> onServiceNameChanged(u, s, t));
256 
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
onUnlockUser(int userId)302     public void onUnlockUser(int userId) {
303         synchronized (mLock) {
304             updateCachedServiceLocked(userId);
305         }
306     }
307 
308     @Override // from SystemService
onCleanupUser(int userId)309     public void onCleanupUser(int userId) {
310         synchronized (mLock) {
311             removeCachedServiceLocked(userId);
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         enforceCallingPermissionForManagement();
375 
376         Objects.requireNonNull(componentName);
377         final int maxDurationMs = getMaximumTemporaryServiceDurationMs();
378         if (durationMs > maxDurationMs) {
379             throw new IllegalArgumentException(
380                     "Max duration is " + maxDurationMs + " (called with " + durationMs + ")");
381         }
382 
383         synchronized (mLock) {
384             final S oldService = peekServiceForUserLocked(userId);
385             if (oldService != null) {
386                 oldService.removeSelfFromCacheLocked();
387             }
388             mServiceNameResolver.setTemporaryService(userId, componentName, durationMs);
389         }
390     }
391 
392     /**
393      * Sets whether the default service should be used.
394      *
395      * <p>Typically used during CTS tests to make sure only the default service doesn't interfere
396      * with the test results.
397      *
398      * @throws SecurityException if caller is not allowed to manage this service's settings.
399      *
400      * @return whether the enabled state changed.
401      */
setDefaultServiceEnabled(@serIdInt int userId, boolean enabled)402     public final boolean setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) {
403         Slog.i(mTag, "setDefaultServiceEnabled() for userId " + userId + ": " + enabled);
404         enforceCallingPermissionForManagement();
405 
406         synchronized (mLock) {
407             final boolean changed = mServiceNameResolver.setDefaultServiceEnabled(userId, enabled);
408             if (!changed) {
409                 if (verbose) {
410                     Slog.v(mTag, "setDefaultServiceEnabled(" + userId + "): already " + enabled);
411                 }
412                 return false;
413             }
414 
415             final S oldService = peekServiceForUserLocked(userId);
416             if (oldService != null) {
417                 oldService.removeSelfFromCacheLocked();
418             }
419 
420             // Must update the service on cache so its initialization code is triggered
421             updateCachedServiceLocked(userId);
422         }
423         return true;
424     }
425 
426     /**
427      * Checks whether the default service should be used.
428      *
429      * <p>Typically used during CTS tests to make sure only the default service doesn't interfere
430      * with the test results.
431      *
432      * @throws SecurityException if caller is not allowed to manage this service's settings.
433      */
isDefaultServiceEnabled(@serIdInt int userId)434     public final boolean isDefaultServiceEnabled(@UserIdInt int userId) {
435         enforceCallingPermissionForManagement();
436 
437         synchronized (mLock) {
438             return mServiceNameResolver.isDefaultServiceEnabled(userId);
439         }
440     }
441 
442     /**
443      * Gets the maximum time the service implementation can be changed.
444      *
445      * @throws UnsupportedOperationException if subclass doesn't override it.
446      */
getMaximumTemporaryServiceDurationMs()447     protected int getMaximumTemporaryServiceDurationMs() {
448         throw new UnsupportedOperationException("Not implemented by " + getClass());
449     }
450 
451     /**
452      * Resets the temporary service implementation to the default component.
453      *
454      * <p>Typically used by Shell command and/or CTS tests.
455      *
456      * @throws SecurityException if caller is not allowed to manage this service's settings.
457      */
resetTemporaryService(@serIdInt int userId)458     public final void resetTemporaryService(@UserIdInt int userId) {
459         Slog.i(mTag, "resetTemporaryService(): " + userId);
460         enforceCallingPermissionForManagement();
461         synchronized (mLock) {
462             final S service = getServiceForUserLocked(userId);
463             if (service != null) {
464                 service.resetTemporaryServiceLocked();
465             }
466         }
467     }
468 
469     /**
470      * Asserts that the caller has permissions to manage this service.
471      *
472      * <p>Typically called by {@code ShellCommand} implementations.
473      *
474      * @throws UnsupportedOperationException if subclass doesn't override it.
475      * @throws SecurityException if caller is not allowed to manage this service's settings.
476      */
enforceCallingPermissionForManagement()477     protected void enforceCallingPermissionForManagement() {
478         throw new UnsupportedOperationException("Not implemented by " + getClass());
479     }
480 
481     /**
482      * Creates a new service that will be added to the cache.
483      *
484      * @param resolvedUserId the resolved user id for the service.
485      * @param disabled whether the service is currently disabled (due to {@link UserManager}
486      * restrictions).
487      *
488      * @return a new instance.
489      */
490     @Nullable
newServiceLocked(@serIdInt int resolvedUserId, boolean disabled)491     protected abstract S newServiceLocked(@UserIdInt int resolvedUserId, boolean disabled);
492 
493     /**
494      * Register the service for extra Settings changes (i.e., other than
495      * {@link android.provider.Settings.Secure#USER_SETUP_COMPLETE} or
496      * {@link #getServiceSettingsProperty()}, which are automatically handled).
497      *
498      * <p> Example:
499      *
500      * <pre><code>
501      * resolver.registerContentObserver(Settings.Global.getUriFor(
502      *     Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES), false, observer,
503      *     UserHandle.USER_ALL);
504      * </code></pre>
505      *
506      * <p><b>NOTE: </p>it doesn't need to register for
507      * {@link android.provider.Settings.Secure#USER_SETUP_COMPLETE} or
508      * {@link #getServiceSettingsProperty()}.
509      *
510      */
511     @SuppressWarnings("unused")
registerForExtraSettingsChanges(@onNull ContentResolver resolver, @NonNull ContentObserver observer)512     protected void registerForExtraSettingsChanges(@NonNull ContentResolver resolver,
513             @NonNull ContentObserver observer) {
514     }
515 
516     /**
517      * Callback for Settings changes that were registered though
518      * {@link #registerForExtraSettingsChanges(ContentResolver, ContentObserver)}.
519      *
520      * @param userId user associated with the change
521      * @param property Settings property changed.
522      */
onSettingsChanged(@serIdInt int userId, @NonNull String property)523     protected void onSettingsChanged(@UserIdInt int userId, @NonNull String property) {
524     }
525 
526     /**
527      * Gets the service instance for an user, creating an instance if not present in the cache.
528      */
529     @GuardedBy("mLock")
530     @NonNull
getServiceForUserLocked(@serIdInt int userId)531     protected S getServiceForUserLocked(@UserIdInt int userId) {
532         final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
533                 Binder.getCallingUid(), userId, false, false, null, null);
534         S service = mServicesCache.get(resolvedUserId);
535         if (service == null) {
536             final boolean disabled = isDisabledLocked(userId);
537             service = newServiceLocked(resolvedUserId, disabled);
538             if (!disabled) {
539                 onServiceEnabledLocked(service, resolvedUserId);
540             }
541             mServicesCache.put(userId, service);
542         }
543         return service;
544     }
545 
546     /**
547      * Gets the <b>existing</b> service instance for a user, returning {@code null} if not already
548      * present in the cache.
549      */
550     @GuardedBy("mLock")
551     @Nullable
peekServiceForUserLocked(@serIdInt int userId)552     protected S peekServiceForUserLocked(@UserIdInt int userId) {
553         final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
554                 Binder.getCallingUid(), userId, false, false, null, null);
555         return mServicesCache.get(resolvedUserId);
556     }
557 
558     /**
559      * Updates a cached service for a given user.
560      */
561     @GuardedBy("mLock")
updateCachedServiceLocked(@serIdInt int userId)562     protected void updateCachedServiceLocked(@UserIdInt int userId) {
563         updateCachedServiceLocked(userId, isDisabledLocked(userId));
564     }
565 
566     /**
567      * Checks whether the service is disabled (through {@link UserManager} restrictions) for the
568      * given user.
569      */
isDisabledLocked(@serIdInt int userId)570     protected boolean isDisabledLocked(@UserIdInt int userId) {
571         return mDisabledByUserRestriction == null ? false : mDisabledByUserRestriction.get(userId);
572     }
573 
574     /**
575      * Updates a cached service for a given user.
576      *
577      * @param userId user handle.
578      * @param disabled whether the user is disabled.
579      * @return service for the user.
580      */
581     @GuardedBy("mLock")
updateCachedServiceLocked(@serIdInt int userId, boolean disabled)582     protected S updateCachedServiceLocked(@UserIdInt int userId, boolean disabled) {
583         final S service = getServiceForUserLocked(userId);
584         if (service != null) {
585             service.updateLocked(disabled);
586             if (!service.isEnabledLocked()) {
587                 removeCachedServiceLocked(userId);
588             } else {
589                 onServiceEnabledLocked(service, userId);
590             }
591         }
592         return service;
593     }
594 
595     /**
596      * Gets the Settings property that defines the name of the component name used to bind this
597      * service to an external service, or {@code null} when the service is not defined by such
598      * property (for example, if it's a system service defined by framework resources).
599      */
600     @Nullable
getServiceSettingsProperty()601     protected String getServiceSettingsProperty() {
602         return null;
603     }
604 
605     /**
606      * Callback called after a new service was added to the cache, or an existing service that was
607      * previously disabled gets enabled.
608      *
609      * <p>By default doesn't do anything, but can be overridden by subclasses.
610      */
611     @SuppressWarnings("unused")
onServiceEnabledLocked(@onNull S service, @UserIdInt int userId)612     protected void onServiceEnabledLocked(@NonNull S service, @UserIdInt int userId) {
613     }
614 
615     /**
616      * Removes a cached service for a given user.
617      *
618      * @return the removed service.
619      */
620     @GuardedBy("mLock")
621     @NonNull
removeCachedServiceLocked(@serIdInt int userId)622     protected final S removeCachedServiceLocked(@UserIdInt int userId) {
623         final S service = peekServiceForUserLocked(userId);
624         if (service != null) {
625             mServicesCache.delete(userId);
626             onServiceRemoved(service, userId);
627         }
628         return service;
629     }
630 
631     /**
632      * Called before the package that provides the service for the given user is being updated.
633      */
onServicePackageUpdatingLocked(@serIdInt int userId)634     protected void onServicePackageUpdatingLocked(@UserIdInt int userId) {
635         if (verbose) Slog.v(mTag, "onServicePackageUpdatingLocked(" + userId + ")");
636     }
637 
638     /**
639      * Called after the package that provides the service for the given user is being updated.
640      */
onServicePackageUpdatedLocked(@serIdInt int userId)641     protected void onServicePackageUpdatedLocked(@UserIdInt int userId) {
642         if (verbose) Slog.v(mTag, "onServicePackageUpdated(" + userId + ")");
643     }
644 
645     /**
646      * Called after the package data that provides the service for the given user is cleared.
647      */
onServicePackageDataClearedLocked(@serIdInt int userId)648     protected void onServicePackageDataClearedLocked(@UserIdInt int userId) {
649         if (verbose) Slog.v(mTag, "onServicePackageDataCleared(" + userId + ")");
650     }
651 
652     /**
653      * Called after the package that provides the service for the given user is restarted.
654      */
onServicePackageRestartedLocked(@serIdInt int userId)655     protected void onServicePackageRestartedLocked(@UserIdInt int userId) {
656         if (verbose) Slog.v(mTag, "onServicePackageRestarted(" + userId + ")");
657     }
658 
659     /**
660      * Called after the service is removed from the cache.
661      */
662     @SuppressWarnings("unused")
onServiceRemoved(@onNull S service, @UserIdInt int userId)663     protected void onServiceRemoved(@NonNull S service, @UserIdInt int userId) {
664     }
665 
666     /**
667      * Called when the service name changed (typically when using temporary services).
668      *
669      * <p>By default, it calls {@link #updateCachedServiceLocked(int)}; subclasses must either call
670      * that same method, or {@code super.onServiceNameChanged()}.
671      *
672      * @param userId user handle.
673      * @param serviceName the new service name.
674      * @param isTemporary whether the new service is temporary.
675      */
onServiceNameChanged(@serIdInt int userId, @Nullable String serviceName, boolean isTemporary)676     protected void onServiceNameChanged(@UserIdInt int userId, @Nullable String serviceName,
677             boolean isTemporary) {
678         synchronized (mLock) {
679             updateCachedServiceLocked(userId);
680         }
681     }
682 
683     /**
684      * Visits all services in the cache.
685      */
686     @GuardedBy("mLock")
visitServicesLocked(@onNull Visitor<S> visitor)687     protected void visitServicesLocked(@NonNull Visitor<S> visitor) {
688         final int size = mServicesCache.size();
689         for (int i = 0; i < size; i++) {
690             visitor.visit(mServicesCache.valueAt(i));
691         }
692     }
693 
694     /**
695      * Clear the cache by removing all services.
696      */
697     @GuardedBy("mLock")
clearCacheLocked()698     protected void clearCacheLocked() {
699         mServicesCache.clear();
700     }
701 
702     /**
703      * Gets a cached reference to {@link UserManagerInternal}.
704      */
705     @NonNull
getUserManagerInternal()706     protected UserManagerInternal getUserManagerInternal() {
707         if (mUm == null) {
708             if (verbose) Slog.v(mTag, "lazy-loading UserManagerInternal");
709             mUm = LocalServices.getService(UserManagerInternal.class);
710         }
711         return mUm;
712     }
713 
714     /**
715      * Gets a list of all supported users (i.e., those that pass the
716      * {@link #isUserSupported(TargetUser)}check).
717      */
718     @NonNull
getSupportedUsers()719     protected List<UserInfo> getSupportedUsers() {
720         final UserInfo[] allUsers = getUserManagerInternal().getUserInfos();
721         final int size = allUsers.length;
722         final List<UserInfo> supportedUsers = new ArrayList<>(size);
723         for (int i = 0; i < size; i++) {
724             final UserInfo userInfo = allUsers[i];
725             if (isUserSupported(new TargetUser(userInfo))) {
726                 supportedUsers.add(userInfo);
727             }
728         }
729         return supportedUsers;
730     }
731 
732     /**
733      * Asserts that the given package name is owned by the UID making this call.
734      *
735      * @throws SecurityException when it's not...
736      */
assertCalledByPackageOwner(@onNull String packageName)737     protected final void assertCalledByPackageOwner(@NonNull String packageName) {
738         Objects.requireNonNull(packageName);
739         final int uid = Binder.getCallingUid();
740         final String[] packages = getContext().getPackageManager().getPackagesForUid(uid);
741         if (packages != null) {
742             for (String candidate : packages) {
743                 if (packageName.equals(candidate)) return; // Found it
744             }
745         }
746         throw new SecurityException("UID " + uid + " does not own " + packageName);
747     }
748 
749     // TODO(b/117779333): support proto
dumpLocked(@onNull String prefix, @NonNull PrintWriter pw)750     protected void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
751         boolean realDebug = debug;
752         boolean realVerbose = verbose;
753         final String prefix2 = "    ";
754 
755         try {
756             // Temporarily turn on full logging;
757             debug = verbose = true;
758             final int size = mServicesCache.size();
759             pw.print(prefix); pw.print("Debug: "); pw.print(realDebug);
760             pw.print(" Verbose: "); pw.println(realVerbose);
761             pw.print("Package policy flags: "); pw.println(mServicePackagePolicyFlags);
762             if (mUpdatingPackageNames != null) {
763                 pw.print("Packages being updated: "); pw.println(mUpdatingPackageNames);
764             }
765             dumpSupportedUsers(pw, prefix);
766             if (mServiceNameResolver != null) {
767                 pw.print(prefix); pw.print("Name resolver: ");
768                 mServiceNameResolver.dumpShort(pw); pw.println();
769                 final List<UserInfo> users = getSupportedUsers();
770                 for (int i = 0; i < users.size(); i++) {
771                     final int userId = users.get(i).id;
772                     pw.print(prefix2); pw.print(userId); pw.print(": ");
773                     mServiceNameResolver.dumpShort(pw, userId); pw.println();
774                 }
775             }
776             pw.print(prefix); pw.print("Users disabled by restriction: ");
777             pw.println(mDisabledByUserRestriction);
778             pw.print(prefix); pw.print("Allow instant service: "); pw.println(mAllowInstantService);
779             final String settingsProperty = getServiceSettingsProperty();
780             if (settingsProperty != null) {
781                 pw.print(prefix); pw.print("Settings property: "); pw.println(settingsProperty);
782             }
783             pw.print(prefix); pw.print("Cached services: ");
784             if (size == 0) {
785                 pw.println("none");
786             } else {
787                 pw.println(size);
788                 for (int i = 0; i < size; i++) {
789                     pw.print(prefix); pw.print("Service at "); pw.print(i); pw.println(": ");
790                     final S service = mServicesCache.valueAt(i);
791                     service.dumpLocked(prefix2, pw);
792                     pw.println();
793                 }
794             }
795         } finally {
796             debug = realDebug;
797             verbose = realVerbose;
798         }
799     }
800 
startTrackingPackageChanges()801     private void startTrackingPackageChanges() {
802         final PackageMonitor monitor = new PackageMonitor() {
803 
804             @Override
805             public void onPackageUpdateStarted(@NonNull String packageName, int uid) {
806                 if (verbose) Slog.v(mTag, "onPackageUpdateStarted(): " + packageName);
807                 final String activePackageName = getActiveServicePackageNameLocked();
808                 if (!packageName.equals(activePackageName)) return;
809 
810                 final int userId = getChangingUserId();
811                 synchronized (mLock) {
812                     if (mUpdatingPackageNames == null) {
813                         mUpdatingPackageNames = new SparseArray<String>(mServicesCache.size());
814                     }
815                     mUpdatingPackageNames.put(userId, packageName);
816                     onServicePackageUpdatingLocked(userId);
817                     if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_NO_REFRESH) != 0) {
818                         if (debug) {
819                             Slog.d(mTag, "Holding service for user " + userId + " while package "
820                                     + activePackageName + " is being updated");
821                         }
822                     } else {
823                         if (debug) {
824                             Slog.d(mTag, "Removing service for user " + userId
825                                     + " because package " + activePackageName
826                                     + " is being updated");
827                         }
828                         removeCachedServiceLocked(userId);
829 
830                         if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_REFRESH_EAGER)
831                                 != 0) {
832                             if (debug) {
833                                 Slog.d(mTag, "Eagerly recreating service for user "
834                                         + userId);
835                             }
836                             getServiceForUserLocked(userId);
837                         }
838                     }
839                 }
840             }
841 
842             @Override
843             public void onPackageUpdateFinished(@NonNull String packageName, int uid) {
844                 if (verbose) Slog.v(mTag, "onPackageUpdateFinished(): " + packageName);
845                 final int userId = getChangingUserId();
846                 synchronized (mLock) {
847                     final String activePackageName = mUpdatingPackageNames == null ? null
848                             : mUpdatingPackageNames.get(userId);
849                     if (packageName.equals(activePackageName)) {
850                         if (mUpdatingPackageNames != null) {
851                             mUpdatingPackageNames.remove(userId);
852                             if (mUpdatingPackageNames.size() == 0) {
853                                 mUpdatingPackageNames = null;
854                             }
855                         }
856                         onServicePackageUpdatedLocked(userId);
857                     } else {
858                         handlePackageUpdateLocked(packageName);
859                     }
860                 }
861             }
862 
863             @Override
864             public void onPackageRemoved(String packageName, int uid) {
865                 synchronized (mLock) {
866                     final int userId = getChangingUserId();
867                     final S service = peekServiceForUserLocked(userId);
868                     if (service != null) {
869                         final ComponentName componentName = service.getServiceComponentName();
870                         if (componentName != null) {
871                             if (packageName.equals(componentName.getPackageName())) {
872                                 handleActiveServiceRemoved(userId);
873                             }
874                         }
875                     }
876                 }
877             }
878 
879             @Override
880             public boolean onHandleForceStop(Intent intent, String[] packages,
881                     int uid, boolean doit) {
882                 synchronized (mLock) {
883                     final String activePackageName = getActiveServicePackageNameLocked();
884                     for (String pkg : packages) {
885                         if (pkg.equals(activePackageName)) {
886                             if (!doit) {
887                                 return true;
888                             }
889                             final String action = intent.getAction();
890                             final int userId = getChangingUserId();
891                             if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) {
892                                 handleActiveServiceRestartedLocked(activePackageName, userId);
893                             } else {
894                                 removeCachedServiceLocked(userId);
895                             }
896                         } else {
897                             handlePackageUpdateLocked(pkg);
898                         }
899                     }
900                 }
901                 return false;
902             }
903 
904             @Override
905             public void onPackageDataCleared(String packageName, int uid) {
906                 if (verbose) Slog.v(mTag, "onPackageDataCleared(): " + packageName);
907                 final int userId = getChangingUserId();
908                 synchronized (mLock) {
909                     final S service = peekServiceForUserLocked(userId);
910                     if (service != null) {
911                         final ComponentName componentName = service.getServiceComponentName();
912                         if (componentName != null) {
913                             if (packageName.equals(componentName.getPackageName())) {
914                                 onServicePackageDataClearedLocked(userId);
915                             }
916                         }
917                     }
918                 }
919             }
920 
921             private void handleActiveServiceRemoved(@UserIdInt int userId) {
922                 synchronized (mLock) {
923                     removeCachedServiceLocked(userId);
924                 }
925                 final String serviceSettingsProperty = getServiceSettingsProperty();
926                 if (serviceSettingsProperty != null) {
927                     Settings.Secure.putStringForUser(getContext().getContentResolver(),
928                             serviceSettingsProperty, null, userId);
929                 }
930             }
931 
932             private void handleActiveServiceRestartedLocked(String activePackageName,
933                     @UserIdInt int userId) {
934                 if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_NO_REFRESH) != 0) {
935                     if (debug) {
936                         Slog.d(mTag, "Holding service for user " + userId + " while package "
937                                 + activePackageName + " is being restarted");
938                     }
939                 } else {
940                     if (debug) {
941                         Slog.d(mTag, "Removing service for user " + userId
942                                 + " because package " + activePackageName
943                                 + " is being restarted");
944                     }
945                     removeCachedServiceLocked(userId);
946 
947                     if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_REFRESH_EAGER) != 0) {
948                         if (debug) {
949                             Slog.d(mTag, "Eagerly recreating service for user " + userId);
950                         }
951                         getServiceForUserLocked(userId);
952                     }
953                 }
954                 onServicePackageRestartedLocked(userId);
955             }
956 
957             @Override
958             public void onPackageModified(String packageName) {
959                 if (verbose) Slog.v(mTag, "onPackageModified(): " + packageName);
960 
961                 final int userId = getChangingUserId();
962                 final String serviceName = mServiceNameResolver.getDefaultServiceName(userId);
963                 if (serviceName == null) {
964                     return;
965                 }
966 
967                 final ComponentName serviceComponentName =
968                         ComponentName.unflattenFromString(serviceName);
969                 if (serviceComponentName == null
970                         || !serviceComponentName.getPackageName().equals(packageName)) {
971                     return;
972                 }
973 
974                 // The default service package has changed, update the cached if the service
975                 // exists but no active component.
976                 final S service = peekServiceForUserLocked(userId);
977                 if (service != null) {
978                     final ComponentName componentName = service.getServiceComponentName();
979                     if (componentName == null) {
980                         if (verbose) Slog.v(mTag, "update cached");
981                         updateCachedServiceLocked(userId);
982                     }
983                 }
984             }
985 
986             private String getActiveServicePackageNameLocked() {
987                 final int userId = getChangingUserId();
988                 final S service = peekServiceForUserLocked(userId);
989                 if (service == null) {
990                     return null;
991                 }
992                 final ComponentName serviceComponent = service.getServiceComponentName();
993                 if (serviceComponent == null) {
994                     return null;
995                 }
996                 return serviceComponent.getPackageName();
997             }
998 
999             @GuardedBy("mLock")
1000             private void handlePackageUpdateLocked(String packageName) {
1001                 visitServicesLocked((s) -> s.handlePackageUpdateLocked(packageName));
1002             }
1003         };
1004 
1005         // package changes
1006         monitor.register(getContext(), null,  UserHandle.ALL, true);
1007     }
1008 
1009     /**
1010      * Visitor pattern.
1011      *
1012      * @param <S> visited class.
1013      */
1014     public interface Visitor<S> {
1015         /**
1016          * Visits a service.
1017          *
1018          * @param service the service to be visited.
1019          */
visit(@onNull S service)1020         void visit(@NonNull S service);
1021     }
1022 
1023     private final class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler)1024         SettingsObserver(Handler handler) {
1025             super(handler);
1026             ContentResolver resolver = getContext().getContentResolver();
1027             final String serviceProperty = getServiceSettingsProperty();
1028             if (serviceProperty != null) {
1029                 resolver.registerContentObserver(Settings.Secure.getUriFor(
1030                         serviceProperty), false, this, UserHandle.USER_ALL);
1031             }
1032             resolver.registerContentObserver(Settings.Secure.getUriFor(
1033                     Settings.Secure.USER_SETUP_COMPLETE), false, this, UserHandle.USER_ALL);
1034             registerForExtraSettingsChanges(resolver, this);
1035         }
1036 
1037         @Override
onChange(boolean selfChange, Uri uri, @UserIdInt int userId)1038         public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) {
1039             if (verbose) Slog.v(mTag, "onChange(): uri=" + uri + ", userId=" + userId);
1040             final String property = uri.getLastPathSegment();
1041             if (property.equals(getServiceSettingsProperty())
1042                     || property.equals(Settings.Secure.USER_SETUP_COMPLETE)) {
1043                 synchronized (mLock) {
1044                     updateCachedServiceLocked(userId);
1045                 }
1046             } else {
1047                 onSettingsChanged(userId, property);
1048             }
1049         }
1050     }
1051 }
1052