• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2014, 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 
17 package com.android.server.notification;
18 
19 import static android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR;
20 import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT;
21 import static android.content.Context.BIND_AUTO_CREATE;
22 import static android.content.Context.BIND_FOREGROUND_SERVICE;
23 import static android.content.Context.DEVICE_POLICY_SERVICE;
24 import static android.os.UserHandle.USER_ALL;
25 import static android.os.UserHandle.USER_SYSTEM;
26 import static android.service.notification.NotificationListenerService.META_DATA_DEFAULT_AUTOBIND;
27 
28 import static com.android.server.notification.Flags.FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER;
29 import static com.android.server.notification.Flags.managedServicesConcurrentMultiuser;
30 import static com.android.server.notification.NotificationManagerService.privateSpaceFlagsEnabled;
31 
32 import android.annotation.FlaggedApi;
33 import android.annotation.NonNull;
34 import android.app.ActivityManager;
35 import android.app.ActivityOptions;
36 import android.app.PendingIntent;
37 import android.app.admin.DevicePolicyManager;
38 import android.content.ComponentName;
39 import android.content.ContentResolver;
40 import android.content.Context;
41 import android.content.Intent;
42 import android.content.ServiceConnection;
43 import android.content.pm.ApplicationInfo;
44 import android.content.pm.IPackageManager;
45 import android.content.pm.PackageManager;
46 import android.content.pm.PackageManager.NameNotFoundException;
47 import android.content.pm.ResolveInfo;
48 import android.content.pm.ServiceInfo;
49 import android.content.pm.UserInfo;
50 import android.os.Binder;
51 import android.os.Build;
52 import android.os.Handler;
53 import android.os.IBinder;
54 import android.os.IInterface;
55 import android.os.Looper;
56 import android.os.RemoteException;
57 import android.os.UserHandle;
58 import android.os.UserManager;
59 import android.provider.Settings;
60 import android.service.notification.ManagedServiceInfoProto;
61 import android.service.notification.ManagedServicesProto;
62 import android.service.notification.ManagedServicesProto.ServiceProto;
63 import android.text.TextUtils;
64 import android.util.ArrayMap;
65 import android.util.ArraySet;
66 import android.util.IntArray;
67 import android.util.Log;
68 import android.util.Pair;
69 import android.util.Slog;
70 import android.util.SparseArray;
71 import android.util.SparseSetArray;
72 import android.util.proto.ProtoOutputStream;
73 
74 import com.android.internal.annotations.GuardedBy;
75 import com.android.internal.annotations.VisibleForTesting;
76 import com.android.internal.util.XmlUtils;
77 import com.android.internal.util.function.TriPredicate;
78 import com.android.modules.utils.TypedXmlPullParser;
79 import com.android.modules.utils.TypedXmlSerializer;
80 import com.android.server.LocalServices;
81 import com.android.server.notification.NotificationManagerService.DumpFilter;
82 import com.android.server.pm.UserManagerInternal;
83 import com.android.server.utils.TimingsTraceAndSlog;
84 
85 import org.xmlpull.v1.XmlPullParser;
86 import org.xmlpull.v1.XmlPullParserException;
87 
88 import java.io.IOException;
89 import java.io.PrintWriter;
90 import java.util.ArrayList;
91 import java.util.Arrays;
92 import java.util.HashSet;
93 import java.util.List;
94 import java.util.Objects;
95 import java.util.Set;
96 
97 /**
98  * Manages the lifecycle of application-provided services bound by system server.
99  *
100  * Services managed by this helper must have:
101  *  - An associated system settings value with a list of enabled component names.
102  *  - A well-known action for services to use in their intent-filter.
103  *  - A system permission for services to require in order to ensure system has exclusive binding.
104  *  - A settings page for user configuration of enabled services, and associated intent action.
105  *  - A remote interface definition (aidl) provided by the service used for communication.
106  */
107 abstract public class ManagedServices {
108     protected final String TAG = getClass().getSimpleName().replace('$', '.');
109     protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
110 
111     private static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000;
112     protected static final String ENABLED_SERVICES_SEPARATOR = ":";
113     private static final String DB_VERSION_1 = "1";
114     private static final String DB_VERSION_2 = "2";
115     private static final String DB_VERSION_3 = "3";
116 
117 
118     /**
119      * List of components and apps that can have running {@link ManagedServices}.
120      */
121     static final String TAG_MANAGED_SERVICES = "service_listing";
122     static final String ATT_APPROVED_LIST = "approved";
123     static final String ATT_USER_ID = "user";
124     static final String ATT_IS_PRIMARY = "primary";
125     static final String ATT_VERSION = "version";
126     static final String ATT_DEFAULTS = "defaults";
127     static final String ATT_USER_SET = "user_set_services";
128     static final String ATT_USER_SET_OLD = "user_set";
129     static final String ATT_USER_CHANGED = "user_changed";
130 
131     static final String DB_VERSION = "4";
132 
133     static final int APPROVAL_BY_PACKAGE = 0;
134     static final int APPROVAL_BY_COMPONENT = 1;
135 
136     protected final Context mContext;
137     protected final Object mMutex;
138     private final UserProfiles mUserProfiles;
139     protected final IPackageManager mPm;
140     protected final UserManager mUm;
141     protected final UserManagerInternal mUmInternal;
142     private final Config mConfig;
143     private final Handler mHandler = new Handler(Looper.getMainLooper());
144 
145     // contains connections to all connected services, including app services
146     // and system services
147     @GuardedBy("mMutex")
148     private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<>();
149     /**
150      * The services that have been bound by us. If the service is also connected, it will also
151      * be in {@link #mServices}.
152      */
153     @GuardedBy("mMutex")
154     private final ArrayList<Pair<ComponentName, Integer>> mServicesBound = new ArrayList<>();
155     @GuardedBy("mMutex")
156     private final ArraySet<Pair<ComponentName, Integer>> mServicesRebinding = new ArraySet<>();
157     // we need these packages to be protected because classes that inherit from it need to see it
158     protected final Object mDefaultsLock = new Object();
159     @GuardedBy("mDefaultsLock")
160     protected final ArraySet<ComponentName> mDefaultComponents = new ArraySet<>();
161     @GuardedBy("mDefaultsLock")
162     protected final ArraySet<String> mDefaultPackages = new ArraySet<>();
163 
164     // lists the component names of all enabled (and therefore potentially connected)
165     // app services for each user. This is intended to support a concurrent multi-user environment.
166     // key value is the resolved userId.
167     @GuardedBy("mMutex")
168     private final SparseArray<ArraySet<ComponentName>> mEnabledServicesByUser =
169             new SparseArray<>();
170     // Just the packages from mEnabledServicesByUser
171     // This is intended to support a concurrent multi-user environment.
172     // key value is the resolved userId.
173     @GuardedBy("mMutex")
174     private final SparseArray<ArraySet<String>> mEnabledServicesPackageNamesByUser =
175             new SparseArray<>();
176     // Per user id, list of enabled packages that have nevertheless asked not to be run
177     @GuardedBy("mSnoozing")
178     private final SparseSetArray<ComponentName> mSnoozing = new SparseSetArray<>();
179 
180     // List of approved packages or components (by user, then by primary/secondary) that are
181     // allowed to be bound as managed services. A package or component appearing in this list does
182     // not mean that we are currently bound to said package/component.
183     @GuardedBy("mApproved")
184     protected final ArrayMap<Integer, ArrayMap<Boolean, ArraySet<String>>> mApproved =
185             new ArrayMap<>();
186     // List of packages or components (by user) that are configured to be enabled/disabled
187     // explicitly by the user
188     @GuardedBy("mApproved")
189     protected ArrayMap<Integer, ArraySet<String>> mUserSetServices = new ArrayMap<>();
190     @GuardedBy("mApproved")
191     protected ArrayMap<Integer, Boolean> mIsUserChanged = new ArrayMap<>();
192 
193     // True if approved services are stored in xml, not settings.
194     private boolean mUseXml;
195 
196     // Whether managed services are approved individually or package wide
197     protected int mApprovalLevel;
198 
ManagedServices(Context context, Object mutex, UserProfiles userProfiles, IPackageManager pm)199     public ManagedServices(Context context, Object mutex, UserProfiles userProfiles,
200             IPackageManager pm) {
201         mContext = context;
202         mMutex = mutex;
203         mUserProfiles = userProfiles;
204         mPm = pm;
205         mConfig = getConfig();
206         mApprovalLevel = APPROVAL_BY_COMPONENT;
207         mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
208         mUmInternal = LocalServices.getService(UserManagerInternal.class);
209         // Initialize for the current user.
210         mEnabledServicesByUser.put(UserHandle.USER_CURRENT, new ArraySet<>());
211         mEnabledServicesPackageNamesByUser.put(UserHandle.USER_CURRENT, new ArraySet<>());
212     }
213 
getConfig()214     abstract protected Config getConfig();
215 
getCaption()216     private String getCaption() {
217         return mConfig.caption;
218     }
219 
asInterface(IBinder binder)220     abstract protected IInterface asInterface(IBinder binder);
221 
checkType(IInterface service)222     abstract protected boolean checkType(IInterface service);
223 
onServiceAdded(ManagedServiceInfo info)224     abstract protected void onServiceAdded(ManagedServiceInfo info);
225 
ensureFilters(ServiceInfo si, int userId)226     abstract protected void ensureFilters(ServiceInfo si, int userId);
227 
getServices()228     protected List<ManagedServiceInfo> getServices() {
229         synchronized (mMutex) {
230             List<ManagedServiceInfo> services = new ArrayList<>(mServices);
231             return services;
232         }
233     }
234 
addDefaultComponentOrPackage(String packageOrComponent)235     protected void addDefaultComponentOrPackage(String packageOrComponent) {
236         if (!TextUtils.isEmpty(packageOrComponent)) {
237             synchronized (mDefaultsLock) {
238                 if (mApprovalLevel == APPROVAL_BY_PACKAGE) {
239                     mDefaultPackages.add(packageOrComponent);
240                     return;
241                 }
242                 ComponentName cn = ComponentName.unflattenFromString(packageOrComponent);
243                 if (cn != null  && mApprovalLevel == APPROVAL_BY_COMPONENT) {
244                     mDefaultPackages.add(cn.getPackageName());
245                     mDefaultComponents.add(cn);
246                     return;
247                 }
248             }
249         }
250     }
251 
loadDefaultsFromConfig()252     protected abstract void loadDefaultsFromConfig();
253 
isDefaultComponentOrPackage(String packageOrComponent)254     boolean isDefaultComponentOrPackage(String packageOrComponent) {
255         synchronized (mDefaultsLock) {
256             ComponentName cn = ComponentName.unflattenFromString(packageOrComponent);
257             if (cn == null) {
258                 return mDefaultPackages.contains(packageOrComponent);
259             } else {
260                 return mDefaultComponents.contains(cn);
261             }
262         }
263     }
264 
getDefaultComponents()265     ArraySet<ComponentName> getDefaultComponents() {
266         synchronized (mDefaultsLock) {
267             return new ArraySet<>(mDefaultComponents);
268         }
269     }
270 
getDefaultPackages()271     ArraySet<String> getDefaultPackages() {
272         synchronized (mDefaultsLock) {
273             return new ArraySet<>(mDefaultPackages);
274         }
275     }
276 
277     /**
278      * When resetting a package, we need to enable default components that belong to that packages
279      * we also need to disable components that are not default to return the managed service state
280      * to when a new android device is first turned on for that package.
281      *
282      * @param packageName package to reset.
283      * @param userId the android user id
284      * @return a list of components that were permitted
285      */
286     @NonNull
resetComponents(String packageName, int userId)287     ArrayMap<Boolean, ArrayList<ComponentName>> resetComponents(String packageName, int userId) {
288         // components that we want to enable
289         ArrayList<ComponentName> componentsToEnable;
290         // components that were removed
291         ArrayList<ComponentName> disabledComponents;
292         // all components that are enabled now
293         ArraySet<ComponentName> enabledComponents = new ArraySet<>(getAllowedComponents(userId));
294 
295         boolean changed = false;
296 
297         synchronized (mDefaultsLock) {
298             componentsToEnable = new ArrayList<>(mDefaultComponents.size());
299             disabledComponents = new ArrayList<>(mDefaultComponents.size());
300 
301             // record all components that are enabled but should not be by default
302             for (int i = 0; i < mDefaultComponents.size() && enabledComponents.size() > 0; i++) {
303                 ComponentName currentDefault = mDefaultComponents.valueAt(i);
304                 if (packageName.equals(currentDefault.getPackageName())
305                         && !enabledComponents.contains(currentDefault)) {
306                     componentsToEnable.add(currentDefault);
307                 }
308             }
309             synchronized (mApproved) {
310                 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(
311                         userId);
312                 if (approvedByType != null) {
313                     final int M = approvedByType.size();
314                     for (int j = 0; j < M; j++) {
315                         final ArraySet<String> approved = approvedByType.valueAt(j);
316                         for (int i = 0; i < enabledComponents.size(); i++) {
317                             ComponentName currentComponent = enabledComponents.valueAt(i);
318                             if (packageName.equals(currentComponent.getPackageName())
319                                     && !mDefaultComponents.contains(currentComponent)) {
320                                 if (approved.remove(currentComponent.flattenToString())) {
321                                     disabledComponents.add(currentComponent);
322                                     clearUserSetFlagLocked(currentComponent, userId);
323                                     changed = true;
324                                 }
325                             }
326                         }
327                         for (int i = 0; i < componentsToEnable.size(); i++) {
328                             ComponentName candidate = componentsToEnable.get(i);
329                             changed |= approved.add(candidate.flattenToString());
330                         }
331                     }
332 
333                 }
334             }
335         }
336         if (changed) rebindServices(false, USER_ALL);
337 
338         ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
339         changes.put(true, componentsToEnable);
340         changes.put(false, disabledComponents);
341 
342         return changes;
343     }
344 
345     @GuardedBy("mApproved")
clearUserSetFlagLocked(ComponentName component, int userId)346     private boolean clearUserSetFlagLocked(ComponentName component, int userId) {
347         String approvedValue = getApprovedValue(component.flattenToString());
348         ArraySet<String> userSet = mUserSetServices.get(userId);
349         return userSet != null && userSet.remove(approvedValue);
350     }
351 
getBindFlags()352     protected int getBindFlags() {
353         return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT;
354     }
355 
onServiceRemovedLocked(ManagedServiceInfo removed)356     protected void onServiceRemovedLocked(ManagedServiceInfo removed) { }
357 
newServiceInfo(IInterface service, ComponentName component, int userId, boolean isSystem, ServiceConnection connection, int targetSdkVersion, int uid)358     private ManagedServiceInfo newServiceInfo(IInterface service,
359             ComponentName component, int userId, boolean isSystem, ServiceConnection connection,
360             int targetSdkVersion, int uid) {
361         return new ManagedServiceInfo(service, component, userId, isSystem, connection,
362                 targetSdkVersion, uid);
363     }
364 
onBootPhaseAppsCanStart()365     public void onBootPhaseAppsCanStart() {}
366 
dump(PrintWriter pw, DumpFilter filter)367     public void dump(PrintWriter pw, DumpFilter filter) {
368         pw.println("    Allowed " + getCaption() + "s:");
369         synchronized (mApproved) {
370             final int N = mApproved.size();
371             for (int i = 0; i < N; i++) {
372                 final int userId = mApproved.keyAt(i);
373                 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
374                 final Boolean userChanged = mIsUserChanged.get(userId);
375                 if (approvedByType != null) {
376                     final int M = approvedByType.size();
377                     for (int j = 0; j < M; j++) {
378                         final boolean isPrimary = approvedByType.keyAt(j);
379                         final ArraySet<String> approved = approvedByType.valueAt(j);
380                         if (approvedByType != null && approvedByType.size() > 0) {
381                             pw.println("      " + String.join(ENABLED_SERVICES_SEPARATOR, approved)
382                                     + " (user: " + userId + " isPrimary: " + isPrimary
383                                     + (userChanged == null ? "" : " isUserChanged: "
384                                     + userChanged) + ")");
385                         }
386                     }
387                 }
388             }
389             pw.println("    Has user set:");
390             Set<Integer> userIds = mUserSetServices.keySet();
391             for (int userId : userIds) {
392                 if (mIsUserChanged.get(userId) == null) {
393                     pw.println("      userId=" + userId + " value="
394                             + (mUserSetServices.get(userId)));
395                 }
396             }
397         }
398 
399         synchronized (mMutex) {
400             if (managedServicesConcurrentMultiuser()) {
401                 for (int i = 0; i < mEnabledServicesByUser.size(); i++) {
402                     final int userId = mEnabledServicesByUser.keyAt(i);
403                     final ArraySet<ComponentName> componentNames =
404                             mEnabledServicesByUser.get(userId);
405                     String userString = userId == UserHandle.USER_CURRENT
406                             ? "current profiles" : "user " + Integer.toString(userId);
407                     pw.println("    All " + getCaption() + "s (" + componentNames.size()
408                             + ") enabled for " +  userString + ":");
409                     for (ComponentName cmpt : componentNames) {
410                         if (filter != null && !filter.matches(cmpt)) continue;
411                         pw.println("      " + cmpt);
412                     }
413                 }
414             } else {
415                 final ArraySet<ComponentName> enabledServicesForCurrentProfiles =
416                         mEnabledServicesByUser.get(UserHandle.USER_CURRENT);
417                 pw.println("    All " + getCaption() + "s ("
418                         + enabledServicesForCurrentProfiles.size()
419                         + ") enabled for current profiles:");
420                 for (ComponentName cmpt : enabledServicesForCurrentProfiles) {
421                     if (filter != null && !filter.matches(cmpt)) continue;
422                     pw.println("      " + cmpt);
423                 }
424             }
425 
426             pw.println("    Live " + getCaption() + "s (" + mServices.size() + "):");
427             for (ManagedServiceInfo info : mServices) {
428                 if (filter != null && !filter.matches(info.component)) continue;
429                 pw.println("      " + info.component
430                         + " (user " + info.userid + "): " + info.service
431                         + (info.isSystem ? " SYSTEM" : "")
432                         + (info.isGuest(this) ? " GUEST" : ""));
433             }
434         }
435 
436         final SparseSetArray<ComponentName> snoozingComponents;
437         synchronized (mSnoozing) {
438             snoozingComponents = new SparseSetArray<>(mSnoozing);
439         }
440         pw.println("    Snoozed " + getCaption() + "s ("
441                 + snoozingComponents.size() + "):");
442         for (int i = 0; i < snoozingComponents.size(); i++) {
443             pw.println("      User: " + snoozingComponents.keyAt(i));
444             for (ComponentName name : snoozingComponents.valuesAt(i)) {
445                 final ServiceInfo info = getServiceInfo(name, snoozingComponents.keyAt(i));
446                 pw.println("        " + name.flattenToShortString() + (isAutobindAllowed(info) ? ""
447                         : " (META_DATA_DEFAULT_AUTOBIND=false)"));
448             }
449         }
450     }
451 
dump(ProtoOutputStream proto, DumpFilter filter)452     public void dump(ProtoOutputStream proto, DumpFilter filter) {
453         proto.write(ManagedServicesProto.CAPTION, getCaption());
454         synchronized (mApproved) {
455             final int N = mApproved.size();
456             for (int i = 0; i < N; i++) {
457                 final int userId = mApproved.keyAt(i);
458                 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
459                 if (approvedByType != null) {
460                     final int M = approvedByType.size();
461                     for (int j = 0; j < M; j++) {
462                         final boolean isPrimary = approvedByType.keyAt(j);
463                         final ArraySet<String> approved = approvedByType.valueAt(j);
464                         if (approvedByType != null && approvedByType.size() > 0) {
465                             final long sToken = proto.start(ManagedServicesProto.APPROVED);
466                             for (String s : approved) {
467                                 proto.write(ServiceProto.NAME, s);
468                             }
469                             proto.write(ServiceProto.USER_ID, userId);
470                             proto.write(ServiceProto.IS_PRIMARY, isPrimary);
471                             proto.end(sToken);
472                         }
473                     }
474                 }
475             }
476         }
477 
478         synchronized (mMutex) {
479             if (managedServicesConcurrentMultiuser()) {
480                 for (int i = 0; i < mEnabledServicesByUser.size(); i++) {
481                     final int userId = mEnabledServicesByUser.keyAt(i);
482                     final ArraySet<ComponentName> componentNames =
483                             mEnabledServicesByUser.get(userId);
484                     for (ComponentName cmpt : componentNames) {
485                         if (filter != null && !filter.matches(cmpt)) continue;
486                         cmpt.dumpDebug(proto, ManagedServicesProto.ENABLED);
487                     }
488                 }
489             } else {
490                 final ArraySet<ComponentName> enabledServicesForCurrentProfiles =
491                         mEnabledServicesByUser.get(UserHandle.USER_CURRENT);
492                 for (ComponentName cmpt : enabledServicesForCurrentProfiles) {
493                     if (filter != null && !filter.matches(cmpt)) continue;
494                     cmpt.dumpDebug(proto, ManagedServicesProto.ENABLED);
495                 }
496             }
497             for (ManagedServiceInfo info : mServices) {
498                 if (filter != null && !filter.matches(info.component)) continue;
499                 info.dumpDebug(proto, ManagedServicesProto.LIVE_SERVICES, this);
500             }
501         }
502 
503         synchronized (mSnoozing) {
504             for (int i = 0; i < mSnoozing.size(); i++) {
505                 long token = proto.start(ManagedServicesProto.SNOOZED);
506                 proto.write(ManagedServicesProto.SnoozedServices.USER_ID,
507                         mSnoozing.keyAt(i));
508                 for (ComponentName name : mSnoozing.valuesAt(i)) {
509                     name.dumpDebug(proto, ManagedServicesProto.SnoozedServices.SNOOZED);
510                 }
511                 proto.end(token);
512             }
513         }
514     }
515 
onSettingRestored(String element, String value, int backupSdkInt, int userId)516     protected void onSettingRestored(String element, String value, int backupSdkInt, int userId) {
517         if (!mUseXml) {
518             Slog.d(TAG, "Restored managed service setting: " + element);
519             if (mConfig.secureSettingName.equals(element) ||
520                     (mConfig.secondarySettingName != null
521                             && mConfig.secondarySettingName.equals(element))) {
522                 if (backupSdkInt < Build.VERSION_CODES.O) {
523                     // automatic system grants were added in O, so append the approved apps
524                     // rather than wiping out the setting
525                     String currentSetting =
526                             getApproved(userId, mConfig.secureSettingName.equals(element));
527                     if (!TextUtils.isEmpty(currentSetting)) {
528                         if (!TextUtils.isEmpty(value)) {
529                             value = value + ENABLED_SERVICES_SEPARATOR + currentSetting;
530                         } else {
531                             value = currentSetting;
532                         }
533                     }
534                 }
535                 if (shouldReflectToSettings()) {
536                     Settings.Secure.putStringForUser(
537                             mContext.getContentResolver(), element, value, userId);
538                 }
539 
540                 for (UserInfo user : mUm.getUsers()) {
541                     addApprovedList(value, user.id, mConfig.secureSettingName.equals(element));
542                 }
543                 Slog.d(TAG, "Done loading approved values from settings");
544                 rebindServices(false, userId);
545             }
546         }
547     }
548 
writeDefaults(TypedXmlSerializer out)549     void writeDefaults(TypedXmlSerializer out) throws IOException {
550         synchronized (mDefaultsLock) {
551             List<String> componentStrings = new ArrayList<>(mDefaultComponents.size());
552             for (int i = 0; i < mDefaultComponents.size(); i++) {
553                 componentStrings.add(mDefaultComponents.valueAt(i).flattenToString());
554             }
555             String defaults = String.join(ENABLED_SERVICES_SEPARATOR, componentStrings);
556             out.attribute(null, ATT_DEFAULTS, defaults);
557         }
558     }
559 
writeXml(TypedXmlSerializer out, boolean forBackup, int userId)560     public void writeXml(TypedXmlSerializer out, boolean forBackup, int userId) throws IOException {
561         out.startTag(null, getConfig().xmlTag);
562 
563         out.attributeInt(null, ATT_VERSION, Integer.parseInt(DB_VERSION));
564 
565         writeDefaults(out);
566 
567         if (forBackup) {
568             trimApprovedListsAccordingToInstalledServices(userId);
569         }
570 
571         synchronized (mApproved) {
572             final int N = mApproved.size();
573             for (int i = 0; i < N; i++) {
574                 final int approvedUserId = mApproved.keyAt(i);
575                 if (forBackup && approvedUserId != userId) {
576                     continue;
577                 }
578                 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
579                 final Boolean isUserChanged = mIsUserChanged.get(approvedUserId);
580                 if (approvedByType != null) {
581                     final int M = approvedByType.size();
582                     for (int j = 0; j < M; j++) {
583                         final boolean isPrimary = approvedByType.keyAt(j);
584                         final Set<String> approved = approvedByType.valueAt(j);
585                         final Set<String> userSet = mUserSetServices.get(approvedUserId);
586                         if (approved != null || userSet != null || isUserChanged != null) {
587                             String allowedItems = approved == null
588                                     ? ""
589                                     : String.join(ENABLED_SERVICES_SEPARATOR, approved);
590                             out.startTag(null, TAG_MANAGED_SERVICES);
591                             out.attribute(null, ATT_APPROVED_LIST, allowedItems);
592                             out.attributeInt(null, ATT_USER_ID, approvedUserId);
593                             out.attributeBoolean(null, ATT_IS_PRIMARY, isPrimary);
594                             if (isUserChanged != null) {
595                                 out.attributeBoolean(null, ATT_USER_CHANGED, isUserChanged);
596                             } else if (userSet != null) {
597                                 String userSetItems =
598                                         String.join(ENABLED_SERVICES_SEPARATOR, userSet);
599                                 out.attribute(null, ATT_USER_SET, userSetItems);
600                             }
601                             writeExtraAttributes(out, approvedUserId);
602                             out.endTag(null, TAG_MANAGED_SERVICES);
603 
604                             if (!forBackup && isPrimary) {
605                                 if (shouldReflectToSettings()) {
606                                     // Also write values to settings, for observers who haven't
607                                     // migrated yet
608                                     Settings.Secure.putStringForUser(mContext.getContentResolver(),
609                                             getConfig().secureSettingName, allowedItems,
610                                             approvedUserId);
611                                 }
612                             }
613 
614                         }
615                     }
616                 }
617             }
618         }
619 
620         writeExtraXmlTags(out);
621 
622         out.endTag(null, getConfig().xmlTag);
623     }
624 
625     /**
626      * Returns whether the approved list of services should also be written to the Settings db
627      */
shouldReflectToSettings()628     protected boolean shouldReflectToSettings() {
629         return false;
630     }
631 
632     /**
633      * Writes extra xml attributes to {@link #TAG_MANAGED_SERVICES} tag.
634      */
writeExtraAttributes(TypedXmlSerializer out, int userId)635     protected void writeExtraAttributes(TypedXmlSerializer out, int userId) throws IOException {}
636 
637     /**
638      * Writes extra xml tags within the parent tag specified in {@link Config#xmlTag}.
639      */
writeExtraXmlTags(TypedXmlSerializer out)640     protected void writeExtraXmlTags(TypedXmlSerializer out) throws IOException {}
641 
642     /**
643      * This is called to process tags other than {@link #TAG_MANAGED_SERVICES}.
644      */
readExtraTag(String tag, TypedXmlPullParser parser)645     protected void readExtraTag(String tag, TypedXmlPullParser parser)
646             throws IOException, XmlPullParserException {}
647 
migrateToXml()648     protected final void migrateToXml() {
649         for (UserInfo user : mUm.getUsers()) {
650             final ContentResolver cr = mContext.getContentResolver();
651             if (!TextUtils.isEmpty(getConfig().secureSettingName)) {
652                 addApprovedList(Settings.Secure.getStringForUser(
653                         cr,
654                         getConfig().secureSettingName,
655                         user.id), user.id, true);
656             }
657             if (!TextUtils.isEmpty(getConfig().secondarySettingName)) {
658                 addApprovedList(Settings.Secure.getStringForUser(
659                         cr,
660                         getConfig().secondarySettingName,
661                         user.id), user.id, false);
662             }
663         }
664     }
665 
readDefaults(TypedXmlPullParser parser)666     void readDefaults(TypedXmlPullParser parser) {
667         String defaultComponents = XmlUtils.readStringAttribute(parser, ATT_DEFAULTS);
668 
669         if (!TextUtils.isEmpty(defaultComponents)) {
670             String[] components = defaultComponents.split(ENABLED_SERVICES_SEPARATOR);
671             synchronized (mDefaultsLock) {
672                 for (int i = 0; i < components.length; i++) {
673                     if (!TextUtils.isEmpty(components[i])) {
674                         ComponentName cn = ComponentName.unflattenFromString(components[i]);
675                         if (cn != null) {
676                             mDefaultPackages.add(cn.getPackageName());
677                             mDefaultComponents.add(cn);
678                         } else {
679                             mDefaultPackages.add(components[i]);
680                         }
681                     }
682                 }
683             }
684         }
685     }
686 
readXml( TypedXmlPullParser parser, TriPredicate<String, Integer, String> allowedManagedServicePackages, boolean forRestore, int userId)687     public void readXml(
688             TypedXmlPullParser parser,
689             TriPredicate<String, Integer, String> allowedManagedServicePackages,
690             boolean forRestore,
691             int userId)
692             throws XmlPullParserException, IOException {
693         // read grants
694         int type;
695         String version = XmlUtils.readStringAttribute(parser, ATT_VERSION);
696         boolean needUpgradeUserset = false;
697         readDefaults(parser);
698         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
699             String tag = parser.getName();
700             if (type == XmlPullParser.END_TAG
701                     && getConfig().xmlTag.equals(tag)) {
702                 break;
703             }
704             if (type == XmlPullParser.START_TAG) {
705                 if (TAG_MANAGED_SERVICES.equals(tag)) {
706                     Slog.i(TAG, "Read " + mConfig.caption + " permissions from xml");
707 
708                     final String approved = XmlUtils.readStringAttribute(parser, ATT_APPROVED_LIST);
709                     // Ignore parser's user id for restore.
710                     final int resolvedUserId = forRestore
711                             ? userId : parser.getAttributeInt(null, ATT_USER_ID, 0);
712                     final boolean isPrimary =
713                             parser.getAttributeBoolean(null, ATT_IS_PRIMARY, true);
714 
715                     // Load three different userSet attributes from xml
716                     // user_changed, not null if version == 4 and is NAS setting
717                     final String isUserChanged = XmlUtils.readStringAttribute(parser,
718                             ATT_USER_CHANGED);
719                     // user_set, not null if version <= 3
720                     final String isUserChanged_Old = XmlUtils.readStringAttribute(parser,
721                             ATT_USER_SET_OLD);
722                     // user_set_services, not null if version >= 3 and is non-NAS setting
723                     String userSetComponent = XmlUtils.readStringAttribute(parser, ATT_USER_SET);
724 
725                     // since the same xml version may have different userSet attributes,
726                     // we need to check both xml version and userSet values to know how to set
727                     // the userSetComponent/mIsUserChanged to the correct value
728                     if (DB_VERSION.equals(version)) {
729                         // version 4, NAS contains user_changed and
730                         // NLS/others contain user_set_services
731                         if (isUserChanged == null) { //NLS
732                             userSetComponent = TextUtils.emptyIfNull(userSetComponent);
733                         } else { //NAS
734                             synchronized (mApproved) {
735                                 mIsUserChanged.put(resolvedUserId, Boolean.valueOf(isUserChanged));
736                             }
737                             userSetComponent = Boolean.valueOf(isUserChanged) ? approved : "";
738                         }
739                     } else {
740                         // version 3 may contain user_set (R) or user_set_services (S)
741                         // version 2 or older contain user_set or nothing
742                         needUpgradeUserset = true;
743                         if (userSetComponent == null) { //contains user_set
744                             if (isUserChanged_Old != null && Boolean.valueOf(isUserChanged_Old)) {
745                                 //user_set = true
746                                 userSetComponent = approved;
747                                 synchronized (mApproved) {
748                                     mIsUserChanged.put(resolvedUserId, true);
749                                 }
750                                 needUpgradeUserset = false;
751                             } else {
752                                 userSetComponent = "";
753                             }
754                         }
755                     }
756                     readExtraAttributes(tag, parser, resolvedUserId);
757                     if (isUserChanged != null && approved.isEmpty()) {
758                         // NAS
759                         denyPregrantedAppUserSet(resolvedUserId, isPrimary);
760                         mUseXml = true;
761                     } else {
762                         if (allowedManagedServicePackages == null
763                                 || allowedManagedServicePackages.test(
764                                 getPackageName(approved), resolvedUserId, getRequiredPermission())
765                                 || approved.isEmpty()) {
766                             if (mUm.getUserInfo(resolvedUserId) != null) {
767                                 addApprovedList(approved, resolvedUserId, isPrimary,
768                                         userSetComponent);
769                             }
770                             mUseXml = true;
771                         }
772                     }
773                 } else {
774                     readExtraTag(tag, parser);
775                 }
776             }
777         }
778         boolean isOldVersion = TextUtils.isEmpty(version)
779                 || DB_VERSION_1.equals(version)
780                 || DB_VERSION_2.equals(version)
781                 || DB_VERSION_3.equals(version);
782         if (isOldVersion) {
783             upgradeDefaultsXmlVersion();
784         }
785         if (needUpgradeUserset) {
786             upgradeUserSet();
787         }
788 
789         rebindServices(false, USER_ALL);
790     }
791 
upgradeDefaultsXmlVersion()792     void upgradeDefaultsXmlVersion() {
793         int defaultsSize;
794         synchronized (mDefaultsLock) {
795             // check if any defaults are loaded
796             defaultsSize = mDefaultComponents.size() + mDefaultPackages.size();
797         }
798         if (defaultsSize == 0) {
799             // load defaults from current allowed
800             if (this.mApprovalLevel == APPROVAL_BY_COMPONENT) {
801                 List<ComponentName> approvedComponents = getAllowedComponents(USER_SYSTEM);
802                 for (int i = 0; i < approvedComponents.size(); i++) {
803                     addDefaultComponentOrPackage(approvedComponents.get(i).flattenToString());
804                 }
805             }
806             if (this.mApprovalLevel == APPROVAL_BY_PACKAGE) {
807                 List<String> approvedPkgs = getAllowedPackages(USER_SYSTEM);
808                 for (int i = 0; i < approvedPkgs.size(); i++) {
809                     addDefaultComponentOrPackage(approvedPkgs.get(i));
810                 }
811             }
812         }
813         synchronized (mDefaultsLock) {
814             defaultsSize = mDefaultComponents.size() + mDefaultPackages.size();
815         }
816         // if no defaults are loaded, then load from config
817         if (defaultsSize == 0) {
818             loadDefaultsFromConfig();
819         }
820     }
821 
upgradeUserSet()822     protected void upgradeUserSet() {};
823 
824     /**
825      * Read extra attributes in the {@link #TAG_MANAGED_SERVICES} tag.
826      */
readExtraAttributes(String tag, TypedXmlPullParser parser, int userId)827     protected void readExtraAttributes(String tag, TypedXmlPullParser parser, int userId)
828             throws IOException {}
829 
getRequiredPermission()830     protected abstract String getRequiredPermission();
831 
addApprovedList(String approved, int userId, boolean isPrimary)832     protected void addApprovedList(String approved, int userId, boolean isPrimary) {
833         addApprovedList(approved, userId, isPrimary, approved);
834     }
835 
addApprovedList(String approved, int userId, boolean isPrimary, String userSet)836     protected void addApprovedList(String approved, int userId, boolean isPrimary, String userSet) {
837         if (TextUtils.isEmpty(approved)) {
838             approved = "";
839         }
840         if (userSet == null) {
841             userSet = approved;
842         }
843         synchronized (mApproved) {
844             ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
845             if (approvedByType == null) {
846                 approvedByType = new ArrayMap<>();
847                 mApproved.put(userId, approvedByType);
848             }
849 
850             ArraySet<String> approvedList = approvedByType.get(isPrimary);
851             if (approvedList == null) {
852                 approvedList = new ArraySet<>();
853                 approvedByType.put(isPrimary, approvedList);
854             }
855 
856             String[] approvedArray = approved.split(ENABLED_SERVICES_SEPARATOR);
857             for (String pkgOrComponent : approvedArray) {
858                 String approvedItem = getApprovedValue(pkgOrComponent);
859                 if (approvedItem != null) {
860                     approvedList.add(approvedItem);
861                 }
862             }
863 
864             ArraySet<String> userSetList = mUserSetServices.get(userId);
865             if (userSetList == null) {
866                 userSetList = new ArraySet<>();
867                 mUserSetServices.put(userId, userSetList);
868             }
869             String[] userSetArray = userSet.split(ENABLED_SERVICES_SEPARATOR);
870             for (String pkgOrComponent : userSetArray) {
871                 String approvedItem = getApprovedValue(pkgOrComponent);
872                 if (approvedItem != null) {
873                     userSetList.add(approvedItem);
874                 }
875             }
876         }
877     }
878 
denyPregrantedAppUserSet(int userId, boolean isPrimary)879     protected void denyPregrantedAppUserSet(int userId, boolean isPrimary) {
880         synchronized (mApproved) {
881             ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
882             if (approvedByType == null) {
883                 approvedByType = new ArrayMap<>();
884                 mApproved.put(userId, approvedByType);
885             }
886             approvedByType.put(isPrimary, new ArraySet<>());
887         }
888     }
889 
890     /** convenience method for looking in mEnabledServicesPackageNamesByUser
891      * for UserHandle.USER_CURRENT.
892      * This is a legacy API. When FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER becomes
893      * trunk stable,  this API should be deprecated.  Additionally, when this method
894      * is deprecated, the unit tests written using this method should also be revised.
895      *
896      * @param pkg target package name
897      * @return boolean value that indicates whether it is enabled for the current profiles
898      */
isComponentEnabledForPackage(String pkg)899     protected boolean isComponentEnabledForPackage(String pkg) {
900         return isComponentEnabledForPackage(pkg, UserHandle.USER_CURRENT);
901     }
902 
903     /** convenience method for looking in mEnabledServicesPackageNamesByUser
904      *
905      * @param pkg target package name
906      * @param userId the id of the target user
907      * @return boolean value that indicates whether it is enabled for the target user
908      */
909     @FlaggedApi(FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER)
isComponentEnabledForPackage(String pkg, int userId)910     protected boolean isComponentEnabledForPackage(String pkg, int userId) {
911         synchronized (mMutex) {
912             ArraySet<String> enabledServicesPackageNames =
913                     mEnabledServicesPackageNamesByUser.get(resolveUserId(userId));
914             return enabledServicesPackageNames != null && enabledServicesPackageNames.contains(pkg);
915         }
916     }
917 
setPackageOrComponentEnabled(String pkgOrComponent, int userId, boolean isPrimary, boolean enabled)918     protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId,
919             boolean isPrimary, boolean enabled) {
920         setPackageOrComponentEnabled(pkgOrComponent, userId, isPrimary, enabled, true);
921     }
922 
setPackageOrComponentEnabled(String pkgOrComponent, int userId, boolean isPrimary, boolean enabled, boolean userSet)923     protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId,
924             boolean isPrimary, boolean enabled, boolean userSet) {
925         Slog.i(TAG,
926                 (enabled ? " Allowing " : "Disallowing ") + mConfig.caption + " "
927                         + pkgOrComponent + " (userSet: " + userSet + ")");
928         synchronized (mApproved) {
929             ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.get(userId);
930             if (allowedByType == null) {
931                 allowedByType = new ArrayMap<>();
932                 mApproved.put(userId, allowedByType);
933             }
934             ArraySet<String> approved = allowedByType.get(isPrimary);
935             if (approved == null) {
936                 approved = new ArraySet<>();
937                 allowedByType.put(isPrimary, approved);
938             }
939             String approvedItem = getApprovedValue(pkgOrComponent);
940 
941             if (approvedItem != null) {
942                 if (enabled) {
943                     approved.add(approvedItem);
944                 } else {
945                     approved.remove(approvedItem);
946                 }
947             }
948             ArraySet<String> userSetServices = mUserSetServices.get(userId);
949             if (userSetServices == null) {
950                 userSetServices = new ArraySet<>();
951                 mUserSetServices.put(userId, userSetServices);
952             }
953             if (userSet) {
954                 userSetServices.add(pkgOrComponent);
955             } else {
956                 userSetServices.remove(pkgOrComponent);
957             }
958         }
959 
960         rebindServices(false, userId);
961     }
962 
getApprovedValue(String pkgOrComponent)963     private String getApprovedValue(String pkgOrComponent) {
964         if (mApprovalLevel == APPROVAL_BY_COMPONENT) {
965             if(ComponentName.unflattenFromString(pkgOrComponent) != null) {
966                 return pkgOrComponent;
967             }
968             return null;
969         } else {
970             return getPackageName(pkgOrComponent);
971         }
972     }
973 
getApproved(int userId, boolean primary)974     protected String getApproved(int userId, boolean primary) {
975         synchronized (mApproved) {
976             final ArrayMap<Boolean, ArraySet<String>> allowedByType =
977                     mApproved.getOrDefault(userId, new ArrayMap<>());
978             ArraySet<String> approved = allowedByType.getOrDefault(primary, new ArraySet<>());
979             return String.join(ENABLED_SERVICES_SEPARATOR, approved);
980         }
981     }
982 
getAllowedComponents(int userId)983     protected List<ComponentName> getAllowedComponents(int userId) {
984         final List<ComponentName> allowedComponents = new ArrayList<>();
985         synchronized (mApproved) {
986             final ArrayMap<Boolean, ArraySet<String>> allowedByType =
987                     mApproved.getOrDefault(userId, new ArrayMap<>());
988             for (int i = 0; i < allowedByType.size(); i++) {
989                 final ArraySet<String> allowed = allowedByType.valueAt(i);
990                 for (int j = 0; j < allowed.size(); j++) {
991                     ComponentName cn = ComponentName.unflattenFromString(allowed.valueAt(j));
992                     if (cn != null) {
993                         allowedComponents.add(cn);
994                     }
995                 }
996             }
997         }
998         return allowedComponents;
999     }
1000 
1001     @NonNull
getAllowedPackages(int userId)1002     protected List<String> getAllowedPackages(int userId) {
1003         final List<String> allowedPackages = new ArrayList<>();
1004         synchronized (mApproved) {
1005             final ArrayMap<Boolean, ArraySet<String>> allowedByType =
1006                     mApproved.getOrDefault(userId, new ArrayMap<>());
1007             for (int i = 0; i < allowedByType.size(); i++) {
1008                 final ArraySet<String> allowed = allowedByType.valueAt(i);
1009                 for (int j = 0; j < allowed.size(); j++) {
1010                     String pkgName = getPackageName(allowed.valueAt(j));
1011                     if (!TextUtils.isEmpty(pkgName)) {
1012                         allowedPackages.add(pkgName);
1013                     }
1014                 }
1015             }
1016         }
1017         return allowedPackages;
1018     }
1019 
isPackageOrComponentAllowed(String pkgOrComponent, int userId)1020     protected boolean isPackageOrComponentAllowed(String pkgOrComponent, int userId) {
1021         synchronized (mApproved) {
1022             ArrayMap<Boolean, ArraySet<String>> allowedByType =
1023                     mApproved.getOrDefault(userId, new ArrayMap<>());
1024             for (int i = 0; i < allowedByType.size(); i++) {
1025                 ArraySet<String> allowed = allowedByType.valueAt(i);
1026                 if (allowed.contains(pkgOrComponent)) {
1027                     return true;
1028                 }
1029             }
1030         }
1031         return false;
1032     }
1033 
isPackageOrComponentAllowedWithPermission(ComponentName component, int userId)1034     protected boolean isPackageOrComponentAllowedWithPermission(ComponentName component,
1035             int userId) {
1036         if (!(isPackageOrComponentAllowed(component.flattenToString(), userId)
1037                 || isPackageOrComponentAllowed(component.getPackageName(), userId))) {
1038             return false;
1039         }
1040         return componentHasBindPermission(component, userId);
1041     }
1042 
componentHasBindPermission(ComponentName component, int userId)1043     private boolean componentHasBindPermission(ComponentName component, int userId) {
1044         ServiceInfo info = getServiceInfo(component, userId);
1045         if (info == null) {
1046             return false;
1047         }
1048         return mConfig.bindPermission.equals(info.permission);
1049     }
1050 
isPackageOrComponentUserSet(String pkgOrComponent, int userId)1051     boolean isPackageOrComponentUserSet(String pkgOrComponent, int userId) {
1052         synchronized (mApproved) {
1053             ArraySet<String> services = mUserSetServices.get(userId);
1054             return services != null && services.contains(pkgOrComponent);
1055         }
1056     }
1057 
isPackageAllowed(String pkg, int userId)1058     protected boolean isPackageAllowed(String pkg, int userId) {
1059         if (pkg == null) {
1060             return false;
1061         }
1062         synchronized (mApproved) {
1063             ArrayMap<Boolean, ArraySet<String>> allowedByType =
1064                     mApproved.getOrDefault(userId, new ArrayMap<>());
1065             for (int i = 0; i < allowedByType.size(); i++) {
1066                 ArraySet<String> allowed = allowedByType.valueAt(i);
1067                 for (String allowedEntry : allowed) {
1068                     ComponentName component = ComponentName.unflattenFromString(allowedEntry);
1069                     if (component != null) {
1070                         if (pkg.equals(component.getPackageName())) {
1071                             return true;
1072                         }
1073                     } else {
1074                         if (pkg.equals(allowedEntry)) {
1075                             return true;
1076                         }
1077                     }
1078                 }
1079             }
1080         }
1081         return false;
1082     }
1083 
onPackagesChanged(boolean removingPackage, String[] pkgList, int[] uidList)1084     public void onPackagesChanged(boolean removingPackage, String[] pkgList, int[] uidList) {
1085         if (DEBUG) {
1086             synchronized (mMutex) {
1087                 int resolvedUserId = (managedServicesConcurrentMultiuser()
1088                         && (uidList != null && uidList.length > 0))
1089                         ? resolveUserId(UserHandle.getUserId(uidList[0]))
1090                         : UserHandle.USER_CURRENT;
1091                 Slog.d(TAG, "onPackagesChanged removingPackage=" + removingPackage
1092                         + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList))
1093                         + " mEnabledServicesPackageNames="
1094                         + mEnabledServicesPackageNamesByUser.get(resolvedUserId));
1095             }
1096         }
1097 
1098         if (pkgList != null && (pkgList.length > 0)) {
1099             boolean anyServicesInvolved = false;
1100             // Remove notification settings for uninstalled package
1101             if (removingPackage && uidList != null) {
1102                 int size = Math.min(pkgList.length, uidList.length);
1103                 for (int i = 0; i < size; i++) {
1104                     final String pkg = pkgList[i];
1105                     final int userId = UserHandle.getUserId(uidList[i]);
1106                     anyServicesInvolved = removeUninstalledItemsFromApprovedLists(userId, pkg);
1107                 }
1108             }
1109             for (String pkgName : pkgList) {
1110                 if (!managedServicesConcurrentMultiuser()) {
1111                     if (isComponentEnabledForPackage(pkgName)) {
1112                         anyServicesInvolved = true;
1113                     }
1114                 }
1115                 if (uidList != null && uidList.length > 0) {
1116                     for (int uid : uidList) {
1117                         if (managedServicesConcurrentMultiuser()) {
1118                             if (isComponentEnabledForPackage(pkgName, UserHandle.getUserId(uid))) {
1119                                 anyServicesInvolved = true;
1120                             }
1121                         }
1122                         if (isPackageAllowed(pkgName, UserHandle.getUserId(uid))) {
1123                             anyServicesInvolved = true;
1124                             trimApprovedListsForInvalidServices(pkgName, UserHandle.getUserId(uid));
1125                         }
1126                     }
1127                 }
1128             }
1129 
1130             if (anyServicesInvolved) {
1131                 // make sure we're still bound to any of our services who may have just upgraded
1132                 rebindServices(false, USER_ALL);
1133             }
1134         }
1135     }
1136 
onUserRemoved(int user)1137     public void onUserRemoved(int user) {
1138         Slog.i(TAG, "Removing approved services for removed user " + user);
1139         synchronized (mApproved) {
1140             mApproved.remove(user);
1141         }
1142         synchronized (mSnoozing) {
1143             mSnoozing.remove(user);
1144         }
1145         unbindUserServices(user);
1146     }
1147 
1148     /**
1149      * Call this method when a user is stopped
1150      *
1151      * @param user the id of the stopped user
1152      */
onUserStopped(int user)1153     public void onUserStopped(int user) {
1154         if (!managedServicesConcurrentMultiuser()) {
1155             return;
1156         }
1157         boolean hasAny = false;
1158         synchronized (mMutex) {
1159             if (mEnabledServicesByUser.contains(user)
1160                     && mEnabledServicesPackageNamesByUser.contains(user)) {
1161                 // Through the ManagedServices.resolveUserId,
1162                 // we resolve UserHandle.USER_CURRENT as the key for users
1163                 // other than the visible background user.
1164                 // Therefore, the user IDs that exist as keys for each member variable
1165                 // correspond to the visible background user.
1166                 // We need to unbind services of the stopped visible background user.
1167                 mEnabledServicesByUser.remove(user);
1168                 mEnabledServicesPackageNamesByUser.remove(user);
1169                 hasAny = true;
1170             }
1171         }
1172         if (hasAny) {
1173             Slog.i(TAG, "Removing approved services for stopped user " + user);
1174             unbindUserServices(user);
1175         }
1176     }
1177 
onUserSwitched(int user)1178     public void onUserSwitched(int user) {
1179         if (DEBUG) Slog.d(TAG, "onUserSwitched u=" + user);
1180         unbindOtherUserServices(user);
1181         rebindServices(true, user);
1182     }
1183 
onUserUnlocked(int user)1184     public void onUserUnlocked(int user) {
1185         if (DEBUG) Slog.d(TAG, "onUserUnlocked u=" + user);
1186         rebindServices(false, user);
1187     }
1188 
getServiceFromTokenLocked(IInterface service)1189     private ManagedServiceInfo getServiceFromTokenLocked(IInterface service) {
1190         if (service == null) {
1191             return null;
1192         }
1193         final IBinder token = service.asBinder();
1194         synchronized (mMutex) {
1195             final int nServices = mServices.size();
1196             for (int i = 0; i < nServices; i++) {
1197                 final ManagedServiceInfo info = mServices.get(i);
1198                 if (info.service.asBinder() == token) return info;
1199             }
1200         }
1201         return null;
1202     }
1203 
isServiceTokenValidLocked(IInterface service)1204     protected boolean isServiceTokenValidLocked(IInterface service) {
1205         if (service == null) {
1206             return false;
1207         }
1208         ManagedServiceInfo info = getServiceFromTokenLocked(service);
1209         if (info != null) {
1210             return true;
1211         }
1212         return false;
1213     }
1214 
checkServiceTokenLocked(IInterface service)1215     protected ManagedServiceInfo checkServiceTokenLocked(IInterface service) {
1216         checkNotNull(service);
1217         ManagedServiceInfo info = getServiceFromTokenLocked(service);
1218         if (info != null) {
1219             return info;
1220         }
1221         throw new SecurityException("Disallowed call from unknown " + getCaption() + ": "
1222                 + service.asBinder() + " " + service.getClass());
1223     }
1224 
isSameUser(IInterface service, int userId)1225     public boolean isSameUser(IInterface service, int userId) {
1226         checkNotNull(service);
1227         synchronized (mMutex) {
1228             ManagedServiceInfo info = getServiceFromTokenLocked(service);
1229             if (info != null) {
1230                 return info.isSameUser(userId);
1231             }
1232             return false;
1233         }
1234     }
1235 
unregisterService(IInterface service, int userid)1236     public void unregisterService(IInterface service, int userid) {
1237         checkNotNull(service);
1238         // no need to check permissions; if your service binder is in the list,
1239         // that's proof that you had permission to add it in the first place
1240         unregisterServiceImpl(service, userid);
1241     }
1242 
registerSystemService(IInterface service, ComponentName component, int userid, int uid)1243     public void registerSystemService(IInterface service, ComponentName component, int userid,
1244             int uid) {
1245         checkNotNull(service);
1246         ManagedServiceInfo info = registerServiceImpl(
1247                 service, component, userid, Build.VERSION_CODES.CUR_DEVELOPMENT, uid);
1248         if (info != null) {
1249             onServiceAdded(info);
1250         }
1251     }
1252 
1253     /**
1254      * Add a service to our callbacks. The lifecycle of this service is managed externally,
1255      * but unlike a system service, it should not be considered privileged.
1256      * */
registerGuestService(ManagedServiceInfo guest)1257     protected void registerGuestService(ManagedServiceInfo guest) {
1258         checkNotNull(guest.service);
1259         if (!checkType(guest.service)) {
1260             throw new IllegalArgumentException();
1261         }
1262         if (registerServiceImpl(guest) != null) {
1263             onServiceAdded(guest);
1264         }
1265     }
1266 
setComponentState(ComponentName component, int userId, boolean enabled)1267     protected void setComponentState(ComponentName component, int userId, boolean enabled) {
1268         synchronized (mSnoozing) {
1269             boolean previous = !mSnoozing.contains(userId, component);
1270             if (previous == enabled) {
1271                 return;
1272             }
1273 
1274             if (enabled) {
1275                 mSnoozing.remove(userId, component);
1276             } else {
1277                 mSnoozing.add(userId, component);
1278             }
1279         }
1280 
1281         // State changed
1282         Slog.d(TAG, ((enabled) ? "Enabling " : "Disabling ") + "component " +
1283                 component.flattenToShortString());
1284 
1285         synchronized (mMutex) {
1286             if (enabled) {
1287                 if (isPackageOrComponentAllowedWithPermission(component, userId)) {
1288                     registerServiceLocked(component, userId);
1289                 } else {
1290                     Slog.d(TAG, component + " no longer has permission to be bound");
1291                 }
1292             } else {
1293                 unregisterServiceLocked(component, userId);
1294             }
1295         }
1296     }
1297 
loadComponentNamesFromValues( ArraySet<String> approved, int userId)1298     private @NonNull ArraySet<ComponentName> loadComponentNamesFromValues(
1299             ArraySet<String> approved, int userId) {
1300         if (approved == null || approved.size() == 0)
1301             return new ArraySet<>();
1302         ArraySet<ComponentName> result = new ArraySet<>(approved.size());
1303         for (int i = 0; i < approved.size(); i++) {
1304             final String packageOrComponent = approved.valueAt(i);
1305             if (!TextUtils.isEmpty(packageOrComponent)) {
1306                 ComponentName component = ComponentName.unflattenFromString(packageOrComponent);
1307                 if (component != null) {
1308                     result.add(component);
1309                 } else {
1310                     result.addAll(queryPackageForServices(packageOrComponent, userId));
1311                 }
1312             }
1313         }
1314         return result;
1315     }
1316 
queryPackageForServices(String packageName, int userId)1317     protected Set<ComponentName> queryPackageForServices(String packageName, int userId) {
1318         return queryPackageForServices(packageName, 0, userId);
1319     }
1320 
queryPackageForServices(String packageName, int extraFlags, int userId)1321     protected ArraySet<ComponentName> queryPackageForServices(String packageName, int extraFlags,
1322             int userId) {
1323         ArraySet<ComponentName> installed = new ArraySet<>();
1324         final PackageManager pm = mContext.getPackageManager();
1325         Intent queryIntent = new Intent(mConfig.serviceInterface);
1326         if (!TextUtils.isEmpty(packageName)) {
1327             queryIntent.setPackage(packageName);
1328         }
1329         List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
1330                 queryIntent,
1331                 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA | extraFlags,
1332                 userId);
1333         if (DEBUG)
1334             Slog.v(TAG, mConfig.serviceInterface + " services: " + installedServices);
1335         if (installedServices != null) {
1336             for (int i = 0, count = installedServices.size(); i < count; i++) {
1337                 ResolveInfo resolveInfo = installedServices.get(i);
1338                 ServiceInfo info = resolveInfo.serviceInfo;
1339 
1340                 ComponentName component = new ComponentName(info.packageName, info.name);
1341                 if (!mConfig.bindPermission.equals(info.permission)) {
1342                     Slog.w(TAG, "Skipping " + getCaption() + " service "
1343                         + info.packageName + "/" + info.name
1344                         + ": it does not require the permission "
1345                         + mConfig.bindPermission);
1346                     continue;
1347                 }
1348                 installed.add(component);
1349             }
1350         }
1351         return installed;
1352     }
1353 
trimApprovedListsAccordingToInstalledServices(int userId)1354     private void trimApprovedListsAccordingToInstalledServices(int userId) {
1355         synchronized (mApproved) {
1356             final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
1357             if (approvedByType == null) {
1358                 return;
1359             }
1360             for (int i = 0; i < approvedByType.size(); i++) {
1361                 final ArraySet<String> approved = approvedByType.valueAt(i);
1362                 for (int j = approved.size() - 1; j >= 0; j--) {
1363                     final String approvedPackageOrComponent = approved.valueAt(j);
1364                     if (!isValidEntry(approvedPackageOrComponent, userId)) {
1365                         approved.removeAt(j);
1366                         Slog.v(TAG, "Removing " + approvedPackageOrComponent
1367                                 + " from approved list; no matching services found");
1368                     } else {
1369                         if (DEBUG) {
1370                             Slog.v(TAG, "Keeping " + approvedPackageOrComponent
1371                                     + " on approved list; matching services found");
1372                         }
1373                     }
1374                 }
1375             }
1376         }
1377     }
1378 
removeUninstalledItemsFromApprovedLists(int uninstalledUserId, String pkg)1379     private boolean removeUninstalledItemsFromApprovedLists(int uninstalledUserId, String pkg) {
1380         boolean removed = false;
1381         synchronized (mApproved) {
1382             final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(
1383                     uninstalledUserId);
1384             if (approvedByType != null) {
1385                 int M = approvedByType.size();
1386                 for (int j = 0; j < M; j++) {
1387                     final ArraySet<String> approved = approvedByType.valueAt(j);
1388                     int O = approved.size();
1389                     for (int k = O - 1; k >= 0; k--) {
1390                         final String packageOrComponent = approved.valueAt(k);
1391                         final String packageName = getPackageName(packageOrComponent);
1392                         if (TextUtils.equals(pkg, packageName)) {
1393                             approved.removeAt(k);
1394                             if (DEBUG) {
1395                                 Slog.v(TAG, "Removing " + packageOrComponent
1396                                         + " from approved list; uninstalled");
1397                             }
1398                         }
1399                     }
1400                 }
1401             }
1402             // Remove uninstalled components from user-set list
1403             final ArraySet<String> userSet = mUserSetServices.get(uninstalledUserId);
1404             if (userSet != null) {
1405                 int numServices = userSet.size();
1406                 for (int i = numServices - 1; i >= 0; i--) {
1407                     String pkgOrComponent = userSet.valueAt(i);
1408                     if (TextUtils.equals(pkg, getPackageName(pkgOrComponent))) {
1409                         userSet.removeAt(i);
1410                         if (DEBUG) {
1411                             Slog.v(TAG, "Removing " + pkgOrComponent
1412                                     + " from user-set list; uninstalled");
1413                         }
1414                     }
1415                 }
1416             }
1417         }
1418         return removed;
1419     }
1420 
trimApprovedListsForInvalidServices(String packageName, int userId)1421     private void trimApprovedListsForInvalidServices(String packageName, int userId) {
1422         synchronized (mApproved) {
1423             final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
1424             if (approvedByType == null) {
1425                 return;
1426             }
1427             for (int i = 0; i < approvedByType.size(); i++) {
1428                 final ArraySet<String> approved = approvedByType.valueAt(i);
1429                 for (int j = approved.size() - 1; j >= 0; j--) {
1430                     final String approvedPackageOrComponent = approved.valueAt(j);
1431                     if (TextUtils.equals(getPackageName(approvedPackageOrComponent), packageName)) {
1432                         final ComponentName component = ComponentName.unflattenFromString(
1433                                 approvedPackageOrComponent);
1434                         if (component != null && !componentHasBindPermission(component, userId)) {
1435                             approved.removeAt(j);
1436                             if (DEBUG) {
1437                                 Slog.v(TAG, "Removing " + approvedPackageOrComponent
1438                                         + " from approved list; no bind permission found "
1439                                         + mConfig.bindPermission);
1440                             }
1441                         }
1442                     }
1443                 }
1444             }
1445         }
1446     }
1447 
getPackageName(String packageOrComponent)1448     protected String getPackageName(String packageOrComponent) {
1449         final ComponentName component = ComponentName.unflattenFromString(packageOrComponent);
1450         if (component != null) {
1451             return component.getPackageName();
1452         } else {
1453             return packageOrComponent;
1454         }
1455     }
1456 
isValidEntry(String packageOrComponent, int userId)1457     protected boolean isValidEntry(String packageOrComponent, int userId) {
1458         return hasMatchingServices(packageOrComponent, userId);
1459     }
1460 
hasMatchingServices(String packageOrComponent, int userId)1461     private boolean hasMatchingServices(String packageOrComponent, int userId) {
1462         if (!TextUtils.isEmpty(packageOrComponent)) {
1463             final String packageName = getPackageName(packageOrComponent);
1464             return queryPackageForServices(packageName, userId).size() > 0;
1465         }
1466         return false;
1467     }
1468 
1469     @VisibleForTesting
getAllowedComponents(IntArray userIds)1470     protected SparseArray<ArraySet<ComponentName>> getAllowedComponents(IntArray userIds) {
1471         final int nUserIds = userIds.size();
1472         final SparseArray<ArraySet<ComponentName>> componentsByUser = new SparseArray<>();
1473 
1474         for (int i = 0; i < nUserIds; ++i) {
1475             final int userId = userIds.get(i);
1476             synchronized (mApproved) {
1477                 final ArrayMap<Boolean, ArraySet<String>> approvedLists = mApproved.get(userId);
1478                 if (approvedLists != null) {
1479                     final int N = approvedLists.size();
1480                     for (int j = 0; j < N; j++) {
1481                         ArraySet<ComponentName> approvedByUser = componentsByUser.get(userId);
1482                         if (approvedByUser == null) {
1483                             approvedByUser = new ArraySet<>();
1484                             componentsByUser.put(userId, approvedByUser);
1485                         }
1486                         approvedByUser.addAll(
1487                                 loadComponentNamesFromValues(approvedLists.valueAt(j), userId));
1488                     }
1489                 }
1490             }
1491         }
1492         return componentsByUser;
1493     }
1494 
1495     @GuardedBy("mMutex")
populateComponentsToBind(SparseArray<Set<ComponentName>> componentsToBind, final IntArray activeUsers, SparseArray<ArraySet<ComponentName>> approvedComponentsByUser)1496     protected void populateComponentsToBind(SparseArray<Set<ComponentName>> componentsToBind,
1497             final IntArray activeUsers,
1498             SparseArray<ArraySet<ComponentName>> approvedComponentsByUser) {
1499         final int nUserIds = activeUsers.size();
1500         if (managedServicesConcurrentMultiuser()) {
1501             for (int i = 0; i < nUserIds; ++i) {
1502                 final int resolvedUserId = resolveUserId(activeUsers.get(i));
1503                 if (mEnabledServicesByUser.get(resolvedUserId) != null) {
1504                     mEnabledServicesByUser.get(resolvedUserId).clear();
1505                 }
1506                 if (mEnabledServicesPackageNamesByUser.get(resolvedUserId) != null) {
1507                     mEnabledServicesPackageNamesByUser.get(resolvedUserId).clear();
1508                 }
1509             }
1510         } else {
1511             mEnabledServicesByUser.get(UserHandle.USER_CURRENT).clear();
1512             mEnabledServicesPackageNamesByUser.get(UserHandle.USER_CURRENT).clear();
1513         }
1514         for (int i = 0; i < nUserIds; ++i) {
1515             final int userId = activeUsers.get(i);
1516             // decode the list of components
1517             final ArraySet<ComponentName> userComponents = approvedComponentsByUser.get(userId);
1518             if (null == userComponents) {
1519                 componentsToBind.put(userId, new ArraySet<>());
1520                 continue;
1521             }
1522 
1523             final int resolvedUserId = managedServicesConcurrentMultiuser()
1524                     ? resolveUserId(userId)
1525                     : UserHandle.USER_CURRENT;
1526             ArraySet<ComponentName> enabledServices =
1527                     mEnabledServicesByUser.contains(resolvedUserId)
1528                     ? mEnabledServicesByUser.get(resolvedUserId)
1529                     : new ArraySet<>();
1530             ArraySet<String> enabledServicesPackageName =
1531                     mEnabledServicesPackageNamesByUser.contains(resolvedUserId)
1532                     ? mEnabledServicesPackageNamesByUser.get(resolvedUserId)
1533                     : new ArraySet<>();
1534 
1535             final Set<ComponentName> add = new HashSet<>(userComponents);
1536             synchronized (mSnoozing) {
1537                 ArraySet<ComponentName> snoozed = mSnoozing.get(userId);
1538                 if (snoozed != null) {
1539                     add.removeAll(snoozed);
1540                 }
1541             }
1542 
1543             componentsToBind.put(userId, add);
1544 
1545             enabledServices.addAll(userComponents);
1546             for (int j = 0; j < userComponents.size(); j++) {
1547                 enabledServicesPackageName.add(userComponents.valueAt(j).getPackageName());
1548             }
1549             mEnabledServicesByUser.put(resolvedUserId, enabledServices);
1550             mEnabledServicesPackageNamesByUser.put(resolvedUserId, enabledServicesPackageName);
1551         }
1552     }
1553 
1554     @GuardedBy("mMutex")
getRemovableConnectedServices()1555     protected Set<ManagedServiceInfo> getRemovableConnectedServices() {
1556         final Set<ManagedServiceInfo> removableBoundServices = new ArraySet<>();
1557         for (ManagedServiceInfo service : mServices) {
1558             if (!service.isSystem && !service.isGuest(this)) {
1559                 removableBoundServices.add(service);
1560             }
1561         }
1562         return removableBoundServices;
1563     }
1564 
populateComponentsToUnbind( boolean forceRebind, Set<ManagedServiceInfo> removableBoundServices, SparseArray<Set<ComponentName>> allowedComponentsToBind, SparseArray<Set<ComponentName>> componentsToUnbind)1565     protected void populateComponentsToUnbind(
1566             boolean forceRebind,
1567             Set<ManagedServiceInfo> removableBoundServices,
1568             SparseArray<Set<ComponentName>> allowedComponentsToBind,
1569             SparseArray<Set<ComponentName>> componentsToUnbind) {
1570         for (ManagedServiceInfo info : removableBoundServices) {
1571             final Set<ComponentName> allowedComponents = allowedComponentsToBind.get(info.userid);
1572             if (allowedComponents != null) {
1573                 if (forceRebind || !allowedComponents.contains(info.component)) {
1574                     Set<ComponentName> toUnbind =
1575                             componentsToUnbind.get(info.userid, new ArraySet<>());
1576                     toUnbind.add(info.component);
1577                     componentsToUnbind.put(info.userid, toUnbind);
1578                 }
1579             }
1580         }
1581     }
1582 
1583     /**
1584      * Called whenever packages change, the user switches, or the secure setting
1585      * is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
1586      */
rebindServices(boolean forceRebind, int userToRebind)1587     protected void rebindServices(boolean forceRebind, int userToRebind) {
1588         if (DEBUG) Slog.d(TAG, "rebindServices " + forceRebind + " " + userToRebind);
1589         boolean rebindAllCurrentUsers = mUserProfiles.isProfileUser(userToRebind, mContext)
1590                 && allowRebindForParentUser();
1591         IntArray userIds = getUserIdsForRebindServices(userToRebind, rebindAllCurrentUsers);
1592 
1593         final SparseArray<Set<ComponentName>> componentsToBind = new SparseArray<>();
1594         final SparseArray<Set<ComponentName>> componentsToUnbind = new SparseArray<>();
1595 
1596         synchronized (mMutex) {
1597             final SparseArray<ArraySet<ComponentName>> approvedComponentsByUser =
1598                     getAllowedComponents(userIds);
1599             final Set<ManagedServiceInfo> removableBoundServices = getRemovableConnectedServices();
1600 
1601             // Filter approvedComponentsByUser to collect all of the components that are allowed
1602             // for the currently active user(s).
1603             populateComponentsToBind(componentsToBind, userIds, approvedComponentsByUser);
1604 
1605             // For every current non-system connection, disconnect services that are no longer
1606             // approved, or ALL services if we are force rebinding
1607             populateComponentsToUnbind(
1608                     forceRebind, removableBoundServices, componentsToBind, componentsToUnbind);
1609         }
1610 
1611         unbindFromServices(componentsToUnbind);
1612         bindToServices(componentsToBind);
1613     }
1614 
getUserIdsForRebindServices(int userToRebind, boolean rebindAllCurrentUsers)1615     private IntArray getUserIdsForRebindServices(int userToRebind, boolean rebindAllCurrentUsers) {
1616         IntArray userIds = mUserProfiles.getCurrentProfileIds();
1617         if (userToRebind != USER_ALL && !rebindAllCurrentUsers) {
1618             userIds = new IntArray(1);
1619             userIds.add(userToRebind);
1620         } else if (managedServicesConcurrentMultiuser()
1621                 && userToRebind == USER_ALL) {
1622             for (UserInfo user : mUm.getUsers()) {
1623                 if (mUmInternal.isVisibleBackgroundFullUser(user.id)
1624                         && !userIds.contains(user.id)) {
1625                     userIds.add(user.id);
1626                 }
1627             }
1628         }
1629         return userIds;
1630     }
1631 
1632     /**
1633      * Called when user switched to unbind all services from other users.
1634      */
1635     @VisibleForTesting
unbindOtherUserServices(int currentUser)1636     void unbindOtherUserServices(int currentUser) {
1637         TimingsTraceAndSlog t = new TimingsTraceAndSlog();
1638         t.traceBegin("ManagedServices.unbindOtherUserServices_current" + currentUser);
1639         unbindServicesImpl(currentUser, true /* allExceptUser */);
1640         t.traceEnd();
1641     }
1642 
unbindUserServices(int user)1643     void unbindUserServices(int user) {
1644         TimingsTraceAndSlog t = new TimingsTraceAndSlog();
1645         t.traceBegin("ManagedServices.unbindUserServices" + user);
1646         unbindServicesImpl(user, false /* allExceptUser */);
1647         t.traceEnd();
1648     }
1649 
unbindServicesImpl(int user, boolean allExceptUser)1650     void unbindServicesImpl(int user, boolean allExceptUser) {
1651         final SparseArray<Set<ComponentName>> componentsToUnbind = new SparseArray<>();
1652         synchronized (mMutex) {
1653             final Set<ManagedServiceInfo> removableBoundServices = getRemovableConnectedServices();
1654             for (ManagedServiceInfo info : removableBoundServices) {
1655                 // User switching is the event for the forground user.
1656                 // It should not affect the service of the visible background user.
1657                 if ((allExceptUser && (info.userid != user)
1658                         && !(managedServicesConcurrentMultiuser()
1659                             && info.isVisibleBackgroundUserService))
1660                         || (!allExceptUser && (info.userid == user))) {
1661                     Set<ComponentName> toUnbind =
1662                             componentsToUnbind.get(info.userid, new ArraySet<>());
1663                     toUnbind.add(info.component);
1664                     componentsToUnbind.put(info.userid, toUnbind);
1665                 }
1666             }
1667         }
1668         unbindFromServices(componentsToUnbind);
1669     }
1670 
unbindFromServices(SparseArray<Set<ComponentName>> componentsToUnbind)1671     protected void unbindFromServices(SparseArray<Set<ComponentName>> componentsToUnbind) {
1672         for (int i = 0; i < componentsToUnbind.size(); i++) {
1673             final int userId = componentsToUnbind.keyAt(i);
1674             final Set<ComponentName> removableComponents = componentsToUnbind.get(userId);
1675             for (ComponentName cn : removableComponents) {
1676                 // No longer allowed to be bound, or must rebind.
1677                 Slog.v(TAG, "disabling " + getCaption() + " for user " + userId + ": " + cn);
1678                 unregisterService(cn, userId);
1679             }
1680         }
1681     }
1682 
1683     // Attempt to bind to services, skipping those that cannot be found or lack the permission.
bindToServices(SparseArray<Set<ComponentName>> componentsToBind)1684     private void bindToServices(SparseArray<Set<ComponentName>> componentsToBind) {
1685         for (int i = 0; i < componentsToBind.size(); i++) {
1686             final int userId = componentsToBind.keyAt(i);
1687             final Set<ComponentName> add = componentsToBind.get(userId);
1688             for (ComponentName component : add) {
1689                 ServiceInfo info = getServiceInfo(component, userId);
1690                 if (info == null) {
1691                     Slog.w(TAG, "Not binding " + getCaption() + " service " + component
1692                             + ": service not found");
1693                     continue;
1694                 }
1695                 if (!mConfig.bindPermission.equals(info.permission)) {
1696                     Slog.w(TAG, "Not binding " + getCaption() + " service " + component
1697                             + ": it does not require the permission " + mConfig.bindPermission);
1698                     continue;
1699                 }
1700                 // Do not (auto)bind if service has meta-data to explicitly disallow it
1701                 if (!isAutobindAllowed(info) && !isBoundOrRebinding(component, userId)) {
1702                     synchronized (mSnoozing) {
1703                         Slog.d(TAG, "Not binding " + getCaption() + " service " + component
1704                                 + ": has META_DATA_DEFAULT_AUTOBIND = false");
1705                         mSnoozing.add(userId, component);
1706                     }
1707                     continue;
1708                 }
1709 
1710                 Slog.v(TAG,
1711                         "enabling " + getCaption() + " for " + userId + ": " + component);
1712                 registerService(info, userId);
1713             }
1714         }
1715     }
1716 
1717     /**
1718      * Version of registerService that takes the name of a service component to bind to.
1719      */
1720     @VisibleForTesting
registerService(final ServiceInfo si, final int userId)1721     void registerService(final ServiceInfo si, final int userId) {
1722         ensureFilters(si, userId);
1723         registerService(si.getComponentName(), userId);
1724     }
1725 
1726     @VisibleForTesting
registerService(final ComponentName cn, final int userId)1727     void registerService(final ComponentName cn, final int userId) {
1728         synchronized (mMutex) {
1729             registerServiceLocked(cn, userId);
1730         }
1731     }
1732 
1733     @VisibleForTesting
reregisterService(final ComponentName cn, final int userId)1734     void reregisterService(final ComponentName cn, final int userId) {
1735         // If rebinding a package that died, ensure it still has permission
1736         // after the rebind delay
1737         if (isPackageOrComponentAllowedWithPermission(cn, userId)) {
1738             registerService(cn, userId);
1739         } else {
1740             if (DEBUG) Slog.v(TAG, "skipped reregisterService cn=" + cn + " u=" + userId
1741                     + " because of isPackageOrComponentAllowedWithPermission check");
1742         }
1743     }
1744 
1745     /**
1746      * Inject a system service into the management list.
1747      */
registerSystemService(final ComponentName name, final int userid)1748     public void registerSystemService(final ComponentName name, final int userid) {
1749         synchronized (mMutex) {
1750             registerServiceLocked(name, userid, true /* isSystem */);
1751         }
1752     }
1753 
1754     @GuardedBy("mMutex")
registerServiceLocked(final ComponentName name, final int userid)1755     private void registerServiceLocked(final ComponentName name, final int userid) {
1756         registerServiceLocked(name, userid, false /* isSystem */);
1757     }
1758 
1759     @GuardedBy("mMutex")
registerServiceLocked(final ComponentName name, final int userid, final boolean isSystem)1760     private void registerServiceLocked(final ComponentName name, final int userid,
1761             final boolean isSystem) {
1762         if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid);
1763 
1764         final Pair<ComponentName, Integer> servicesBindingTag = Pair.create(name, userid);
1765         if (mServicesBound.contains(servicesBindingTag)) {
1766             Slog.v(TAG, "Not registering " + name + " is already bound");
1767             // stop registering this thing already! we're working on it
1768             return;
1769         }
1770         mServicesBound.add(servicesBindingTag);
1771 
1772         final int N = mServices.size();
1773         for (int i = N - 1; i >= 0; i--) {
1774             final ManagedServiceInfo info = mServices.get(i);
1775             if (name.equals(info.component)
1776                 && info.userid == userid) {
1777                 // cut old connections
1778                 Slog.v(TAG, "    disconnecting old " + getCaption() + ": " + info.service);
1779                 removeServiceLocked(i);
1780                 if (info.connection != null) {
1781                     unbindService(info.connection, info.component, info.userid);
1782                 }
1783             }
1784         }
1785 
1786         Intent intent = new Intent(mConfig.serviceInterface);
1787         intent.setComponent(name);
1788 
1789         intent.putExtra(Intent.EXTRA_CLIENT_LABEL, mConfig.clientLabel);
1790 
1791         final ActivityOptions activityOptions = ActivityOptions.makeBasic();
1792         activityOptions.setPendingIntentCreatorBackgroundActivityStartMode(
1793                 ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED);
1794         final PendingIntent pendingIntent = PendingIntent.getActivity(
1795                 mContext, 0, new Intent(mConfig.settingsAction), PendingIntent.FLAG_IMMUTABLE,
1796                 activityOptions.toBundle());
1797         intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent);
1798 
1799         ApplicationInfo appInfo = null;
1800         try {
1801             appInfo = mContext.getPackageManager().getApplicationInfoAsUser(
1802                 name.getPackageName(), 0, userid);
1803         } catch (NameNotFoundException e) {
1804             // Ignore if the package doesn't exist we won't be able to bind to the service.
1805         }
1806         final int targetSdkVersion =
1807             appInfo != null ? appInfo.targetSdkVersion : Build.VERSION_CODES.BASE;
1808         final int uid = appInfo != null ? appInfo.uid : -1;
1809 
1810         try {
1811             Slog.v(TAG, "binding: " + intent);
1812             ServiceConnection serviceConnection = new ServiceConnection() {
1813                 IInterface mService;
1814 
1815                 @Override
1816                 public void onServiceConnected(ComponentName name, IBinder binder) {
1817                     Slog.v(TAG,  userid + " " + getCaption() + " service connected: " + name);
1818                     boolean added = false;
1819                     ManagedServiceInfo info = null;
1820                     synchronized (mMutex) {
1821                         mServicesRebinding.remove(servicesBindingTag);
1822                         try {
1823                             mService = asInterface(binder);
1824                             info = newServiceInfo(mService, name,
1825                                 userid, isSystem, this, targetSdkVersion, uid);
1826                             binder.linkToDeath(info, 0);
1827                             added = mServices.add(info);
1828                         } catch (RemoteException e) {
1829                             Slog.e(TAG, "Failed to linkToDeath, already dead", e);
1830                         }
1831                     }
1832                     if (added) {
1833                         onServiceAdded(info);
1834                     }
1835                 }
1836 
1837                 @Override
1838                 public void onServiceDisconnected(ComponentName name) {
1839                     Slog.v(TAG, userid + " " + getCaption() + " connection lost: " + name);
1840                 }
1841 
1842                 @Override
1843                 public void onBindingDied(ComponentName name) {
1844                     Slog.w(TAG,  userid + " " + getCaption() + " binding died: " + name);
1845                     synchronized (mMutex) {
1846                         unbindService(this, name, userid);
1847                         if (!mServicesRebinding.contains(servicesBindingTag)) {
1848                             mServicesRebinding.add(servicesBindingTag);
1849                             mHandler.postDelayed(() ->
1850                                     reregisterService(name, userid),
1851                                     ON_BINDING_DIED_REBIND_DELAY_MS);
1852                         } else {
1853                             Slog.v(TAG, getCaption() + " not rebinding in user " + userid
1854                                     + " as a previous rebind attempt was made: " + name);
1855                         }
1856                     }
1857                 }
1858 
1859                 @Override
1860                 public void onNullBinding(ComponentName name) {
1861                     Slog.v(TAG, "onNullBinding() called with: name = [" + name + "]");
1862                     mContext.unbindService(this);
1863                 }
1864             };
1865             if (!mContext.bindServiceAsUser(intent,
1866                     serviceConnection,
1867                     getBindFlags(),
1868                     new UserHandle(userid))) {
1869                 mServicesBound.remove(servicesBindingTag);
1870                 Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent
1871                         + " in user " + userid);
1872                 return;
1873             }
1874         } catch (SecurityException ex) {
1875             mServicesBound.remove(servicesBindingTag);
1876             Slog.e(TAG, "Unable to bind " + getCaption() + " service: " + intent, ex);
1877         }
1878     }
1879 
1880     @VisibleForTesting
isBound(ComponentName cn, int userId)1881     boolean isBound(ComponentName cn, int userId) {
1882         final Pair<ComponentName, Integer> servicesBindingTag = Pair.create(cn, userId);
1883         synchronized (mMutex) {
1884             return mServicesBound.contains(servicesBindingTag);
1885         }
1886     }
1887 
isBoundOrRebinding(final ComponentName cn, final int userId)1888     protected boolean isBoundOrRebinding(final ComponentName cn, final int userId) {
1889         synchronized (mMutex) {
1890             return isBound(cn, userId) || mServicesRebinding.contains(Pair.create(cn, userId));
1891         }
1892     }
1893 
1894     /**
1895      * Remove a service for the given user by ComponentName
1896      */
unregisterService(ComponentName name, int userid)1897     private void unregisterService(ComponentName name, int userid) {
1898         synchronized (mMutex) {
1899             unregisterServiceLocked(name, userid);
1900         }
1901     }
1902 
1903     @GuardedBy("mMutex")
unregisterServiceLocked(ComponentName name, int userid)1904     private void unregisterServiceLocked(ComponentName name, int userid) {
1905         final int N = mServices.size();
1906         for (int i = N - 1; i >= 0; i--) {
1907             final ManagedServiceInfo info = mServices.get(i);
1908             if (name.equals(info.component) && info.userid == userid) {
1909                 removeServiceLocked(i);
1910                 if (info.connection != null) {
1911                     unbindService(info.connection, info.component, info.userid);
1912                 }
1913             }
1914         }
1915     }
1916 
1917     /**
1918      * Removes a service from the list but does not unbind
1919      *
1920      * @return the removed service.
1921      */
removeServiceImpl(IInterface service, final int userid)1922     private ManagedServiceInfo removeServiceImpl(IInterface service, final int userid) {
1923         if (DEBUG) Slog.d(TAG, "removeServiceImpl service=" + service + " u=" + userid);
1924         ManagedServiceInfo serviceInfo = null;
1925         synchronized (mMutex) {
1926             final int N = mServices.size();
1927             for (int i = N - 1; i >= 0; i--) {
1928                 final ManagedServiceInfo info = mServices.get(i);
1929                 if (info.service.asBinder() == service.asBinder() && info.userid == userid) {
1930                     Slog.d(TAG, "Removing active service " + info.component);
1931                     serviceInfo = removeServiceLocked(i);
1932                 }
1933             }
1934         }
1935         return serviceInfo;
1936     }
1937 
1938     @GuardedBy("mMutex")
removeServiceLocked(int i)1939     private ManagedServiceInfo removeServiceLocked(int i) {
1940         final ManagedServiceInfo info = mServices.remove(i);
1941         onServiceRemovedLocked(info);
1942         return info;
1943     }
1944 
checkNotNull(IInterface service)1945     private void checkNotNull(IInterface service) {
1946         if (service == null) {
1947             throw new IllegalArgumentException(getCaption() + " must not be null");
1948         }
1949     }
1950 
registerServiceImpl(final IInterface service, final ComponentName component, final int userid, int targetSdk, int uid)1951     private ManagedServiceInfo registerServiceImpl(final IInterface service,
1952             final ComponentName component, final int userid, int targetSdk, int uid) {
1953         ManagedServiceInfo info = newServiceInfo(service, component, userid,
1954                 true /*isSystem*/, null /*connection*/, targetSdk, uid);
1955         return registerServiceImpl(info);
1956     }
1957 
registerServiceImpl(ManagedServiceInfo info)1958     private ManagedServiceInfo registerServiceImpl(ManagedServiceInfo info) {
1959         synchronized (mMutex) {
1960             try {
1961                 info.service.asBinder().linkToDeath(info, 0);
1962                 mServices.add(info);
1963                 return info;
1964             } catch (RemoteException e) {
1965                 // already dead
1966             }
1967         }
1968         return null;
1969     }
1970 
1971     /**
1972      * Removes a service from the list and unbinds.
1973      */
unregisterServiceImpl(IInterface service, int userid)1974     private void unregisterServiceImpl(IInterface service, int userid) {
1975         ManagedServiceInfo info = removeServiceImpl(service, userid);
1976         if (info != null && info.connection != null && !info.isGuest(this)) {
1977             unbindService(info.connection, info.component, info.userid);
1978         }
1979     }
1980 
unbindService(ServiceConnection connection, ComponentName component, int userId)1981     private void unbindService(ServiceConnection connection, ComponentName component, int userId) {
1982         try {
1983             mContext.unbindService(connection);
1984         } catch (IllegalArgumentException e) {
1985             Slog.e(TAG, getCaption() + " " + component + " could not be unbound", e);
1986         }
1987         synchronized (mMutex) {
1988             mServicesBound.remove(Pair.create(component, userId));
1989         }
1990     }
1991 
getServiceInfo(ComponentName component, int userId)1992     private ServiceInfo getServiceInfo(ComponentName component, int userId) {
1993         try {
1994             return mPm.getServiceInfo(component,
1995                     PackageManager.GET_META_DATA
1996                             | PackageManager.MATCH_DIRECT_BOOT_AWARE
1997                             | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
1998                     userId);
1999         } catch (RemoteException e) {
2000             e.rethrowFromSystemServer();
2001         }
2002         return null;
2003     }
2004 
isAutobindAllowed(ServiceInfo serviceInfo)2005     private boolean isAutobindAllowed(ServiceInfo serviceInfo) {
2006         if (serviceInfo != null && serviceInfo.metaData != null && serviceInfo.metaData.containsKey(
2007                 META_DATA_DEFAULT_AUTOBIND)) {
2008             return serviceInfo.metaData.getBoolean(META_DATA_DEFAULT_AUTOBIND, true);
2009         }
2010         return true;
2011     }
2012 
2013     /**
2014      * This method returns the mapped id for the incoming user id
2015      * If the incoming id was not the id of the visible background user, it returns USER_CURRENT.
2016      * In the other cases, it returns the same value as the input.
2017      *
2018      * @param userId the id of the user
2019      * @return the user id if it is a visible background user, otherwise
2020      * {@link UserHandle#USER_CURRENT}
2021      */
2022     @FlaggedApi(FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER)
2023     @VisibleForTesting
resolveUserId(int userId)2024     public int resolveUserId(int userId) {
2025         if (managedServicesConcurrentMultiuser()) {
2026             if (mUmInternal.isVisibleBackgroundFullUser(userId)) {
2027                 // The dataset of the visible background user should be managed independently.
2028                 return userId;
2029             }
2030         }
2031         // The data of current user and its profile users need to  be managed
2032         // in a dataset as before.
2033         return UserHandle.USER_CURRENT;
2034     }
2035 
2036     /**
2037      * Returns true if services in the parent user should be rebound
2038      *  when rebindServices is called with a profile userId.
2039      * Must be false for NotificationAssistants.
2040      */
allowRebindForParentUser()2041     protected abstract boolean allowRebindForParentUser();
2042 
2043     public class ManagedServiceInfo implements IBinder.DeathRecipient {
2044         public IInterface service;
2045         public ComponentName component;
2046         public int userid;
2047         public boolean isSystem;
2048         @FlaggedApi(FLAG_LIFETIME_EXTENSION_REFACTOR)
2049         public boolean isSystemUi;
2050         public ServiceConnection connection;
2051         public int targetSdkVersion;
2052         public Pair<ComponentName, Integer> mKey;
2053         public int uid;
2054         @FlaggedApi(FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER)
2055         public boolean isVisibleBackgroundUserService;
2056 
ManagedServiceInfo(IInterface service, ComponentName component, int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion, int uid)2057         public ManagedServiceInfo(IInterface service, ComponentName component,
2058                 int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion,
2059                 int uid) {
2060             this.service = service;
2061             this.component = component;
2062             this.userid = userid;
2063             this.isSystem = isSystem;
2064             this.connection = connection;
2065             this.targetSdkVersion = targetSdkVersion;
2066             this.uid = uid;
2067             if (managedServicesConcurrentMultiuser()) {
2068                 this.isVisibleBackgroundUserService = LocalServices
2069                         .getService(UserManagerInternal.class).isVisibleBackgroundFullUser(userid);
2070             }
2071             mKey = Pair.create(component, userid);
2072         }
2073 
isGuest(ManagedServices host)2074         public boolean isGuest(ManagedServices host) {
2075             return ManagedServices.this != host;
2076         }
2077 
getOwner()2078         public ManagedServices getOwner() {
2079             return ManagedServices.this;
2080         }
2081 
getService()2082         public IInterface getService() {
2083             return service;
2084         }
2085 
isSystem()2086         public boolean isSystem() {
2087             return isSystem;
2088         }
2089 
2090         @FlaggedApi(FLAG_LIFETIME_EXTENSION_REFACTOR)
isSystemUi()2091         public boolean isSystemUi() {
2092             return isSystemUi;
2093         }
2094 
2095         @Override
toString()2096         public String toString() {
2097             return new StringBuilder("ManagedServiceInfo[")
2098                     .append("component=").append(component)
2099                     .append(",userid=").append(userid)
2100                     .append(",isSystem=").append(isSystem)
2101                     .append(",targetSdkVersion=").append(targetSdkVersion)
2102                     .append(",connection=").append(connection == null ? null : "<connection>")
2103                     .append(",service=").append(service)
2104                     .append(",serviceAsBinder=").append(service != null ? service.asBinder() : null)
2105                     .append(']').toString();
2106         }
2107 
dumpDebug(ProtoOutputStream proto, long fieldId, ManagedServices host)2108         public void dumpDebug(ProtoOutputStream proto, long fieldId, ManagedServices host) {
2109             final long token = proto.start(fieldId);
2110             component.dumpDebug(proto, ManagedServiceInfoProto.COMPONENT);
2111             proto.write(ManagedServiceInfoProto.USER_ID, userid);
2112             proto.write(ManagedServiceInfoProto.SERVICE, service.getClass().getName());
2113             proto.write(ManagedServiceInfoProto.IS_SYSTEM, isSystem);
2114             proto.write(ManagedServiceInfoProto.IS_GUEST, isGuest(host));
2115             proto.end(token);
2116         }
2117 
isSameUser(int userId)2118         public boolean isSameUser(int userId) {
2119             if (!isEnabledForUser()) {
2120                 return false;
2121             }
2122             return userId == USER_ALL || userId == this.userid;
2123         }
2124 
enabledAndUserMatches(int nid)2125         public boolean enabledAndUserMatches(int nid) {
2126             if (!isEnabledForUser()) {
2127                 return false;
2128             }
2129             if (this.userid == USER_ALL) return true;
2130             if (this.isSystem) return true;
2131             if (nid == USER_ALL || nid == this.userid) return true;
2132             if (managedServicesConcurrentMultiuser()
2133                     && mUmInternal.getProfileParentId(nid)
2134                         != mUmInternal.getProfileParentId(this.userid)) {
2135                 // If the profile parent IDs do not match each other,
2136                 // it is determined that the users do not match.
2137                 // This situation may occur when comparing the current user's ID
2138                 // with the visible background user's ID.
2139                 return false;
2140             }
2141             return supportsProfiles()
2142                     && mUserProfiles.isCurrentProfile(nid)
2143                     && isPermittedForProfile(nid);
2144         }
2145 
supportsProfiles()2146         public boolean supportsProfiles() {
2147             return targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP;
2148         }
2149 
2150         @Override
binderDied()2151         public void binderDied() {
2152             if (DEBUG) Slog.d(TAG, "binderDied " + this);
2153             // Remove the service, but don't unbind from the service. The system will bring the
2154             // service back up, and the onServiceConnected handler will read the service with the
2155             // new binding. If this isn't a bound service, and is just a registered
2156             // service, just removing it from the list is all we need to do anyway.
2157             removeServiceImpl(this.service, this.userid);
2158         }
2159 
2160         /**
2161          * convenience method for looking in mEnabledServicesByUser.
2162          * If FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER is disabled, this manages the data using
2163          * only UserHandle.USER_CURRENT as the key, in order to behave the same as the legacy logic.
2164         */
isEnabledForUser()2165         public boolean isEnabledForUser() {
2166             if (this.isSystem) return true;
2167             if (this.connection == null) return false;
2168             synchronized (mMutex) {
2169                 int resolvedUserId = managedServicesConcurrentMultiuser()
2170                         ? resolveUserId(this.userid)
2171                         : UserHandle.USER_CURRENT;
2172                 ArraySet<ComponentName> enabledServices =
2173                         mEnabledServicesByUser.get(resolvedUserId);
2174                 return enabledServices != null && enabledServices.contains(this.component);
2175             }
2176         }
2177 
2178         /**
2179          * Returns true if this service is allowed to receive events for the given userId. A
2180          * managed profile owner can disallow non-system services running outside of the profile
2181          * from receiving events from the profile.
2182          */
isPermittedForProfile(int userId)2183         public boolean isPermittedForProfile(int userId) {
2184             if (!mUserProfiles.isProfileUser(userId, mContext)) {
2185                 return true;
2186             }
2187             DevicePolicyManager dpm =
2188                     (DevicePolicyManager) mContext.getSystemService(DEVICE_POLICY_SERVICE);
2189             final long identity = Binder.clearCallingIdentity();
2190             try {
2191                 return dpm.isNotificationListenerServicePermitted(
2192                         component.getPackageName(), userId);
2193             } finally {
2194                 Binder.restoreCallingIdentity(identity);
2195             }
2196         }
2197 
2198         @Override
equals(Object o)2199         public boolean equals(Object o) {
2200             if (this == o) return true;
2201             if (o == null || getClass() != o.getClass()) return false;
2202             ManagedServiceInfo that = (ManagedServiceInfo) o;
2203             return userid == that.userid
2204                     && isSystem == that.isSystem
2205                     && targetSdkVersion == that.targetSdkVersion
2206                     && Objects.equals(service, that.service)
2207                     && Objects.equals(component, that.component)
2208                     && Objects.equals(connection, that.connection);
2209         }
2210 
2211         @Override
hashCode()2212         public int hashCode() {
2213             return Objects.hash(service, component, userid, isSystem, connection, targetSdkVersion);
2214         }
2215     }
2216 
2217     /** convenience method for looking in mEnabledServicesByUser for UserHandle.USER_CURRENT.
2218      * This is a legacy API. When FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER becomes
2219      * trunk stable,  this API should be deprecated.  Additionally, when this method
2220      * is deprecated, the unit tests written using this method should also be revised.
2221      *
2222      * @param component target component name
2223      * @return boolean value that indicates whether it is enabled for the current profiles
2224      */
isComponentEnabledForCurrentProfiles(ComponentName component)2225     public boolean isComponentEnabledForCurrentProfiles(ComponentName component) {
2226         return isComponentEnabledForUser(component, UserHandle.USER_CURRENT);
2227     }
2228 
2229     /** convenience method for looking in mEnabledServicesForUser
2230      *
2231      * @param component target component name
2232      * @param userId the id of the target user
2233      * @return boolean value that indicates whether it is enabled for the target user
2234     */
2235     @FlaggedApi(FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER)
isComponentEnabledForUser(ComponentName component, int userId)2236     public boolean isComponentEnabledForUser(ComponentName component, int userId) {
2237         synchronized (mMutex) {
2238             ArraySet<ComponentName> enabledServicesForUser =
2239                     mEnabledServicesByUser.get(resolveUserId(userId));
2240             return enabledServicesForUser != null && enabledServicesForUser.contains(component);
2241         }
2242     }
2243 
2244     public static class UserProfiles {
2245         // Profiles of the current user.
2246         private final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>();
2247 
updateCache(@onNull Context context)2248         public void updateCache(@NonNull Context context) {
2249             UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
2250             if (userManager != null) {
2251                 int currentUserId = ActivityManager.getCurrentUser();
2252                 List<UserInfo> profiles = userManager.getProfiles(currentUserId);
2253                 synchronized (mCurrentProfiles) {
2254                     mCurrentProfiles.clear();
2255                     for (UserInfo user : profiles) {
2256                         mCurrentProfiles.put(user.id, user);
2257                     }
2258                 }
2259             }
2260         }
2261 
2262         /**
2263          * Returns the currently active users (generally one user and its work profile).
2264          */
getCurrentProfileIds()2265         public IntArray getCurrentProfileIds() {
2266             synchronized (mCurrentProfiles) {
2267                 IntArray users = new IntArray(mCurrentProfiles.size());
2268                 final int N = mCurrentProfiles.size();
2269                 for (int i = 0; i < N; ++i) {
2270                     users.add(mCurrentProfiles.keyAt(i));
2271                 }
2272                 return users;
2273             }
2274         }
2275 
isCurrentProfile(int userId)2276         public boolean isCurrentProfile(int userId) {
2277             synchronized (mCurrentProfiles) {
2278                 return mCurrentProfiles.get(userId) != null;
2279             }
2280         }
2281 
isProfileUser(int userId, Context context)2282         public boolean isProfileUser(int userId, Context context) {
2283             synchronized (mCurrentProfiles) {
2284                 UserInfo user = mCurrentProfiles.get(userId);
2285                 if (user == null) {
2286                     return false;
2287                 }
2288                 if (privateSpaceFlagsEnabled()) {
2289                     return user.isProfile() && hasParent(user, context);
2290                 }
2291                 return user.isManagedProfile() || user.isCloneProfile();
2292             }
2293         }
2294 
hasParent(UserInfo profile, Context context)2295         boolean hasParent(UserInfo profile, Context context) {
2296             final long identity = Binder.clearCallingIdentity();
2297             try {
2298                 UserManager um = context.getSystemService(UserManager.class);
2299                 return um.getProfileParent(profile.id) != null;
2300             } finally {
2301                 Binder.restoreCallingIdentity(identity);
2302             }
2303         }
2304     }
2305 
2306     public static class Config {
2307         public String caption;
2308         public String serviceInterface;
2309         public String secureSettingName;
2310         public String secondarySettingName;
2311         public String xmlTag;
2312         public String bindPermission;
2313         public String settingsAction;
2314         public int clientLabel;
2315     }
2316 }
2317