• Home
  • 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.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.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> "main" 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
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             removeCachedServiceLocked(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.removeSelfFromCacheLocked();
390             }
391             mServiceNameResolver.setTemporaryService(userId, componentName, durationMs);
392         }
393     }
394 
395     /**
396      * Sets whether the default service should be used.
397      *
398      * <p>Typically used during CTS tests to make sure only the default service doesn't interfere
399      * with the test results.
400      *
401      * @throws SecurityException if caller is not allowed to manage this service's settings.
402      *
403      * @return whether the enabled state changed.
404      */
setDefaultServiceEnabled(@serIdInt int userId, boolean enabled)405     public final boolean setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) {
406         Slog.i(mTag, "setDefaultServiceEnabled() for userId " + userId + ": " + enabled);
407         enforceCallingPermissionForManagement();
408 
409         synchronized (mLock) {
410             if (mServiceNameResolver == null) {
411                 return false;
412             }
413             final boolean changed = mServiceNameResolver.setDefaultServiceEnabled(userId, enabled);
414             if (!changed) {
415                 if (verbose) {
416                     Slog.v(mTag, "setDefaultServiceEnabled(" + userId + "): already " + enabled);
417                 }
418                 return false;
419             }
420 
421             final S oldService = peekServiceForUserLocked(userId);
422             if (oldService != null) {
423                 oldService.removeSelfFromCacheLocked();
424             }
425 
426             // Must update the service on cache so its initialization code is triggered
427             updateCachedServiceLocked(userId);
428         }
429         return true;
430     }
431 
432     /**
433      * Checks whether the default service should be used.
434      *
435      * <p>Typically used during CTS tests to make sure only the default service doesn't interfere
436      * with the test results.
437      *
438      * @throws SecurityException if caller is not allowed to manage this service's settings.
439      */
isDefaultServiceEnabled(@serIdInt int userId)440     public final boolean isDefaultServiceEnabled(@UserIdInt int userId) {
441         enforceCallingPermissionForManagement();
442 
443         if (mServiceNameResolver == null) {
444             return false;
445         }
446 
447         synchronized (mLock) {
448             return mServiceNameResolver.isDefaultServiceEnabled(userId);
449         }
450     }
451 
452     /**
453      * Gets the maximum time the service implementation can be changed.
454      *
455      * @throws UnsupportedOperationException if subclass doesn't override it.
456      */
getMaximumTemporaryServiceDurationMs()457     protected int getMaximumTemporaryServiceDurationMs() {
458         throw new UnsupportedOperationException("Not implemented by " + getClass());
459     }
460 
461     /**
462      * Resets the temporary service implementation to the default component.
463      *
464      * <p>Typically used by Shell command and/or CTS tests.
465      *
466      * @throws SecurityException if caller is not allowed to manage this service's settings.
467      */
resetTemporaryService(@serIdInt int userId)468     public final void resetTemporaryService(@UserIdInt int userId) {
469         Slog.i(mTag, "resetTemporaryService(): " + userId);
470         enforceCallingPermissionForManagement();
471         synchronized (mLock) {
472             final S service = getServiceForUserLocked(userId);
473             if (service != null) {
474                 service.resetTemporaryServiceLocked();
475             }
476         }
477     }
478 
479     /**
480      * Asserts that the caller has permissions to manage this service.
481      *
482      * <p>Typically called by {@code ShellCommand} implementations.
483      *
484      * @throws UnsupportedOperationException if subclass doesn't override it.
485      * @throws SecurityException if caller is not allowed to manage this service's settings.
486      */
enforceCallingPermissionForManagement()487     protected void enforceCallingPermissionForManagement() {
488         throw new UnsupportedOperationException("Not implemented by " + getClass());
489     }
490 
491     /**
492      * Creates a new service that will be added to the cache.
493      *
494      * @param resolvedUserId the resolved user id for the service.
495      * @param disabled whether the service is currently disabled (due to {@link UserManager}
496      * restrictions).
497      *
498      * @return a new instance.
499      */
500     @Nullable
newServiceLocked(@serIdInt int resolvedUserId, boolean disabled)501     protected abstract S newServiceLocked(@UserIdInt int resolvedUserId, boolean disabled);
502 
503     /**
504      * Register the service for extra Settings changes (i.e., other than
505      * {@link android.provider.Settings.Secure#USER_SETUP_COMPLETE} or
506      * {@link #getServiceSettingsProperty()}, which are automatically handled).
507      *
508      * <p> Example:
509      *
510      * <pre><code>
511      * resolver.registerContentObserver(Settings.Global.getUriFor(
512      *     Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES), false, observer,
513      *     UserHandle.USER_ALL);
514      * </code></pre>
515      *
516      * <p><b>NOTE: </p>it doesn't need to register for
517      * {@link android.provider.Settings.Secure#USER_SETUP_COMPLETE} or
518      * {@link #getServiceSettingsProperty()}.
519      *
520      */
521     @SuppressWarnings("unused")
registerForExtraSettingsChanges(@onNull ContentResolver resolver, @NonNull ContentObserver observer)522     protected void registerForExtraSettingsChanges(@NonNull ContentResolver resolver,
523             @NonNull ContentObserver observer) {
524     }
525 
526     /**
527      * Callback for Settings changes that were registered though
528      * {@link #registerForExtraSettingsChanges(ContentResolver, ContentObserver)}.
529      *
530      * @param userId user associated with the change
531      * @param property Settings property changed.
532      */
onSettingsChanged(@serIdInt int userId, @NonNull String property)533     protected void onSettingsChanged(@UserIdInt int userId, @NonNull String property) {
534     }
535 
536     /**
537      * Gets the service instance for an user, creating an instance if not present in the cache.
538      */
539     @GuardedBy("mLock")
540     @NonNull
getServiceForUserLocked(@serIdInt int userId)541     protected S getServiceForUserLocked(@UserIdInt int userId) {
542         final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
543                 Binder.getCallingUid(), userId, false, false, null, null);
544         S service = mServicesCache.get(resolvedUserId);
545         if (service == null) {
546             final boolean disabled = isDisabledLocked(userId);
547             service = newServiceLocked(resolvedUserId, disabled);
548             if (!disabled) {
549                 onServiceEnabledLocked(service, resolvedUserId);
550             }
551             mServicesCache.put(userId, service);
552         }
553         return service;
554     }
555 
556     /**
557      * Gets the <b>existing</b> service instance for a user, returning {@code null} if not already
558      * present in the cache.
559      */
560     @GuardedBy("mLock")
561     @Nullable
peekServiceForUserLocked(@serIdInt int userId)562     protected S peekServiceForUserLocked(@UserIdInt int userId) {
563         final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
564                 Binder.getCallingUid(), userId, false, false, null, null);
565         return mServicesCache.get(resolvedUserId);
566     }
567 
568     /**
569      * Updates a cached service for a given user.
570      */
571     @GuardedBy("mLock")
updateCachedServiceLocked(@serIdInt int userId)572     protected void updateCachedServiceLocked(@UserIdInt int userId) {
573         updateCachedServiceLocked(userId, isDisabledLocked(userId));
574     }
575 
576     /**
577      * Checks whether the service is disabled (through {@link UserManager} restrictions) for the
578      * given user.
579      */
isDisabledLocked(@serIdInt int userId)580     protected boolean isDisabledLocked(@UserIdInt int userId) {
581         return mDisabledByUserRestriction == null ? false : mDisabledByUserRestriction.get(userId);
582     }
583 
584     /**
585      * Updates a cached service for a given user.
586      *
587      * @param userId user handle.
588      * @param disabled whether the user is disabled.
589      * @return service for the user.
590      */
591     @GuardedBy("mLock")
updateCachedServiceLocked(@serIdInt int userId, boolean disabled)592     protected S updateCachedServiceLocked(@UserIdInt int userId, boolean disabled) {
593         final S service = getServiceForUserLocked(userId);
594         if (service != null) {
595             service.updateLocked(disabled);
596             if (!service.isEnabledLocked()) {
597                 removeCachedServiceLocked(userId);
598             } else {
599                 onServiceEnabledLocked(service, userId);
600             }
601         }
602         return service;
603     }
604 
605     /**
606      * Gets the Settings property that defines the name of the component name used to bind this
607      * service to an external service, or {@code null} when the service is not defined by such
608      * property (for example, if it's a system service defined by framework resources).
609      */
610     @Nullable
getServiceSettingsProperty()611     protected String getServiceSettingsProperty() {
612         return null;
613     }
614 
615     /**
616      * Callback called after a new service was added to the cache, or an existing service that was
617      * previously disabled gets enabled.
618      *
619      * <p>By default doesn't do anything, but can be overridden by subclasses.
620      */
621     @SuppressWarnings("unused")
onServiceEnabledLocked(@onNull S service, @UserIdInt int userId)622     protected void onServiceEnabledLocked(@NonNull S service, @UserIdInt int userId) {
623     }
624 
625     /**
626      * Removes a cached service for a given user.
627      *
628      * @return the removed service.
629      */
630     @GuardedBy("mLock")
631     @NonNull
removeCachedServiceLocked(@serIdInt int userId)632     protected final S removeCachedServiceLocked(@UserIdInt int userId) {
633         final S service = peekServiceForUserLocked(userId);
634         if (service != null) {
635             mServicesCache.delete(userId);
636             onServiceRemoved(service, userId);
637         }
638         return service;
639     }
640 
641     /**
642      * Called before the package that provides the service for the given user is being updated.
643      */
onServicePackageUpdatingLocked(@serIdInt int userId)644     protected void onServicePackageUpdatingLocked(@UserIdInt int userId) {
645         if (verbose) Slog.v(mTag, "onServicePackageUpdatingLocked(" + userId + ")");
646     }
647 
648     /**
649      * Called after the package that provides the service for the given user is being updated.
650      */
onServicePackageUpdatedLocked(@serIdInt int userId)651     protected void onServicePackageUpdatedLocked(@UserIdInt int userId) {
652         if (verbose) Slog.v(mTag, "onServicePackageUpdated(" + userId + ")");
653     }
654 
655     /**
656      * Called after the package data that provides the service for the given user is cleared.
657      */
onServicePackageDataClearedLocked(@serIdInt int userId)658     protected void onServicePackageDataClearedLocked(@UserIdInt int userId) {
659         if (verbose) Slog.v(mTag, "onServicePackageDataCleared(" + userId + ")");
660     }
661 
662     /**
663      * Called after the package that provides the service for the given user is restarted.
664      */
onServicePackageRestartedLocked(@serIdInt int userId)665     protected void onServicePackageRestartedLocked(@UserIdInt int userId) {
666         if (verbose) Slog.v(mTag, "onServicePackageRestarted(" + userId + ")");
667     }
668 
669     /**
670      * Called after the service is removed from the cache.
671      */
672     @SuppressWarnings("unused")
onServiceRemoved(@onNull S service, @UserIdInt int userId)673     protected void onServiceRemoved(@NonNull S service, @UserIdInt int userId) {
674     }
675 
676     /**
677      * Called when the service name changed (typically when using temporary services).
678      *
679      * <p>By default, it calls {@link #updateCachedServiceLocked(int)}; subclasses must either call
680      * that same method, or {@code super.onServiceNameChanged()}.
681      *
682      * @param userId user handle.
683      * @param serviceName the new service name.
684      * @param isTemporary whether the new service is temporary.
685      */
onServiceNameChanged(@serIdInt int userId, @Nullable String serviceName, boolean isTemporary)686     protected void onServiceNameChanged(@UserIdInt int userId, @Nullable String serviceName,
687             boolean isTemporary) {
688         synchronized (mLock) {
689             updateCachedServiceLocked(userId);
690         }
691     }
692 
693     /**
694      * Visits all services in the cache.
695      */
696     @GuardedBy("mLock")
visitServicesLocked(@onNull Visitor<S> visitor)697     protected void visitServicesLocked(@NonNull Visitor<S> visitor) {
698         final int size = mServicesCache.size();
699         for (int i = 0; i < size; i++) {
700             visitor.visit(mServicesCache.valueAt(i));
701         }
702     }
703 
704     /**
705      * Clear the cache by removing all services.
706      */
707     @GuardedBy("mLock")
clearCacheLocked()708     protected void clearCacheLocked() {
709         mServicesCache.clear();
710     }
711 
712     /**
713      * Gets a cached reference to {@link UserManagerInternal}.
714      */
715     @NonNull
getUserManagerInternal()716     protected UserManagerInternal getUserManagerInternal() {
717         if (mUm == null) {
718             if (verbose) Slog.v(mTag, "lazy-loading UserManagerInternal");
719             mUm = LocalServices.getService(UserManagerInternal.class);
720         }
721         return mUm;
722     }
723 
724     /**
725      * Gets a list of all supported users (i.e., those that pass the
726      * {@link #isUserSupported(TargetUser)}check).
727      */
728     @NonNull
getSupportedUsers()729     protected List<UserInfo> getSupportedUsers() {
730         final UserInfo[] allUsers = getUserManagerInternal().getUserInfos();
731         final int size = allUsers.length;
732         final List<UserInfo> supportedUsers = new ArrayList<>(size);
733         for (int i = 0; i < size; i++) {
734             final UserInfo userInfo = allUsers[i];
735             if (isUserSupported(new TargetUser(userInfo))) {
736                 supportedUsers.add(userInfo);
737             }
738         }
739         return supportedUsers;
740     }
741 
742     /**
743      * Asserts that the given package name is owned by the UID making this call.
744      *
745      * @throws SecurityException when it's not...
746      */
assertCalledByPackageOwner(@onNull String packageName)747     protected void assertCalledByPackageOwner(@NonNull String packageName) {
748         Objects.requireNonNull(packageName);
749         final int uid = Binder.getCallingUid();
750         final String[] packages = getContext().getPackageManager().getPackagesForUid(uid);
751         if (packages != null) {
752             for (String candidate : packages) {
753                 if (packageName.equals(candidate)) return; // Found it
754             }
755         }
756         throw new SecurityException("UID " + uid + " does not own " + packageName);
757     }
758 
759     // TODO(b/117779333): support proto
dumpLocked(@onNull String prefix, @NonNull PrintWriter pw)760     protected void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
761         boolean realDebug = debug;
762         boolean realVerbose = verbose;
763         final String prefix2 = "    ";
764 
765         try {
766             // Temporarily turn on full logging;
767             debug = verbose = true;
768             final int size = mServicesCache.size();
769             pw.print(prefix); pw.print("Debug: "); pw.print(realDebug);
770             pw.print(" Verbose: "); pw.println(realVerbose);
771             pw.print("Package policy flags: "); pw.println(mServicePackagePolicyFlags);
772             if (mUpdatingPackageNames != null) {
773                 pw.print("Packages being updated: "); pw.println(mUpdatingPackageNames);
774             }
775             dumpSupportedUsers(pw, prefix);
776             if (mServiceNameResolver != null) {
777                 pw.print(prefix); pw.print("Name resolver: ");
778                 mServiceNameResolver.dumpShort(pw); pw.println();
779                 final List<UserInfo> users = getSupportedUsers();
780                 for (int i = 0; i < users.size(); i++) {
781                     final int userId = users.get(i).id;
782                     pw.print(prefix2); pw.print(userId); pw.print(": ");
783                     mServiceNameResolver.dumpShort(pw, userId); pw.println();
784                 }
785             }
786             pw.print(prefix); pw.print("Users disabled by restriction: ");
787             pw.println(mDisabledByUserRestriction);
788             pw.print(prefix); pw.print("Allow instant service: "); pw.println(mAllowInstantService);
789             final String settingsProperty = getServiceSettingsProperty();
790             if (settingsProperty != null) {
791                 pw.print(prefix); pw.print("Settings property: "); pw.println(settingsProperty);
792             }
793             pw.print(prefix); pw.print("Cached services: ");
794             if (size == 0) {
795                 pw.println("none");
796             } else {
797                 pw.println(size);
798                 for (int i = 0; i < size; i++) {
799                     pw.print(prefix); pw.print("Service at "); pw.print(i); pw.println(": ");
800                     final S service = mServicesCache.valueAt(i);
801                     service.dumpLocked(prefix2, pw);
802                     pw.println();
803                 }
804             }
805         } finally {
806             debug = realDebug;
807             verbose = realVerbose;
808         }
809     }
810 
startTrackingPackageChanges()811     private void startTrackingPackageChanges() {
812         final PackageMonitor monitor = new PackageMonitor() {
813 
814             @Override
815             public void onPackageUpdateStarted(@NonNull String packageName, int uid) {
816                 if (verbose) Slog.v(mTag, "onPackageUpdateStarted(): " + packageName);
817                 final String activePackageName = getActiveServicePackageNameLocked();
818                 if (!packageName.equals(activePackageName)) return;
819 
820                 final int userId = getChangingUserId();
821                 synchronized (mLock) {
822                     if (mUpdatingPackageNames == null) {
823                         mUpdatingPackageNames = new SparseArray<String>(mServicesCache.size());
824                     }
825                     mUpdatingPackageNames.put(userId, packageName);
826                     onServicePackageUpdatingLocked(userId);
827                     if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_NO_REFRESH) != 0) {
828                         if (debug) {
829                             Slog.d(mTag, "Holding service for user " + userId + " while package "
830                                     + activePackageName + " is being updated");
831                         }
832                     } else {
833                         if (debug) {
834                             Slog.d(mTag, "Removing service for user " + userId
835                                     + " because package " + activePackageName
836                                     + " is being updated");
837                         }
838                         removeCachedServiceLocked(userId);
839 
840                         if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_REFRESH_EAGER)
841                                 != 0) {
842                             if (debug) {
843                                 Slog.d(mTag, "Eagerly recreating service for user "
844                                         + userId);
845                             }
846                             getServiceForUserLocked(userId);
847                         }
848                     }
849                 }
850             }
851 
852             @Override
853             public void onPackageUpdateFinished(@NonNull String packageName, int uid) {
854                 if (verbose) Slog.v(mTag, "onPackageUpdateFinished(): " + packageName);
855                 final int userId = getChangingUserId();
856                 synchronized (mLock) {
857                     final String activePackageName = mUpdatingPackageNames == null ? null
858                             : mUpdatingPackageNames.get(userId);
859                     if (packageName.equals(activePackageName)) {
860                         if (mUpdatingPackageNames != null) {
861                             mUpdatingPackageNames.remove(userId);
862                             if (mUpdatingPackageNames.size() == 0) {
863                                 mUpdatingPackageNames = null;
864                             }
865                         }
866                         onServicePackageUpdatedLocked(userId);
867                     } else {
868                         handlePackageUpdateLocked(packageName);
869                     }
870                 }
871             }
872 
873             @Override
874             public void onPackageRemoved(String packageName, int uid) {
875                 synchronized (mLock) {
876                     final int userId = getChangingUserId();
877                     final S service = peekServiceForUserLocked(userId);
878                     if (service != null) {
879                         final ComponentName componentName = service.getServiceComponentName();
880                         if (componentName != null) {
881                             if (packageName.equals(componentName.getPackageName())) {
882                                 handleActiveServiceRemoved(userId);
883                             }
884                         }
885                     }
886                 }
887             }
888 
889             @Override
890             public boolean onHandleForceStop(Intent intent, String[] packages,
891                     int uid, boolean doit) {
892                 synchronized (mLock) {
893                     final String activePackageName = getActiveServicePackageNameLocked();
894                     for (String pkg : packages) {
895                         if (pkg.equals(activePackageName)) {
896                             if (!doit) {
897                                 return true;
898                             }
899                             final String action = intent.getAction();
900                             final int userId = getChangingUserId();
901                             if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) {
902                                 handleActiveServiceRestartedLocked(activePackageName, userId);
903                             } else {
904                                 removeCachedServiceLocked(userId);
905                             }
906                         } else {
907                             handlePackageUpdateLocked(pkg);
908                         }
909                     }
910                 }
911                 return false;
912             }
913 
914             @Override
915             public void onPackageDataCleared(String packageName, int uid) {
916                 if (verbose) Slog.v(mTag, "onPackageDataCleared(): " + packageName);
917                 final int userId = getChangingUserId();
918                 synchronized (mLock) {
919                     final S service = peekServiceForUserLocked(userId);
920                     if (service != null) {
921                         final ComponentName componentName = service.getServiceComponentName();
922                         if (componentName != null) {
923                             if (packageName.equals(componentName.getPackageName())) {
924                                 onServicePackageDataClearedLocked(userId);
925                             }
926                         }
927                     }
928                 }
929             }
930 
931             private void handleActiveServiceRemoved(@UserIdInt int userId) {
932                 synchronized (mLock) {
933                     removeCachedServiceLocked(userId);
934                 }
935                 final String serviceSettingsProperty = getServiceSettingsProperty();
936                 if (serviceSettingsProperty != null) {
937                     Settings.Secure.putStringForUser(getContext().getContentResolver(),
938                             serviceSettingsProperty, null, userId);
939                 }
940             }
941 
942             private void handleActiveServiceRestartedLocked(String activePackageName,
943                     @UserIdInt int userId) {
944                 if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_NO_REFRESH) != 0) {
945                     if (debug) {
946                         Slog.d(mTag, "Holding service for user " + userId + " while package "
947                                 + activePackageName + " is being restarted");
948                     }
949                 } else {
950                     if (debug) {
951                         Slog.d(mTag, "Removing service for user " + userId
952                                 + " because package " + activePackageName
953                                 + " is being restarted");
954                     }
955                     removeCachedServiceLocked(userId);
956 
957                     if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_REFRESH_EAGER) != 0) {
958                         if (debug) {
959                             Slog.d(mTag, "Eagerly recreating service for user " + userId);
960                         }
961                         updateCachedServiceLocked(userId);
962                     }
963                 }
964                 onServicePackageRestartedLocked(userId);
965             }
966 
967             @Override
968             public void onPackageModified(String packageName) {
969                 if (verbose) Slog.v(mTag, "onPackageModified(): " + packageName);
970 
971                 if (mServiceNameResolver == null) {
972                     return;
973                 }
974 
975                 final int userId = getChangingUserId();
976                 final String serviceName = mServiceNameResolver.getDefaultServiceName(userId);
977                 if (serviceName == null) {
978                     return;
979                 }
980 
981                 final ComponentName serviceComponentName =
982                         ComponentName.unflattenFromString(serviceName);
983                 if (serviceComponentName == null
984                         || !serviceComponentName.getPackageName().equals(packageName)) {
985                     return;
986                 }
987 
988                 // The default service package has changed, update the cached if the service
989                 // exists but no active component.
990                 final S service = peekServiceForUserLocked(userId);
991                 if (service != null) {
992                     final ComponentName componentName = service.getServiceComponentName();
993                     if (componentName == null) {
994                         if (verbose) Slog.v(mTag, "update cached");
995                         updateCachedServiceLocked(userId);
996                     }
997                 }
998             }
999 
1000             private String getActiveServicePackageNameLocked() {
1001                 final int userId = getChangingUserId();
1002                 final S service = peekServiceForUserLocked(userId);
1003                 if (service == null) {
1004                     return null;
1005                 }
1006                 final ComponentName serviceComponent = service.getServiceComponentName();
1007                 if (serviceComponent == null) {
1008                     return null;
1009                 }
1010                 return serviceComponent.getPackageName();
1011             }
1012 
1013             @GuardedBy("mLock")
1014             private void handlePackageUpdateLocked(String packageName) {
1015                 visitServicesLocked((s) -> s.handlePackageUpdateLocked(packageName));
1016             }
1017         };
1018 
1019         // package changes
1020         monitor.register(getContext(), null,  UserHandle.ALL, true);
1021     }
1022 
1023     /**
1024      * Visitor pattern.
1025      *
1026      * @param <S> visited class.
1027      */
1028     public interface Visitor<S> {
1029         /**
1030          * Visits a service.
1031          *
1032          * @param service the service to be visited.
1033          */
visit(@onNull S service)1034         void visit(@NonNull S service);
1035     }
1036 
1037     private final class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler)1038         SettingsObserver(Handler handler) {
1039             super(handler);
1040             ContentResolver resolver = getContext().getContentResolver();
1041             final String serviceProperty = getServiceSettingsProperty();
1042             if (serviceProperty != null) {
1043                 resolver.registerContentObserver(Settings.Secure.getUriFor(
1044                         serviceProperty), false, this, UserHandle.USER_ALL);
1045             }
1046             resolver.registerContentObserver(Settings.Secure.getUriFor(
1047                     Settings.Secure.USER_SETUP_COMPLETE), false, this, UserHandle.USER_ALL);
1048             registerForExtraSettingsChanges(resolver, this);
1049         }
1050 
1051         @Override
onChange(boolean selfChange, Uri uri, @UserIdInt int userId)1052         public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) {
1053             if (verbose) Slog.v(mTag, "onChange(): uri=" + uri + ", userId=" + userId);
1054             final String property = uri.getLastPathSegment();
1055             if (property == null) {
1056                 return;
1057             }
1058             if (property.equals(getServiceSettingsProperty())
1059                     || property.equals(Settings.Secure.USER_SETUP_COMPLETE)) {
1060                 synchronized (mLock) {
1061                     updateCachedServiceLocked(userId);
1062                 }
1063             } else {
1064                 onSettingsChanged(userId, property);
1065             }
1066         }
1067     }
1068 }
1069