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