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