OSDN Git Service

Don't autogrant permissions on managed profiles
[android-x86/frameworks-base.git] / services / core / java / com / android / server / notification / ManagedServices.java
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
24 import android.annotation.NonNull;
25 import android.app.ActivityManager;
26 import android.app.PendingIntent;
27 import android.app.admin.DevicePolicyManager;
28 import android.content.ComponentName;
29 import android.content.ContentResolver;
30 import android.content.Context;
31 import android.content.Intent;
32 import android.content.ServiceConnection;
33 import android.content.pm.ApplicationInfo;
34 import android.content.pm.IPackageManager;
35 import android.content.pm.PackageManager;
36 import android.content.pm.PackageManager.NameNotFoundException;
37 import android.content.pm.ResolveInfo;
38 import android.content.pm.ServiceInfo;
39 import android.content.pm.UserInfo;
40 import android.os.Binder;
41 import android.os.Build;
42 import android.os.IBinder;
43 import android.os.IInterface;
44 import android.os.RemoteException;
45 import android.os.UserHandle;
46 import android.os.UserManager;
47 import android.provider.Settings;
48 import android.text.TextUtils;
49 import android.util.ArrayMap;
50 import android.util.ArraySet;
51 import android.util.Log;
52 import android.util.Slog;
53 import android.util.SparseArray;
54
55 import com.android.internal.util.XmlUtils;
56 import com.android.server.notification.NotificationManagerService.DumpFilter;
57
58 import org.xmlpull.v1.XmlPullParser;
59 import org.xmlpull.v1.XmlPullParserException;
60 import org.xmlpull.v1.XmlSerializer;
61
62 import java.io.IOException;
63 import java.io.PrintWriter;
64 import java.util.ArrayList;
65 import java.util.Arrays;
66 import java.util.HashSet;
67 import java.util.List;
68 import java.util.Set;
69 import java.util.stream.Collectors;
70
71 /**
72  * Manages the lifecycle of application-provided services bound by system server.
73  *
74  * Services managed by this helper must have:
75  *  - An associated system settings value with a list of enabled component names.
76  *  - A well-known action for services to use in their intent-filter.
77  *  - A system permission for services to require in order to ensure system has exclusive binding.
78  *  - A settings page for user configuration of enabled services, and associated intent action.
79  *  - A remote interface definition (aidl) provided by the service used for communication.
80  */
81 abstract public class ManagedServices {
82     protected final String TAG = getClass().getSimpleName();
83     protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
84
85     protected static final String ENABLED_SERVICES_SEPARATOR = ":";
86
87     /**
88      * List of components and apps that can have running {@link ManagedServices}.
89      */
90     static final String TAG_MANAGED_SERVICES = "service_listing";
91     static final String ATT_APPROVED_LIST = "approved";
92     static final String ATT_USER_ID = "user";
93     static final String ATT_IS_PRIMARY = "primary";
94
95     static final int APPROVAL_BY_PACKAGE = 0;
96     static final int APPROVAL_BY_COMPONENT = 1;
97
98     protected final Context mContext;
99     protected final Object mMutex;
100     private final UserProfiles mUserProfiles;
101     private final IPackageManager mPm;
102     private final Config mConfig;
103
104     // contains connections to all connected services, including app services
105     // and system services
106     private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<>();
107     // things that will be put into mServices as soon as they're ready
108     private final ArrayList<String> mServicesBinding = new ArrayList<>();
109     // lists the component names of all enabled (and therefore potentially connected)
110     // app services for current profiles.
111     private ArraySet<ComponentName> mEnabledServicesForCurrentProfiles
112             = new ArraySet<>();
113     // Just the packages from mEnabledServicesForCurrentProfiles
114     private ArraySet<String> mEnabledServicesPackageNames = new ArraySet<>();
115     // List of enabled packages that have nevertheless asked not to be run
116     private ArraySet<ComponentName> mSnoozingForCurrentProfiles = new ArraySet<>();
117
118     // List of approved packages or components (by user, then by primary/secondary) that are
119     // allowed to be bound as managed services. A package or component appearing in this list does
120     // not mean that we are currently bound to said package/component.
121     private ArrayMap<Integer, ArrayMap<Boolean, ArraySet<String>>> mApproved = new ArrayMap<>();
122
123     // Kept to de-dupe user change events (experienced after boot, when we receive a settings and a
124     // user change).
125     private int[] mLastSeenProfileIds;
126
127     // True if approved services are stored in xml, not settings.
128     private boolean mUseXml;
129
130     // Whether managed services are approved individually or package wide
131     protected int mApprovalLevel;
132
133     public ManagedServices(Context context, Object mutex, UserProfiles userProfiles,
134             IPackageManager pm) {
135         mContext = context;
136         mMutex = mutex;
137         mUserProfiles = userProfiles;
138         mPm = pm;
139         mConfig = getConfig();
140         mApprovalLevel = APPROVAL_BY_COMPONENT;
141     }
142
143     abstract protected Config getConfig();
144
145     private String getCaption() {
146         return mConfig.caption;
147     }
148
149     abstract protected IInterface asInterface(IBinder binder);
150
151     abstract protected boolean checkType(IInterface service);
152
153     abstract protected void onServiceAdded(ManagedServiceInfo info);
154
155     protected List<ManagedServiceInfo> getServices() {
156         synchronized (mMutex) {
157             List<ManagedServiceInfo> services = new ArrayList<>(mServices);
158             return services;
159         }
160     }
161
162     protected void onServiceRemovedLocked(ManagedServiceInfo removed) { }
163
164     private ManagedServiceInfo newServiceInfo(IInterface service,
165             ComponentName component, int userId, boolean isSystem, ServiceConnection connection,
166             int targetSdkVersion) {
167         return new ManagedServiceInfo(service, component, userId, isSystem, connection,
168                 targetSdkVersion);
169     }
170
171     public void onBootPhaseAppsCanStart() {}
172
173     public void dump(PrintWriter pw, DumpFilter filter) {
174         pw.println("    Allowed " + getCaption() + "s:");
175         final int N = mApproved.size();
176         for (int i = 0 ; i < N; i++) {
177             final int userId = mApproved.keyAt(i);
178             final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
179             if (approvedByType != null) {
180                 final int M = approvedByType.size();
181                 for (int j = 0; j < M; j++) {
182                     final boolean isPrimary = approvedByType.keyAt(j);
183                     final ArraySet<String> approved = approvedByType.valueAt(j);
184                     if (approvedByType != null && approvedByType.size() > 0) {
185                         pw.println("      " + String.join(ENABLED_SERVICES_SEPARATOR, approved)
186                                 + " (user: " + userId + " isPrimary: " + isPrimary + ")");
187                     }
188                 }
189             }
190         }
191
192         pw.println("    All " + getCaption() + "s (" + mEnabledServicesForCurrentProfiles.size()
193                 + ") enabled for current profiles:");
194         for (ComponentName cmpt : mEnabledServicesForCurrentProfiles) {
195             if (filter != null && !filter.matches(cmpt)) continue;
196             pw.println("      " + cmpt);
197         }
198
199         pw.println("    Live " + getCaption() + "s (" + mServices.size() + "):");
200         for (ManagedServiceInfo info : mServices) {
201             if (filter != null && !filter.matches(info.component)) continue;
202             pw.println("      " + info.component
203                     + " (user " + info.userid + "): " + info.service
204                     + (info.isSystem?" SYSTEM":"")
205                     + (info.isGuest(this)?" GUEST":""));
206         }
207
208         pw.println("    Snoozed " + getCaption() + "s (" +
209                 mSnoozingForCurrentProfiles.size() + "):");
210         for (ComponentName name : mSnoozingForCurrentProfiles) {
211             pw.println("      " + name.flattenToShortString());
212         }
213     }
214
215     protected void onSettingRestored(String element, String value, int backupSdkInt, int userId) {
216         if (!mUseXml) {
217             Slog.d(TAG, "Restored managed service setting: " + element);
218             if (mConfig.secureSettingName.equals(element) ||
219                     (mConfig.secondarySettingName != null
220                             && mConfig.secondarySettingName.equals(element))) {
221                 if (backupSdkInt < Build.VERSION_CODES.O) {
222                     // automatic system grants were added in O, so append the approved apps
223                     // rather than wiping out the setting
224                     String currentSetting =
225                             getApproved(userId, mConfig.secureSettingName.equals(element));
226                     if (!TextUtils.isEmpty(currentSetting)) {
227                         if (!TextUtils.isEmpty(value)) {
228                             value = value + ENABLED_SERVICES_SEPARATOR + currentSetting;
229                         } else {
230                             value = currentSetting;
231                         }
232                     }
233                 }
234                 Settings.Secure.putStringForUser(
235                         mContext.getContentResolver(), element, value, userId);
236                 loadAllowedComponentsFromSettings();
237                 rebindServices(false);
238             }
239         }
240     }
241
242     public void writeXml(XmlSerializer out, boolean forBackup) throws IOException {
243         out.startTag(null, getConfig().xmlTag);
244
245         if (forBackup) {
246             trimApprovedListsAccordingToInstalledServices();
247         }
248
249         final int N = mApproved.size();
250         for (int i = 0 ; i < N; i++) {
251             final int userId = mApproved.keyAt(i);
252             final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
253             if (approvedByType != null) {
254                 final int M = approvedByType.size();
255                 for (int j = 0; j < M; j++) {
256                     final boolean isPrimary = approvedByType.keyAt(j);
257                     final Set<String> approved = approvedByType.valueAt(j);
258                     if (approved != null) {
259                         String allowedItems = String.join(ENABLED_SERVICES_SEPARATOR, approved);
260                         out.startTag(null, TAG_MANAGED_SERVICES);
261                         out.attribute(null, ATT_APPROVED_LIST, allowedItems);
262                         out.attribute(null, ATT_USER_ID, Integer.toString(userId));
263                         out.attribute(null, ATT_IS_PRIMARY, Boolean.toString(isPrimary));
264                         out.endTag(null, TAG_MANAGED_SERVICES);
265
266                         if (!forBackup && isPrimary) {
267                             // Also write values to settings, for observers who haven't migrated yet
268                             Settings.Secure.putStringForUser(mContext.getContentResolver(),
269                                     getConfig().secureSettingName, allowedItems, userId);
270                         }
271
272                     }
273                 }
274             }
275         }
276
277         out.endTag(null, getConfig().xmlTag);
278     }
279
280     protected void migrateToXml() {
281         loadAllowedComponentsFromSettings();
282     }
283
284     public void readXml(XmlPullParser parser)
285             throws XmlPullParserException, IOException {
286         int type;
287         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
288             String tag = parser.getName();
289             if (type == XmlPullParser.END_TAG
290                     && getConfig().xmlTag.equals(tag)) {
291                 break;
292             }
293             if (type == XmlPullParser.START_TAG) {
294                 if (TAG_MANAGED_SERVICES.equals(tag)) {
295                     final String approved = XmlUtils.readStringAttribute(parser, ATT_APPROVED_LIST);
296                     final int userId = XmlUtils.readIntAttribute(parser, ATT_USER_ID, 0);
297                     final boolean isPrimary =
298                             XmlUtils.readBooleanAttribute(parser, ATT_IS_PRIMARY, true);
299                     addApprovedList(approved, userId, isPrimary);
300                     mUseXml = true;
301                 }
302             }
303         }
304         rebindServices(false);
305     }
306
307     private void loadAllowedComponentsFromSettings() {
308
309         UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
310         for (UserInfo user : userManager.getUsers()) {
311             final ContentResolver cr = mContext.getContentResolver();
312             addApprovedList(Settings.Secure.getStringForUser(
313                     cr,
314                     getConfig().secureSettingName,
315                     user.id), user.id, true);
316             if (!TextUtils.isEmpty(getConfig().secondarySettingName)) {
317                 addApprovedList(Settings.Secure.getStringForUser(
318                         cr,
319                         getConfig().secondarySettingName,
320                         user.id), user.id, false);
321             }
322         }
323         Slog.d(TAG, "Done loading approved values from settings");
324     }
325
326     private void addApprovedList(String approved, int userId, boolean isPrimary) {
327         if (TextUtils.isEmpty(approved)) {
328             approved = "";
329         }
330         ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
331         if (approvedByType == null) {
332             approvedByType = new ArrayMap<>();
333             mApproved.put(userId, approvedByType);
334         }
335         String[] approvedArray = approved.split(ENABLED_SERVICES_SEPARATOR);
336         final ArraySet<String> approvedList = new ArraySet<>();
337         for (String pkgOrComponent : approvedArray) {
338             String approvedItem = getApprovedValue(pkgOrComponent);
339             if (approvedItem != null) {
340                 approvedList.add(approvedItem);
341             }
342         }
343         approvedByType.put(isPrimary, approvedList);
344     }
345
346     protected boolean isComponentEnabledForPackage(String pkg) {
347         return mEnabledServicesPackageNames.contains(pkg);
348     }
349
350     protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId,
351             boolean isPrimary, boolean enabled) {
352         ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.get(userId);
353         if (allowedByType == null) {
354             allowedByType = new ArrayMap<>();
355             mApproved.put(userId, allowedByType);
356         }
357         ArraySet<String> approved = allowedByType.get(isPrimary);
358         if (approved == null) {
359             approved = new ArraySet<>();
360             allowedByType.put(isPrimary, approved);
361         }
362         String approvedItem = getApprovedValue(pkgOrComponent);
363
364         if (approvedItem != null) {
365             if (enabled) {
366                 approved.add(approvedItem);
367             } else {
368                 approved.remove(approvedItem);
369             }
370         }
371
372         rebindServices(false);
373     }
374
375     private String getApprovedValue(String pkgOrComponent) {
376         if (mApprovalLevel == APPROVAL_BY_COMPONENT) {
377             if(ComponentName.unflattenFromString(pkgOrComponent) != null) {
378                 return pkgOrComponent;
379             }
380             return null;
381         } else {
382             return getPackageName(pkgOrComponent);
383         }
384     }
385
386     protected String getApproved(int userId, boolean primary) {
387         final ArrayMap<Boolean, ArraySet<String>> allowedByType =
388                 mApproved.getOrDefault(userId, new ArrayMap<>());
389         ArraySet<String> approved = allowedByType.getOrDefault(primary, new ArraySet<>());
390         return String.join(ENABLED_SERVICES_SEPARATOR, approved);
391     }
392
393     protected List<ComponentName> getAllowedComponents(int userId) {
394         final List<ComponentName> allowedComponents = new ArrayList<>();
395         final ArrayMap<Boolean, ArraySet<String>> allowedByType =
396                 mApproved.getOrDefault(userId, new ArrayMap<>());
397         for (int i = 0; i < allowedByType.size(); i++) {
398             final ArraySet<String> allowed = allowedByType.valueAt(i);
399             allowedComponents.addAll(allowed.stream().map(ComponentName::unflattenFromString)
400                     .filter(out -> out != null).collect(Collectors.toList()));
401         }
402         return allowedComponents;
403     }
404
405     protected List<String> getAllowedPackages(int userId) {
406         final List<String> allowedPackages = new ArrayList<>();
407         final ArrayMap<Boolean, ArraySet<String>> allowedByType =
408                 mApproved.getOrDefault(userId, new ArrayMap<>());
409         for (int i = 0; i < allowedByType.size(); i++) {
410             final ArraySet<String> allowed = allowedByType.valueAt(i);
411             allowedPackages.addAll(
412                     allowed.stream().map(this::getPackageName).collect(Collectors.toList()));
413         }
414         return allowedPackages;
415     }
416
417     protected boolean isPackageOrComponentAllowed(String pkgOrComponent, int userId) {
418         ArrayMap<Boolean, ArraySet<String>> allowedByType =
419                 mApproved.getOrDefault(userId, new ArrayMap<>());
420         for (int i = 0; i < allowedByType.size(); i++) {
421             ArraySet<String> allowed = allowedByType.valueAt(i);
422             if (allowed.contains(pkgOrComponent)) {
423                 return true;
424             }
425         }
426         return false;
427     }
428
429     public void onPackagesChanged(boolean removingPackage, String[] pkgList, int[] uidList) {
430         if (DEBUG) Slog.d(TAG, "onPackagesChanged removingPackage=" + removingPackage
431                 + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList))
432                 + " mEnabledServicesPackageNames=" + mEnabledServicesPackageNames);
433
434         if (pkgList != null && (pkgList.length > 0)) {
435             boolean anyServicesInvolved = false;
436             // Remove notification settings for uninstalled package
437             if (removingPackage) {
438                 int size = Math.min(pkgList.length, uidList.length);
439                 for (int i = 0; i < size; i++) {
440                     final String pkg = pkgList[i];
441                     final int userId = UserHandle.getUserId(uidList[i]);
442                     anyServicesInvolved = removeUninstalledItemsFromApprovedLists(userId, pkg);
443                 }
444             }
445             for (String pkgName : pkgList) {
446                 if (mEnabledServicesPackageNames.contains(pkgName)) {
447                     anyServicesInvolved = true;
448                 }
449             }
450
451             if (anyServicesInvolved) {
452                 // make sure we're still bound to any of our services who may have just upgraded
453                 rebindServices(false);
454             }
455         }
456     }
457
458     public void onUserRemoved(int user) {
459         mApproved.remove(user);
460         rebindServices(true);
461     }
462
463     public void onUserSwitched(int user) {
464         if (DEBUG) Slog.d(TAG, "onUserSwitched u=" + user);
465         if (Arrays.equals(mLastSeenProfileIds, mUserProfiles.getCurrentProfileIds())) {
466             if (DEBUG) Slog.d(TAG, "Current profile IDs didn't change, skipping rebindServices().");
467             return;
468         }
469         rebindServices(true);
470     }
471
472     public void onUserUnlocked(int user) {
473         if (DEBUG) Slog.d(TAG, "onUserUnlocked u=" + user);
474         rebindServices(false);
475     }
476
477     private ManagedServiceInfo getServiceFromTokenLocked(IInterface service) {
478         if (service == null) {
479             return null;
480         }
481         final IBinder token = service.asBinder();
482         final int N = mServices.size();
483         for (int i = 0; i < N; i++) {
484             final ManagedServiceInfo info = mServices.get(i);
485             if (info.service.asBinder() == token) return info;
486         }
487         return null;
488     }
489
490     protected ManagedServiceInfo checkServiceTokenLocked(IInterface service) {
491         checkNotNull(service);
492         ManagedServiceInfo info = getServiceFromTokenLocked(service);
493         if (info != null) {
494             return info;
495         }
496         throw new SecurityException("Disallowed call from unknown " + getCaption() + ": "
497                 + service);
498     }
499
500     public void unregisterService(IInterface service, int userid) {
501         checkNotNull(service);
502         // no need to check permissions; if your service binder is in the list,
503         // that's proof that you had permission to add it in the first place
504         unregisterServiceImpl(service, userid);
505     }
506
507     public void registerService(IInterface service, ComponentName component, int userid) {
508         checkNotNull(service);
509         ManagedServiceInfo info = registerServiceImpl(service, component, userid);
510         if (info != null) {
511             onServiceAdded(info);
512         }
513     }
514
515     /**
516      * Add a service to our callbacks. The lifecycle of this service is managed externally,
517      * but unlike a system service, it should not be considered privileged.
518      * */
519     protected void registerGuestService(ManagedServiceInfo guest) {
520         checkNotNull(guest.service);
521         if (!checkType(guest.service)) {
522             throw new IllegalArgumentException();
523         }
524         if (registerServiceImpl(guest) != null) {
525             onServiceAdded(guest);
526         }
527     }
528
529     protected void setComponentState(ComponentName component, boolean enabled) {
530         boolean previous = !mSnoozingForCurrentProfiles.contains(component);
531         if (previous == enabled) {
532             return;
533         }
534
535         if (enabled) {
536             mSnoozingForCurrentProfiles.remove(component);
537         } else {
538             mSnoozingForCurrentProfiles.add(component);
539         }
540
541         // State changed
542         if (DEBUG) {
543             Slog.d(TAG, ((enabled) ? "Enabling " : "Disabling ") + "component " +
544                     component.flattenToShortString());
545         }
546
547         synchronized (mMutex) {
548             final int[] userIds = mUserProfiles.getCurrentProfileIds();
549
550             for (int userId : userIds) {
551                 if (enabled) {
552                     registerServiceLocked(component, userId);
553                 } else {
554                     unregisterServiceLocked(component, userId);
555                 }
556             }
557         }
558     }
559
560     private @NonNull ArraySet<ComponentName> loadComponentNamesFromValues(
561             ArraySet<String> approved, int userId) {
562         if (approved == null || approved.size() == 0)
563             return new ArraySet<>();
564         ArraySet<ComponentName> result = new ArraySet<>(approved.size());
565         for (int i = 0; i < approved.size(); i++) {
566             final String packageOrComponent = approved.valueAt(i);
567             if (!TextUtils.isEmpty(packageOrComponent)) {
568                 ComponentName component = ComponentName.unflattenFromString(packageOrComponent);
569                 if (component != null) {
570                     result.add(component);
571                 } else {
572                     result.addAll(queryPackageForServices(packageOrComponent, userId));
573                 }
574             }
575         }
576         return result;
577     }
578
579     protected Set<ComponentName> queryPackageForServices(String packageName, int userId) {
580         return queryPackageForServices(packageName, 0, userId);
581     }
582
583     protected Set<ComponentName> queryPackageForServices(String packageName, int extraFlags,
584             int userId) {
585         Set<ComponentName> installed = new ArraySet<>();
586         final PackageManager pm = mContext.getPackageManager();
587         Intent queryIntent = new Intent(mConfig.serviceInterface);
588         if (!TextUtils.isEmpty(packageName)) {
589             queryIntent.setPackage(packageName);
590         }
591         List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
592                 queryIntent,
593                 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA | extraFlags,
594                 userId);
595         if (DEBUG)
596             Slog.v(TAG, mConfig.serviceInterface + " services: " + installedServices);
597         if (installedServices != null) {
598             for (int i = 0, count = installedServices.size(); i < count; i++) {
599                 ResolveInfo resolveInfo = installedServices.get(i);
600                 ServiceInfo info = resolveInfo.serviceInfo;
601
602                 ComponentName component = new ComponentName(info.packageName, info.name);
603                 if (!mConfig.bindPermission.equals(info.permission)) {
604                     Slog.w(TAG, "Skipping " + getCaption() + " service "
605                         + info.packageName + "/" + info.name
606                         + ": it does not require the permission "
607                         + mConfig.bindPermission);
608                     continue;
609                 }
610                 installed.add(component);
611             }
612         }
613         return installed;
614     }
615
616     private void trimApprovedListsAccordingToInstalledServices() {
617         int N = mApproved.size();
618         for (int i = 0 ; i < N; i++) {
619             final int userId = mApproved.keyAt(i);
620             final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
621             int M = approvedByType.size();
622             for (int j = 0; j < M; j++) {
623                 final ArraySet<String> approved = approvedByType.valueAt(j);
624                 int P = approved.size();
625                 for (int k = P - 1; k >= 0; k--) {
626                     final String approvedPackageOrComponent = approved.valueAt(k);
627                     if (!hasMatchingServices(approvedPackageOrComponent, userId)){
628                         approved.removeAt(k);
629                         if (DEBUG) {
630                             Slog.v(TAG, "Removing " + approvedPackageOrComponent
631                                     + " from approved list; no matching services found");
632                         }
633                     } else {
634                         if (DEBUG) {
635                             Slog.v(TAG, "Keeping " + approvedPackageOrComponent
636                                     + " on approved list; matching services found");
637                         }
638                     }
639                 }
640             }
641         }
642     }
643
644     private boolean removeUninstalledItemsFromApprovedLists(int uninstalledUserId, String pkg) {
645         boolean removed = false;
646         final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(uninstalledUserId);
647         if (approvedByType != null) {
648             int M = approvedByType.size();
649             for (int j = 0; j < M; j++) {
650                 final ArraySet<String> approved = approvedByType.valueAt(j);
651                 int O = approved.size();
652                 for (int k = O - 1; k >= 0; k--) {
653                     final String packageOrComponent = approved.valueAt(k);
654                     final String packageName = getPackageName(packageOrComponent);
655                     if (TextUtils.equals(pkg, packageName)) {
656                         approved.removeAt(k);
657                         if (DEBUG) {
658                             Slog.v(TAG, "Removing " + packageOrComponent
659                                     + " from approved list; uninstalled");
660                         }
661                     }
662                 }
663             }
664         }
665         return removed;
666     }
667
668     protected String getPackageName(String packageOrComponent) {
669         final ComponentName component = ComponentName.unflattenFromString(packageOrComponent);
670         if (component != null) {
671             return component.getPackageName();
672         } else {
673             return packageOrComponent;
674         }
675     }
676
677     private boolean hasMatchingServices(String packageOrComponent, int userId) {
678         if (!TextUtils.isEmpty(packageOrComponent)) {
679             final String packageName = getPackageName(packageOrComponent);
680             return queryPackageForServices(packageName, userId).size() > 0;
681         }
682         return false;
683     }
684
685     /**
686      * Called whenever packages change, the user switches, or the secure setting
687      * is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
688      */
689     private void rebindServices(boolean forceRebind) {
690         if (DEBUG) Slog.d(TAG, "rebindServices");
691         final int[] userIds = mUserProfiles.getCurrentProfileIds();
692         final int nUserIds = userIds.length;
693
694         final SparseArray<ArraySet<ComponentName>> componentsByUser = new SparseArray<>();
695
696         for (int i = 0; i < nUserIds; ++i) {
697             final int userId = userIds[i];
698             final ArrayMap<Boolean, ArraySet<String>> approvedLists = mApproved.get(userIds[i]);
699             if (approvedLists != null) {
700                 final int N = approvedLists.size();
701                 for (int j = 0; j < N; j++) {
702                     ArraySet<ComponentName> approvedByUser = componentsByUser.get(userId);
703                     if (approvedByUser == null) {
704                         approvedByUser = new ArraySet<>();
705                         componentsByUser.put(userId, approvedByUser);
706                     }
707                     approvedByUser.addAll(
708                             loadComponentNamesFromValues(approvedLists.valueAt(j), userId));
709                 }
710             }
711         }
712
713         final ArrayList<ManagedServiceInfo> removableBoundServices = new ArrayList<>();
714         final SparseArray<Set<ComponentName>> toAdd = new SparseArray<>();
715
716         synchronized (mMutex) {
717             // Rebind to non-system services if user switched
718             for (ManagedServiceInfo service : mServices) {
719                 if (!service.isSystem && !service.isGuest(this)) {
720                     removableBoundServices.add(service);
721                 }
722             }
723
724             mEnabledServicesForCurrentProfiles.clear();
725             mEnabledServicesPackageNames.clear();
726
727             for (int i = 0; i < nUserIds; ++i) {
728                 // decode the list of components
729                 final ArraySet<ComponentName> userComponents = componentsByUser.get(userIds[i]);
730                 if (null == userComponents) {
731                     toAdd.put(userIds[i], new ArraySet<>());
732                     continue;
733                 }
734
735                 final Set<ComponentName> add = new HashSet<>(userComponents);
736                 add.removeAll(mSnoozingForCurrentProfiles);
737
738                 toAdd.put(userIds[i], add);
739
740                 mEnabledServicesForCurrentProfiles.addAll(userComponents);
741
742                 for (int j = 0; j < userComponents.size(); j++) {
743                     final ComponentName component = userComponents.valueAt(j);
744                     mEnabledServicesPackageNames.add(component.getPackageName());
745                 }
746             }
747         }
748
749         for (ManagedServiceInfo info : removableBoundServices) {
750             final ComponentName component = info.component;
751             final int oldUser = info.userid;
752             final Set<ComponentName> allowedComponents = toAdd.get(info.userid);
753             if (allowedComponents != null) {
754                 if (allowedComponents.contains(component) && !forceRebind) {
755                     // Already bound, don't need to bind again.
756                     allowedComponents.remove(component);
757                 } else {
758                     // No longer allowed to be bound, or must rebind.
759                     Slog.v(TAG, "disabling " + getCaption() + " for user "
760                             + oldUser + ": " + component);
761                     unregisterService(component, oldUser);
762                 }
763             }
764         }
765
766         for (int i = 0; i < nUserIds; ++i) {
767             final Set<ComponentName> add = toAdd.get(userIds[i]);
768             for (ComponentName component : add) {
769                 try {
770                     ServiceInfo info = mPm.getServiceInfo(component,
771                             PackageManager.MATCH_DIRECT_BOOT_AWARE
772                                     | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userIds[i]);
773                     if (info == null || !mConfig.bindPermission.equals(info.permission)) {
774                         Slog.w(TAG, "Not binding " + getCaption() + " service " + component
775                                 + ": it does not require the permission " + mConfig.bindPermission);
776                         continue;
777                     }
778                     Slog.v(TAG,
779                             "enabling " + getCaption() + " for " + userIds[i] + ": " + component);
780                     registerService(component, userIds[i]);
781                 } catch (RemoteException e) {
782                     e.rethrowFromSystemServer();
783                 }
784             }
785         }
786
787         mLastSeenProfileIds = userIds;
788     }
789
790     /**
791      * Version of registerService that takes the name of a service component to bind to.
792      */
793     private void registerService(final ComponentName name, final int userid) {
794         synchronized (mMutex) {
795             registerServiceLocked(name, userid);
796         }
797     }
798
799     /**
800      * Inject a system service into the management list.
801      */
802     public void registerSystemService(final ComponentName name, final int userid) {
803         synchronized (mMutex) {
804             registerServiceLocked(name, userid, true /* isSystem */);
805         }
806     }
807
808     private void registerServiceLocked(final ComponentName name, final int userid) {
809         registerServiceLocked(name, userid, false /* isSystem */);
810     }
811
812     private void registerServiceLocked(final ComponentName name, final int userid,
813             final boolean isSystem) {
814         if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid);
815
816         final String servicesBindingTag = name.toString() + "/" + userid;
817         if (mServicesBinding.contains(servicesBindingTag)) {
818             // stop registering this thing already! we're working on it
819             return;
820         }
821         mServicesBinding.add(servicesBindingTag);
822
823         final int N = mServices.size();
824         for (int i = N - 1; i >= 0; i--) {
825             final ManagedServiceInfo info = mServices.get(i);
826             if (name.equals(info.component)
827                 && info.userid == userid) {
828                 // cut old connections
829                 if (DEBUG) Slog.v(TAG, "    disconnecting old " + getCaption() + ": "
830                     + info.service);
831                 removeServiceLocked(i);
832                 if (info.connection != null) {
833                     mContext.unbindService(info.connection);
834                 }
835             }
836         }
837
838         Intent intent = new Intent(mConfig.serviceInterface);
839         intent.setComponent(name);
840
841         intent.putExtra(Intent.EXTRA_CLIENT_LABEL, mConfig.clientLabel);
842
843         final PendingIntent pendingIntent = PendingIntent.getActivity(
844             mContext, 0, new Intent(mConfig.settingsAction), 0);
845         intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent);
846
847         ApplicationInfo appInfo = null;
848         try {
849             appInfo = mContext.getPackageManager().getApplicationInfo(
850                 name.getPackageName(), 0);
851         } catch (NameNotFoundException e) {
852             // Ignore if the package doesn't exist we won't be able to bind to the service.
853         }
854         final int targetSdkVersion =
855             appInfo != null ? appInfo.targetSdkVersion : Build.VERSION_CODES.BASE;
856
857         try {
858             if (DEBUG) Slog.v(TAG, "binding: " + intent);
859             ServiceConnection serviceConnection = new ServiceConnection() {
860                 IInterface mService;
861
862                 @Override
863                 public void onServiceConnected(ComponentName name, IBinder binder) {
864                     boolean added = false;
865                     ManagedServiceInfo info = null;
866                     synchronized (mMutex) {
867                         mServicesBinding.remove(servicesBindingTag);
868                         try {
869                             mService = asInterface(binder);
870                             info = newServiceInfo(mService, name,
871                                 userid, isSystem, this, targetSdkVersion);
872                             binder.linkToDeath(info, 0);
873                             added = mServices.add(info);
874                         } catch (RemoteException e) {
875                             // already dead
876                         }
877                     }
878                     if (added) {
879                         onServiceAdded(info);
880                     }
881                 }
882
883                 @Override
884                 public void onServiceDisconnected(ComponentName name) {
885                     mServicesBinding.remove(servicesBindingTag);
886                     Slog.v(TAG, getCaption() + " connection lost: " + name);
887                 }
888             };
889             if (!mContext.bindServiceAsUser(intent,
890                 serviceConnection,
891                 BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT,
892                 new UserHandle(userid))) {
893                 mServicesBinding.remove(servicesBindingTag);
894                 Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent);
895                 return;
896             }
897         } catch (SecurityException ex) {
898             mServicesBinding.remove(servicesBindingTag);
899             Slog.e(TAG, "Unable to bind " + getCaption() + " service: " + intent, ex);
900         }
901     }
902
903     /**
904      * Remove a service for the given user by ComponentName
905      */
906     private void unregisterService(ComponentName name, int userid) {
907         synchronized (mMutex) {
908             unregisterServiceLocked(name, userid);
909         }
910     }
911
912     private void unregisterServiceLocked(ComponentName name, int userid) {
913         final int N = mServices.size();
914         for (int i = N - 1; i >= 0; i--) {
915             final ManagedServiceInfo info = mServices.get(i);
916             if (name.equals(info.component)
917                 && info.userid == userid) {
918                 removeServiceLocked(i);
919                 if (info.connection != null) {
920                     try {
921                         mContext.unbindService(info.connection);
922                     } catch (IllegalArgumentException ex) {
923                         // something happened to the service: we think we have a connection
924                         // but it's bogus.
925                         Slog.e(TAG, getCaption() + " " + name + " could not be unbound: " + ex);
926                     }
927                 }
928             }
929         }
930     }
931
932     /**
933      * Removes a service from the list but does not unbind
934      *
935      * @return the removed service.
936      */
937     private ManagedServiceInfo removeServiceImpl(IInterface service, final int userid) {
938         if (DEBUG) Slog.d(TAG, "removeServiceImpl service=" + service + " u=" + userid);
939         ManagedServiceInfo serviceInfo = null;
940         synchronized (mMutex) {
941             final int N = mServices.size();
942             for (int i = N - 1; i >= 0; i--) {
943                 final ManagedServiceInfo info = mServices.get(i);
944                 if (info.service.asBinder() == service.asBinder()
945                         && info.userid == userid) {
946                     if (DEBUG) Slog.d(TAG, "Removing active service " + info.component);
947                     serviceInfo = removeServiceLocked(i);
948                 }
949             }
950         }
951         return serviceInfo;
952     }
953
954     private ManagedServiceInfo removeServiceLocked(int i) {
955         final ManagedServiceInfo info = mServices.remove(i);
956         onServiceRemovedLocked(info);
957         return info;
958     }
959
960     private void checkNotNull(IInterface service) {
961         if (service == null) {
962             throw new IllegalArgumentException(getCaption() + " must not be null");
963         }
964     }
965
966     private ManagedServiceInfo registerServiceImpl(final IInterface service,
967             final ComponentName component, final int userid) {
968         ManagedServiceInfo info = newServiceInfo(service, component, userid,
969                 true /*isSystem*/, null /*connection*/, Build.VERSION_CODES.LOLLIPOP);
970         return registerServiceImpl(info);
971     }
972
973     private ManagedServiceInfo registerServiceImpl(ManagedServiceInfo info) {
974         synchronized (mMutex) {
975             try {
976                 info.service.asBinder().linkToDeath(info, 0);
977                 mServices.add(info);
978                 return info;
979             } catch (RemoteException e) {
980                 // already dead
981             }
982         }
983         return null;
984     }
985
986     /**
987      * Removes a service from the list and unbinds.
988      */
989     private void unregisterServiceImpl(IInterface service, int userid) {
990         ManagedServiceInfo info = removeServiceImpl(service, userid);
991         if (info != null && info.connection != null && !info.isGuest(this)) {
992             mContext.unbindService(info.connection);
993         }
994     }
995
996     public class ManagedServiceInfo implements IBinder.DeathRecipient {
997         public IInterface service;
998         public ComponentName component;
999         public int userid;
1000         public boolean isSystem;
1001         public ServiceConnection connection;
1002         public int targetSdkVersion;
1003
1004         public ManagedServiceInfo(IInterface service, ComponentName component,
1005                 int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion) {
1006             this.service = service;
1007             this.component = component;
1008             this.userid = userid;
1009             this.isSystem = isSystem;
1010             this.connection = connection;
1011             this.targetSdkVersion = targetSdkVersion;
1012         }
1013
1014         public boolean isGuest(ManagedServices host) {
1015             return ManagedServices.this != host;
1016         }
1017
1018         public ManagedServices getOwner() {
1019             return ManagedServices.this;
1020         }
1021
1022         @Override
1023         public String toString() {
1024             return new StringBuilder("ManagedServiceInfo[")
1025                     .append("component=").append(component)
1026                     .append(",userid=").append(userid)
1027                     .append(",isSystem=").append(isSystem)
1028                     .append(",targetSdkVersion=").append(targetSdkVersion)
1029                     .append(",connection=").append(connection == null ? null : "<connection>")
1030                     .append(",service=").append(service)
1031                     .append(']').toString();
1032         }
1033
1034         public boolean enabledAndUserMatches(int nid) {
1035             if (!isEnabledForCurrentProfiles()) {
1036                 return false;
1037             }
1038             if (this.userid == UserHandle.USER_ALL) return true;
1039             if (this.isSystem) return true;
1040             if (nid == UserHandle.USER_ALL || nid == this.userid) return true;
1041             return supportsProfiles()
1042                     && mUserProfiles.isCurrentProfile(nid)
1043                     && isPermittedForProfile(nid);
1044         }
1045
1046         public boolean supportsProfiles() {
1047             return targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP;
1048         }
1049
1050         @Override
1051         public void binderDied() {
1052             if (DEBUG) Slog.d(TAG, "binderDied");
1053             // Remove the service, but don't unbind from the service. The system will bring the
1054             // service back up, and the onServiceConnected handler will read the service with the
1055             // new binding. If this isn't a bound service, and is just a registered
1056             // service, just removing it from the list is all we need to do anyway.
1057             removeServiceImpl(this.service, this.userid);
1058         }
1059
1060         /** convenience method for looking in mEnabledServicesForCurrentProfiles */
1061         public boolean isEnabledForCurrentProfiles() {
1062             if (this.isSystem) return true;
1063             if (this.connection == null) return false;
1064             return mEnabledServicesForCurrentProfiles.contains(this.component);
1065         }
1066
1067         /**
1068          * Returns true if this service is allowed to receive events for the given userId. A
1069          * managed profile owner can disallow non-system services running outside of the profile
1070          * from receiving events from the profile.
1071          */
1072         public boolean isPermittedForProfile(int userId) {
1073             if (!mUserProfiles.isManagedProfile(userId)) {
1074                 return true;
1075             }
1076             DevicePolicyManager dpm =
1077                     (DevicePolicyManager) mContext.getSystemService(DEVICE_POLICY_SERVICE);
1078             final long identity = Binder.clearCallingIdentity();
1079             try {
1080                 return dpm.isNotificationListenerServicePermitted(
1081                         component.getPackageName(), userId);
1082             } finally {
1083                 Binder.restoreCallingIdentity(identity);
1084             }
1085         }
1086     }
1087
1088     /** convenience method for looking in mEnabledServicesForCurrentProfiles */
1089     public boolean isComponentEnabledForCurrentProfiles(ComponentName component) {
1090         return mEnabledServicesForCurrentProfiles.contains(component);
1091     }
1092
1093     public static class UserProfiles {
1094         // Profiles of the current user.
1095         private final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>();
1096
1097         public void updateCache(@NonNull Context context) {
1098             UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
1099             if (userManager != null) {
1100                 int currentUserId = ActivityManager.getCurrentUser();
1101                 List<UserInfo> profiles = userManager.getProfiles(currentUserId);
1102                 synchronized (mCurrentProfiles) {
1103                     mCurrentProfiles.clear();
1104                     for (UserInfo user : profiles) {
1105                         mCurrentProfiles.put(user.id, user);
1106                     }
1107                 }
1108             }
1109         }
1110
1111         public int[] getCurrentProfileIds() {
1112             synchronized (mCurrentProfiles) {
1113                 int[] users = new int[mCurrentProfiles.size()];
1114                 final int N = mCurrentProfiles.size();
1115                 for (int i = 0; i < N; ++i) {
1116                     users[i] = mCurrentProfiles.keyAt(i);
1117                 }
1118                 return users;
1119             }
1120         }
1121
1122         public boolean isCurrentProfile(int userId) {
1123             synchronized (mCurrentProfiles) {
1124                 return mCurrentProfiles.get(userId) != null;
1125             }
1126         }
1127
1128         public boolean isManagedProfile(int userId) {
1129             synchronized (mCurrentProfiles) {
1130                 UserInfo user = mCurrentProfiles.get(userId);
1131                 return user != null && user.isManagedProfile();
1132             }
1133         }
1134     }
1135
1136     public static class Config {
1137         public String caption;
1138         public String serviceInterface;
1139         public String secureSettingName;
1140         public String secondarySettingName;
1141         public String xmlTag;
1142         public String bindPermission;
1143         public String settingsAction;
1144         public int clientLabel;
1145     }
1146 }