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