1 /**
2  * Copyright (c) 2014, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.notification;
18 
19 import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT;
20 import static android.content.Context.BIND_AUTO_CREATE;
21 import static android.content.Context.BIND_FOREGROUND_SERVICE;
22 import static android.content.Context.DEVICE_POLICY_SERVICE;
23 import static android.os.UserHandle.USER_ALL;
24 
25 import android.annotation.NonNull;
26 import android.app.ActivityManager;
27 import android.app.PendingIntent;
28 import android.app.admin.DevicePolicyManager;
29 import android.content.ComponentName;
30 import android.content.ContentResolver;
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.ServiceConnection;
34 import android.content.pm.ApplicationInfo;
35 import android.content.pm.IPackageManager;
36 import android.content.pm.PackageManager;
37 import android.content.pm.PackageManager.NameNotFoundException;
38 import android.content.pm.ResolveInfo;
39 import android.content.pm.ServiceInfo;
40 import android.content.pm.UserInfo;
41 import android.os.Binder;
42 import android.os.Build;
43 import android.os.Handler;
44 import android.os.IBinder;
45 import android.os.IInterface;
46 import android.os.Looper;
47 import android.os.RemoteException;
48 import android.os.UserHandle;
49 import android.os.UserManager;
50 import android.provider.Settings;
51 import android.service.notification.ManagedServiceInfoProto;
52 import android.service.notification.ManagedServicesProto;
53 import android.service.notification.ManagedServicesProto.ServiceProto;
54 import android.text.TextUtils;
55 import android.util.ArrayMap;
56 import android.util.ArraySet;
57 import android.util.IntArray;
58 import android.util.Log;
59 import android.util.Pair;
60 import android.util.Slog;
61 import android.util.SparseArray;
62 import android.util.proto.ProtoOutputStream;
63 
64 import com.android.internal.annotations.GuardedBy;
65 import com.android.internal.annotations.VisibleForTesting;
66 import com.android.internal.util.XmlUtils;
67 import com.android.internal.util.function.TriPredicate;
68 import com.android.server.notification.NotificationManagerService.DumpFilter;
69 
70 import org.xmlpull.v1.XmlPullParser;
71 import org.xmlpull.v1.XmlPullParserException;
72 import org.xmlpull.v1.XmlSerializer;
73 
74 import java.io.IOException;
75 import java.io.PrintWriter;
76 import java.util.ArrayList;
77 import java.util.Arrays;
78 import java.util.HashSet;
79 import java.util.List;
80 import java.util.Objects;
81 import java.util.Set;
82 
83 /**
84  * Manages the lifecycle of application-provided services bound by system server.
85  *
86  * Services managed by this helper must have:
87  *  - An associated system settings value with a list of enabled component names.
88  *  - A well-known action for services to use in their intent-filter.
89  *  - A system permission for services to require in order to ensure system has exclusive binding.
90  *  - A settings page for user configuration of enabled services, and associated intent action.
91  *  - A remote interface definition (aidl) provided by the service used for communication.
92  */
93 abstract public class ManagedServices {
94     protected final String TAG = getClass().getSimpleName();
95     protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
96 
97     private static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000;
98     protected static final String ENABLED_SERVICES_SEPARATOR = ":";
99 
100     /**
101      * List of components and apps that can have running {@link ManagedServices}.
102      */
103     static final String TAG_MANAGED_SERVICES = "service_listing";
104     static final String ATT_APPROVED_LIST = "approved";
105     static final String ATT_USER_ID = "user";
106     static final String ATT_IS_PRIMARY = "primary";
107     static final String ATT_VERSION = "version";
108 
109     static final int DB_VERSION = 1;
110 
111     static final int APPROVAL_BY_PACKAGE = 0;
112     static final int APPROVAL_BY_COMPONENT = 1;
113 
114     protected final Context mContext;
115     protected final Object mMutex;
116     private final UserProfiles mUserProfiles;
117     private final IPackageManager mPm;
118     protected final UserManager mUm;
119     private final Config mConfig;
120     private final Handler mHandler = new Handler(Looper.getMainLooper());
121 
122     // contains connections to all connected services, including app services
123     // and system services
124     private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<>();
125     /**
126      * The services that have been bound by us. If the service is also connected, it will also
127      * be in {@link #mServices}.
128      */
129     private final ArrayList<Pair<ComponentName, Integer>> mServicesBound = new ArrayList<>();
130     private final ArraySet<Pair<ComponentName, Integer>> mServicesRebinding = new ArraySet<>();
131 
132     // lists the component names of all enabled (and therefore potentially connected)
133     // app services for current profiles.
134     private ArraySet<ComponentName> mEnabledServicesForCurrentProfiles
135             = new ArraySet<>();
136     // Just the packages from mEnabledServicesForCurrentProfiles
137     private ArraySet<String> mEnabledServicesPackageNames = new ArraySet<>();
138     // List of enabled packages that have nevertheless asked not to be run
139     private ArraySet<ComponentName> mSnoozingForCurrentProfiles = new ArraySet<>();
140 
141     // List of approved packages or components (by user, then by primary/secondary) that are
142     // allowed to be bound as managed services. A package or component appearing in this list does
143     // not mean that we are currently bound to said package/component.
144     private ArrayMap<Integer, ArrayMap<Boolean, ArraySet<String>>> mApproved = new ArrayMap<>();
145 
146     // True if approved services are stored in xml, not settings.
147     private boolean mUseXml;
148 
149     // Whether managed services are approved individually or package wide
150     protected int mApprovalLevel;
151 
ManagedServices(Context context, Object mutex, UserProfiles userProfiles, IPackageManager pm)152     public ManagedServices(Context context, Object mutex, UserProfiles userProfiles,
153             IPackageManager pm) {
154         mContext = context;
155         mMutex = mutex;
156         mUserProfiles = userProfiles;
157         mPm = pm;
158         mConfig = getConfig();
159         mApprovalLevel = APPROVAL_BY_COMPONENT;
160         mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
161     }
162 
getConfig()163     abstract protected Config getConfig();
164 
getCaption()165     private String getCaption() {
166         return mConfig.caption;
167     }
168 
asInterface(IBinder binder)169     abstract protected IInterface asInterface(IBinder binder);
170 
checkType(IInterface service)171     abstract protected boolean checkType(IInterface service);
172 
onServiceAdded(ManagedServiceInfo info)173     abstract protected void onServiceAdded(ManagedServiceInfo info);
174 
getServices()175     protected List<ManagedServiceInfo> getServices() {
176         synchronized (mMutex) {
177             List<ManagedServiceInfo> services = new ArrayList<>(mServices);
178             return services;
179         }
180     }
181 
getBindFlags()182     protected int getBindFlags() {
183         return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT;
184     }
185 
onServiceRemovedLocked(ManagedServiceInfo removed)186     protected void onServiceRemovedLocked(ManagedServiceInfo removed) { }
187 
newServiceInfo(IInterface service, ComponentName component, int userId, boolean isSystem, ServiceConnection connection, int targetSdkVersion)188     private ManagedServiceInfo newServiceInfo(IInterface service,
189             ComponentName component, int userId, boolean isSystem, ServiceConnection connection,
190             int targetSdkVersion) {
191         return new ManagedServiceInfo(service, component, userId, isSystem, connection,
192                 targetSdkVersion);
193     }
194 
onBootPhaseAppsCanStart()195     public void onBootPhaseAppsCanStart() {}
196 
dump(PrintWriter pw, DumpFilter filter)197     public void dump(PrintWriter pw, DumpFilter filter) {
198         pw.println("    Allowed " + getCaption() + "s:");
199         synchronized (mApproved) {
200             final int N = mApproved.size();
201             for (int i = 0; i < N; i++) {
202                 final int userId = mApproved.keyAt(i);
203                 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
204                 if (approvedByType != null) {
205                     final int M = approvedByType.size();
206                     for (int j = 0; j < M; j++) {
207                         final boolean isPrimary = approvedByType.keyAt(j);
208                         final ArraySet<String> approved = approvedByType.valueAt(j);
209                         if (approvedByType != null && approvedByType.size() > 0) {
210                             pw.println("      " + String.join(ENABLED_SERVICES_SEPARATOR, approved)
211                                     + " (user: " + userId + " isPrimary: " + isPrimary + ")");
212                         }
213                     }
214                 }
215             }
216         }
217 
218         pw.println("    All " + getCaption() + "s (" + mEnabledServicesForCurrentProfiles.size()
219                 + ") enabled for current profiles:");
220         for (ComponentName cmpt : mEnabledServicesForCurrentProfiles) {
221             if (filter != null && !filter.matches(cmpt)) continue;
222             pw.println("      " + cmpt);
223         }
224 
225         pw.println("    Live " + getCaption() + "s (" + mServices.size() + "):");
226         synchronized (mMutex) {
227             for (ManagedServiceInfo info : mServices) {
228                 if (filter != null && !filter.matches(info.component)) continue;
229                 pw.println("      " + info.component
230                         + " (user " + info.userid + "): " + info.service
231                         + (info.isSystem ? " SYSTEM" : "")
232                         + (info.isGuest(this) ? " GUEST" : ""));
233             }
234         }
235 
236         pw.println("    Snoozed " + getCaption() + "s (" +
237                 mSnoozingForCurrentProfiles.size() + "):");
238         for (ComponentName name : mSnoozingForCurrentProfiles) {
239             pw.println("      " + name.flattenToShortString());
240         }
241     }
242 
dump(ProtoOutputStream proto, DumpFilter filter)243     public void dump(ProtoOutputStream proto, DumpFilter filter) {
244         proto.write(ManagedServicesProto.CAPTION, getCaption());
245         synchronized (mApproved) {
246             final int N = mApproved.size();
247             for (int i = 0; i < N; i++) {
248                 final int userId = mApproved.keyAt(i);
249                 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
250                 if (approvedByType != null) {
251                     final int M = approvedByType.size();
252                     for (int j = 0; j < M; j++) {
253                         final boolean isPrimary = approvedByType.keyAt(j);
254                         final ArraySet<String> approved = approvedByType.valueAt(j);
255                         if (approvedByType != null && approvedByType.size() > 0) {
256                             final long sToken = proto.start(ManagedServicesProto.APPROVED);
257                             for (String s : approved) {
258                                 proto.write(ServiceProto.NAME, s);
259                             }
260                             proto.write(ServiceProto.USER_ID, userId);
261                             proto.write(ServiceProto.IS_PRIMARY, isPrimary);
262                             proto.end(sToken);
263                         }
264                     }
265                 }
266             }
267         }
268 
269         for (ComponentName cmpt : mEnabledServicesForCurrentProfiles) {
270             if (filter != null && !filter.matches(cmpt)) continue;
271             cmpt.writeToProto(proto, ManagedServicesProto.ENABLED);
272         }
273 
274         synchronized (mMutex) {
275             for (ManagedServiceInfo info : mServices) {
276                 if (filter != null && !filter.matches(info.component)) continue;
277                 info.writeToProto(proto, ManagedServicesProto.LIVE_SERVICES, this);
278             }
279         }
280 
281         for (ComponentName name : mSnoozingForCurrentProfiles) {
282             name.writeToProto(proto, ManagedServicesProto.SNOOZED);
283         }
284     }
285 
onSettingRestored(String element, String value, int backupSdkInt, int userId)286     protected void onSettingRestored(String element, String value, int backupSdkInt, int userId) {
287         if (!mUseXml) {
288             Slog.d(TAG, "Restored managed service setting: " + element);
289             if (mConfig.secureSettingName.equals(element) ||
290                     (mConfig.secondarySettingName != null
291                             && mConfig.secondarySettingName.equals(element))) {
292                 if (backupSdkInt < Build.VERSION_CODES.O) {
293                     // automatic system grants were added in O, so append the approved apps
294                     // rather than wiping out the setting
295                     String currentSetting =
296                             getApproved(userId, mConfig.secureSettingName.equals(element));
297                     if (!TextUtils.isEmpty(currentSetting)) {
298                         if (!TextUtils.isEmpty(value)) {
299                             value = value + ENABLED_SERVICES_SEPARATOR + currentSetting;
300                         } else {
301                             value = currentSetting;
302                         }
303                     }
304                 }
305                 Settings.Secure.putStringForUser(
306                         mContext.getContentResolver(), element, value, userId);
307                 loadAllowedComponentsFromSettings();
308                 rebindServices(false, userId);
309             }
310         }
311     }
312 
writeXml(XmlSerializer out, boolean forBackup, int userId)313     public void writeXml(XmlSerializer out, boolean forBackup, int userId) throws IOException {
314         out.startTag(null, getConfig().xmlTag);
315 
316         out.attribute(null, ATT_VERSION, String.valueOf(DB_VERSION));
317 
318         if (forBackup) {
319             trimApprovedListsAccordingToInstalledServices(userId);
320         }
321 
322         synchronized (mApproved) {
323             final int N = mApproved.size();
324             for (int i = 0; i < N; i++) {
325                 final int approvedUserId = mApproved.keyAt(i);
326                 if (forBackup && approvedUserId != userId) {
327                     continue;
328                 }
329                 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
330                 if (approvedByType != null) {
331                     final int M = approvedByType.size();
332                     for (int j = 0; j < M; j++) {
333                         final boolean isPrimary = approvedByType.keyAt(j);
334                         final Set<String> approved = approvedByType.valueAt(j);
335                         if (approved != null) {
336                             String allowedItems = String.join(ENABLED_SERVICES_SEPARATOR, approved);
337                             out.startTag(null, TAG_MANAGED_SERVICES);
338                             out.attribute(null, ATT_APPROVED_LIST, allowedItems);
339                             out.attribute(null, ATT_USER_ID, Integer.toString(approvedUserId));
340                             out.attribute(null, ATT_IS_PRIMARY, Boolean.toString(isPrimary));
341                             writeExtraAttributes(out, approvedUserId);
342                             out.endTag(null, TAG_MANAGED_SERVICES);
343 
344                             if (!forBackup && isPrimary) {
345                                 // Also write values to settings, for observers who haven't migrated yet
346                                 Settings.Secure.putStringForUser(mContext.getContentResolver(),
347                                         getConfig().secureSettingName, allowedItems,
348                                         approvedUserId);
349                             }
350 
351                         }
352                     }
353                 }
354             }
355         }
356 
357         writeExtraXmlTags(out);
358 
359         out.endTag(null, getConfig().xmlTag);
360     }
361 
362     /**
363      * Writes extra xml attributes to {@link #TAG_MANAGED_SERVICES} tag.
364      */
writeExtraAttributes(XmlSerializer out, int userId)365     protected void writeExtraAttributes(XmlSerializer out, int userId) throws IOException {}
366 
367     /**
368      * Writes extra xml tags within the parent tag specified in {@link Config#xmlTag}.
369      */
writeExtraXmlTags(XmlSerializer out)370     protected void writeExtraXmlTags(XmlSerializer out) throws IOException {}
371 
372     /**
373      * This is called to process tags other than {@link #TAG_MANAGED_SERVICES}.
374      */
readExtraTag(String tag, XmlPullParser parser)375     protected void readExtraTag(String tag, XmlPullParser parser) throws IOException {}
376 
migrateToXml()377     protected void migrateToXml() {
378         loadAllowedComponentsFromSettings();
379     }
380 
readXml( XmlPullParser parser, TriPredicate<String, Integer, String> allowedManagedServicePackages, boolean forRestore, int userId)381     public void readXml(
382             XmlPullParser parser,
383             TriPredicate<String, Integer, String> allowedManagedServicePackages,
384             boolean forRestore,
385             int userId)
386             throws XmlPullParserException, IOException {
387         // read grants
388         int type;
389         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
390             String tag = parser.getName();
391             if (type == XmlPullParser.END_TAG
392                     && getConfig().xmlTag.equals(tag)) {
393                 break;
394             }
395             if (type == XmlPullParser.START_TAG) {
396                 if (TAG_MANAGED_SERVICES.equals(tag)) {
397                     Slog.i(TAG, "Read " + mConfig.caption + " permissions from xml");
398 
399                     final String approved = XmlUtils.readStringAttribute(parser, ATT_APPROVED_LIST);
400                     // Ignore parser's user id for restore.
401                     final int resolvedUserId = forRestore
402                             ? userId : XmlUtils.readIntAttribute(parser, ATT_USER_ID, 0);
403                     final boolean isPrimary =
404                             XmlUtils.readBooleanAttribute(parser, ATT_IS_PRIMARY, true);
405                     readExtraAttributes(tag, parser, resolvedUserId);
406                     if (allowedManagedServicePackages == null || allowedManagedServicePackages.test(
407                             getPackageName(approved), resolvedUserId, getRequiredPermission())) {
408                         if (mUm.getUserInfo(resolvedUserId) != null) {
409                             addApprovedList(approved, resolvedUserId, isPrimary);
410                         }
411                         mUseXml = true;
412                     }
413                 } else {
414                     readExtraTag(tag, parser);
415                 }
416             }
417         }
418         rebindServices(false, USER_ALL);
419     }
420 
421     /**
422      * Read extra attributes in the {@link #TAG_MANAGED_SERVICES} tag.
423      */
readExtraAttributes(String tag, XmlPullParser parser, int userId)424     protected void readExtraAttributes(String tag, XmlPullParser parser, int userId)
425             throws IOException {}
426 
getRequiredPermission()427     protected abstract String getRequiredPermission();
428 
loadAllowedComponentsFromSettings()429     private void loadAllowedComponentsFromSettings() {
430         for (UserInfo user : mUm.getUsers()) {
431             final ContentResolver cr = mContext.getContentResolver();
432             addApprovedList(Settings.Secure.getStringForUser(
433                     cr,
434                     getConfig().secureSettingName,
435                     user.id), user.id, true);
436             if (!TextUtils.isEmpty(getConfig().secondarySettingName)) {
437                 addApprovedList(Settings.Secure.getStringForUser(
438                         cr,
439                         getConfig().secondarySettingName,
440                         user.id), user.id, false);
441             }
442         }
443         Slog.d(TAG, "Done loading approved values from settings");
444     }
445 
addApprovedList(String approved, int userId, boolean isPrimary)446     protected void addApprovedList(String approved, int userId, boolean isPrimary) {
447         if (TextUtils.isEmpty(approved)) {
448             approved = "";
449         }
450         synchronized (mApproved) {
451             ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
452             if (approvedByType == null) {
453                 approvedByType = new ArrayMap<>();
454                 mApproved.put(userId, approvedByType);
455             }
456 
457             ArraySet<String> approvedList = approvedByType.get(isPrimary);
458             if (approvedList == null) {
459                 approvedList = new ArraySet<>();
460                 approvedByType.put(isPrimary, approvedList);
461             }
462 
463             String[] approvedArray = approved.split(ENABLED_SERVICES_SEPARATOR);
464             for (String pkgOrComponent : approvedArray) {
465                 String approvedItem = getApprovedValue(pkgOrComponent);
466                 if (approvedItem != null) {
467                     approvedList.add(approvedItem);
468                 }
469             }
470         }
471     }
472 
isComponentEnabledForPackage(String pkg)473     protected boolean isComponentEnabledForPackage(String pkg) {
474         return mEnabledServicesPackageNames.contains(pkg);
475     }
476 
setPackageOrComponentEnabled(String pkgOrComponent, int userId, boolean isPrimary, boolean enabled)477     protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId,
478             boolean isPrimary, boolean enabled) {
479         Slog.i(TAG,
480                 (enabled ? " Allowing " : "Disallowing ") + mConfig.caption + " " + pkgOrComponent);
481         synchronized (mApproved) {
482             ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.get(userId);
483             if (allowedByType == null) {
484                 allowedByType = new ArrayMap<>();
485                 mApproved.put(userId, allowedByType);
486             }
487             ArraySet<String> approved = allowedByType.get(isPrimary);
488             if (approved == null) {
489                 approved = new ArraySet<>();
490                 allowedByType.put(isPrimary, approved);
491             }
492             String approvedItem = getApprovedValue(pkgOrComponent);
493 
494             if (approvedItem != null) {
495                 if (enabled) {
496                     approved.add(approvedItem);
497                 } else {
498                     approved.remove(approvedItem);
499                 }
500             }
501         }
502 
503         rebindServices(false, userId);
504     }
505 
getApprovedValue(String pkgOrComponent)506     private String getApprovedValue(String pkgOrComponent) {
507         if (mApprovalLevel == APPROVAL_BY_COMPONENT) {
508             if(ComponentName.unflattenFromString(pkgOrComponent) != null) {
509                 return pkgOrComponent;
510             }
511             return null;
512         } else {
513             return getPackageName(pkgOrComponent);
514         }
515     }
516 
getApproved(int userId, boolean primary)517     protected String getApproved(int userId, boolean primary) {
518         synchronized (mApproved) {
519             final ArrayMap<Boolean, ArraySet<String>> allowedByType =
520                     mApproved.getOrDefault(userId, new ArrayMap<>());
521             ArraySet<String> approved = allowedByType.getOrDefault(primary, new ArraySet<>());
522             return String.join(ENABLED_SERVICES_SEPARATOR, approved);
523         }
524     }
525 
getAllowedComponents(int userId)526     protected List<ComponentName> getAllowedComponents(int userId) {
527         final List<ComponentName> allowedComponents = new ArrayList<>();
528         synchronized (mApproved) {
529             final ArrayMap<Boolean, ArraySet<String>> allowedByType =
530                     mApproved.getOrDefault(userId, new ArrayMap<>());
531             for (int i = 0; i < allowedByType.size(); i++) {
532                 final ArraySet<String> allowed = allowedByType.valueAt(i);
533                 for (int j = 0; j < allowed.size(); j++) {
534                     ComponentName cn = ComponentName.unflattenFromString(allowed.valueAt(j));
535                     if (cn != null) {
536                         allowedComponents.add(cn);
537                     }
538                 }
539             }
540         }
541         return allowedComponents;
542     }
543 
getAllowedPackages(int userId)544     protected List<String> getAllowedPackages(int userId) {
545         final List<String> allowedPackages = new ArrayList<>();
546         synchronized (mApproved) {
547             final ArrayMap<Boolean, ArraySet<String>> allowedByType =
548                     mApproved.getOrDefault(userId, new ArrayMap<>());
549             for (int i = 0; i < allowedByType.size(); i++) {
550                 final ArraySet<String> allowed = allowedByType.valueAt(i);
551                 for (int j = 0; j < allowed.size(); j++) {
552                     String pkgName = getPackageName(allowed.valueAt(j));
553                     if (!TextUtils.isEmpty(pkgName)) {
554                         allowedPackages.add(pkgName);
555                     }
556                 }
557             }
558         }
559         return allowedPackages;
560     }
561 
isPackageOrComponentAllowed(String pkgOrComponent, int userId)562     protected boolean isPackageOrComponentAllowed(String pkgOrComponent, int userId) {
563         synchronized (mApproved) {
564             ArrayMap<Boolean, ArraySet<String>> allowedByType =
565                     mApproved.getOrDefault(userId, new ArrayMap<>());
566             for (int i = 0; i < allowedByType.size(); i++) {
567                 ArraySet<String> allowed = allowedByType.valueAt(i);
568                 if (allowed.contains(pkgOrComponent)) {
569                     return true;
570                 }
571             }
572         }
573         return false;
574     }
575 
isPackageAllowed(String pkg, int userId)576     protected boolean isPackageAllowed(String pkg, int userId) {
577         if (pkg == null) {
578             return false;
579         }
580         synchronized (mApproved) {
581             ArrayMap<Boolean, ArraySet<String>> allowedByType =
582                     mApproved.getOrDefault(userId, new ArrayMap<>());
583             for (int i = 0; i < allowedByType.size(); i++) {
584                 ArraySet<String> allowed = allowedByType.valueAt(i);
585                 for (String allowedEntry : allowed) {
586                     ComponentName component = ComponentName.unflattenFromString(allowedEntry);
587                     if (component != null) {
588                         if (pkg.equals(component.getPackageName())) {
589                             return true;
590                         }
591                     } else {
592                         if (pkg.equals(allowedEntry)) {
593                             return true;
594                         }
595                     }
596                 }
597             }
598         }
599         return false;
600     }
601 
onPackagesChanged(boolean removingPackage, String[] pkgList, int[] uidList)602     public void onPackagesChanged(boolean removingPackage, String[] pkgList, int[] uidList) {
603         if (DEBUG) Slog.d(TAG, "onPackagesChanged removingPackage=" + removingPackage
604                 + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList))
605                 + " mEnabledServicesPackageNames=" + mEnabledServicesPackageNames);
606 
607         if (pkgList != null && (pkgList.length > 0)) {
608             boolean anyServicesInvolved = false;
609             // Remove notification settings for uninstalled package
610             if (removingPackage && uidList != null) {
611                 int size = Math.min(pkgList.length, uidList.length);
612                 for (int i = 0; i < size; i++) {
613                     final String pkg = pkgList[i];
614                     final int userId = UserHandle.getUserId(uidList[i]);
615                     anyServicesInvolved = removeUninstalledItemsFromApprovedLists(userId, pkg);
616                 }
617             }
618             for (String pkgName : pkgList) {
619                 if (mEnabledServicesPackageNames.contains(pkgName)) {
620                     anyServicesInvolved = true;
621                 }
622                 if (uidList != null && uidList.length > 0) {
623                     for (int uid : uidList) {
624                         if (isPackageAllowed(pkgName, UserHandle.getUserId(uid))) {
625                             anyServicesInvolved = true;
626                         }
627                     }
628                 }
629             }
630 
631             if (anyServicesInvolved) {
632                 // make sure we're still bound to any of our services who may have just upgraded
633                 rebindServices(false, USER_ALL);
634             }
635         }
636     }
637 
onUserRemoved(int user)638     public void onUserRemoved(int user) {
639         Slog.i(TAG, "Removing approved services for removed user " + user);
640         synchronized (mApproved) {
641             mApproved.remove(user);
642         }
643         rebindServices(true, user);
644     }
645 
onUserSwitched(int user)646     public void onUserSwitched(int user) {
647         if (DEBUG) Slog.d(TAG, "onUserSwitched u=" + user);
648         rebindServices(true, user);
649     }
650 
onUserUnlocked(int user)651     public void onUserUnlocked(int user) {
652         if (DEBUG) Slog.d(TAG, "onUserUnlocked u=" + user);
653         rebindServices(false, user);
654     }
655 
getServiceFromTokenLocked(IInterface service)656     private ManagedServiceInfo getServiceFromTokenLocked(IInterface service) {
657         if (service == null) {
658             return null;
659         }
660         final IBinder token = service.asBinder();
661         final int N = mServices.size();
662         for (int i = 0; i < N; i++) {
663             final ManagedServiceInfo info = mServices.get(i);
664             if (info.service.asBinder() == token) return info;
665         }
666         return null;
667     }
668 
isServiceTokenValidLocked(IInterface service)669     protected boolean isServiceTokenValidLocked(IInterface service) {
670         if (service == null) {
671             return false;
672         }
673         ManagedServiceInfo info = getServiceFromTokenLocked(service);
674         if (info != null) {
675             return true;
676         }
677         return false;
678     }
679 
checkServiceTokenLocked(IInterface service)680     protected ManagedServiceInfo checkServiceTokenLocked(IInterface service) {
681         checkNotNull(service);
682         ManagedServiceInfo info = getServiceFromTokenLocked(service);
683         if (info != null) {
684             return info;
685         }
686         throw new SecurityException("Disallowed call from unknown " + getCaption() + ": "
687                 + service + " " + service.getClass());
688     }
689 
isSameUser(IInterface service, int userId)690     public boolean isSameUser(IInterface service, int userId) {
691         checkNotNull(service);
692         synchronized (mMutex) {
693             ManagedServiceInfo info = getServiceFromTokenLocked(service);
694             if (info != null) {
695                 return info.isSameUser(userId);
696             }
697             return false;
698         }
699     }
700 
unregisterService(IInterface service, int userid)701     public void unregisterService(IInterface service, int userid) {
702         checkNotNull(service);
703         // no need to check permissions; if your service binder is in the list,
704         // that's proof that you had permission to add it in the first place
705         unregisterServiceImpl(service, userid);
706     }
707 
registerService(IInterface service, ComponentName component, int userid)708     public void registerService(IInterface service, ComponentName component, int userid) {
709         checkNotNull(service);
710         ManagedServiceInfo info = registerServiceImpl(service, component, userid);
711         if (info != null) {
712             onServiceAdded(info);
713         }
714     }
715 
716     /**
717      * Add a service to our callbacks. The lifecycle of this service is managed externally,
718      * but unlike a system service, it should not be considered privileged.
719      * */
registerGuestService(ManagedServiceInfo guest)720     protected void registerGuestService(ManagedServiceInfo guest) {
721         checkNotNull(guest.service);
722         if (!checkType(guest.service)) {
723             throw new IllegalArgumentException();
724         }
725         if (registerServiceImpl(guest) != null) {
726             onServiceAdded(guest);
727         }
728     }
729 
setComponentState(ComponentName component, boolean enabled)730     protected void setComponentState(ComponentName component, boolean enabled) {
731         boolean previous = !mSnoozingForCurrentProfiles.contains(component);
732         if (previous == enabled) {
733             return;
734         }
735 
736         if (enabled) {
737             mSnoozingForCurrentProfiles.remove(component);
738         } else {
739             mSnoozingForCurrentProfiles.add(component);
740         }
741 
742         // State changed
743         Slog.d(TAG, ((enabled) ? "Enabling " : "Disabling ") + "component " +
744                 component.flattenToShortString());
745 
746         synchronized (mMutex) {
747             final IntArray userIds = mUserProfiles.getCurrentProfileIds();
748 
749             for (int i = 0; i < userIds.size(); i++) {
750                 final int userId = userIds.get(i);
751                 if (enabled) {
752                     if (isPackageOrComponentAllowed(component.flattenToString(), userId)
753                             || isPackageOrComponentAllowed(component.getPackageName(), userId)) {
754                         registerServiceLocked(component, userId);
755                     } else {
756                         Slog.d(TAG, component + " no longer has permission to be bound");
757                     }
758                 } else {
759                     unregisterServiceLocked(component, userId);
760                 }
761             }
762         }
763     }
764 
loadComponentNamesFromValues( ArraySet<String> approved, int userId)765     private @NonNull ArraySet<ComponentName> loadComponentNamesFromValues(
766             ArraySet<String> approved, int userId) {
767         if (approved == null || approved.size() == 0)
768             return new ArraySet<>();
769         ArraySet<ComponentName> result = new ArraySet<>(approved.size());
770         for (int i = 0; i < approved.size(); i++) {
771             final String packageOrComponent = approved.valueAt(i);
772             if (!TextUtils.isEmpty(packageOrComponent)) {
773                 ComponentName component = ComponentName.unflattenFromString(packageOrComponent);
774                 if (component != null) {
775                     result.add(component);
776                 } else {
777                     result.addAll(queryPackageForServices(packageOrComponent, userId));
778                 }
779             }
780         }
781         return result;
782     }
783 
queryPackageForServices(String packageName, int userId)784     protected Set<ComponentName> queryPackageForServices(String packageName, int userId) {
785         return queryPackageForServices(packageName, 0, userId);
786     }
787 
queryPackageForServices(String packageName, int extraFlags, int userId)788     protected Set<ComponentName> queryPackageForServices(String packageName, int extraFlags,
789             int userId) {
790         Set<ComponentName> installed = new ArraySet<>();
791         final PackageManager pm = mContext.getPackageManager();
792         Intent queryIntent = new Intent(mConfig.serviceInterface);
793         if (!TextUtils.isEmpty(packageName)) {
794             queryIntent.setPackage(packageName);
795         }
796         List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
797                 queryIntent,
798                 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA | extraFlags,
799                 userId);
800         if (DEBUG)
801             Slog.v(TAG, mConfig.serviceInterface + " services: " + installedServices);
802         if (installedServices != null) {
803             for (int i = 0, count = installedServices.size(); i < count; i++) {
804                 ResolveInfo resolveInfo = installedServices.get(i);
805                 ServiceInfo info = resolveInfo.serviceInfo;
806 
807                 ComponentName component = new ComponentName(info.packageName, info.name);
808                 if (!mConfig.bindPermission.equals(info.permission)) {
809                     Slog.w(TAG, "Skipping " + getCaption() + " service "
810                         + info.packageName + "/" + info.name
811                         + ": it does not require the permission "
812                         + mConfig.bindPermission);
813                     continue;
814                 }
815                 installed.add(component);
816             }
817         }
818         return installed;
819     }
820 
getAllowedPackages()821     protected Set<String> getAllowedPackages() {
822         final Set<String> allowedPackages = new ArraySet<>();
823         synchronized (mApproved) {
824             for (int k = 0; k < mApproved.size(); k++) {
825                 ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.valueAt(k);
826                 for (int i = 0; i < allowedByType.size(); i++) {
827                     final ArraySet<String> allowed = allowedByType.valueAt(i);
828                     for (int j = 0; j < allowed.size(); j++) {
829                         String pkgName = getPackageName(allowed.valueAt(j));
830                         if (!TextUtils.isEmpty(pkgName)) {
831                             allowedPackages.add(pkgName);
832                         }
833                     }
834                 }
835             }
836         }
837         return allowedPackages;
838     }
839 
trimApprovedListsAccordingToInstalledServices(int userId)840     private void trimApprovedListsAccordingToInstalledServices(int userId) {
841         synchronized (mApproved) {
842             final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
843             if (approvedByType == null) {
844                 return;
845             }
846             for (int i = 0; i < approvedByType.size(); i++) {
847                 final ArraySet<String> approved = approvedByType.valueAt(i);
848                 for (int j = approved.size() - 1; j >= 0; j--) {
849                     final String approvedPackageOrComponent = approved.valueAt(j);
850                     if (!isValidEntry(approvedPackageOrComponent, userId)) {
851                         approved.removeAt(j);
852                         Slog.v(TAG, "Removing " + approvedPackageOrComponent
853                                 + " from approved list; no matching services found");
854                     } else {
855                         if (DEBUG) {
856                             Slog.v(TAG, "Keeping " + approvedPackageOrComponent
857                                     + " on approved list; matching services found");
858                         }
859                     }
860                 }
861             }
862         }
863     }
864 
removeUninstalledItemsFromApprovedLists(int uninstalledUserId, String pkg)865     private boolean removeUninstalledItemsFromApprovedLists(int uninstalledUserId, String pkg) {
866         boolean removed = false;
867         synchronized (mApproved) {
868             final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(
869                     uninstalledUserId);
870             if (approvedByType != null) {
871                 int M = approvedByType.size();
872                 for (int j = 0; j < M; j++) {
873                     final ArraySet<String> approved = approvedByType.valueAt(j);
874                     int O = approved.size();
875                     for (int k = O - 1; k >= 0; k--) {
876                         final String packageOrComponent = approved.valueAt(k);
877                         final String packageName = getPackageName(packageOrComponent);
878                         if (TextUtils.equals(pkg, packageName)) {
879                             approved.removeAt(k);
880                             if (DEBUG) {
881                                 Slog.v(TAG, "Removing " + packageOrComponent
882                                         + " from approved list; uninstalled");
883                             }
884                         }
885                     }
886                 }
887             }
888         }
889         return removed;
890     }
891 
getPackageName(String packageOrComponent)892     protected String getPackageName(String packageOrComponent) {
893         final ComponentName component = ComponentName.unflattenFromString(packageOrComponent);
894         if (component != null) {
895             return component.getPackageName();
896         } else {
897             return packageOrComponent;
898         }
899     }
900 
isValidEntry(String packageOrComponent, int userId)901     protected boolean isValidEntry(String packageOrComponent, int userId) {
902         return hasMatchingServices(packageOrComponent, userId);
903     }
904 
hasMatchingServices(String packageOrComponent, int userId)905     private boolean hasMatchingServices(String packageOrComponent, int userId) {
906         if (!TextUtils.isEmpty(packageOrComponent)) {
907             final String packageName = getPackageName(packageOrComponent);
908             return queryPackageForServices(packageName, userId).size() > 0;
909         }
910         return false;
911     }
912 
913     @VisibleForTesting
getAllowedComponents(IntArray userIds)914     protected SparseArray<ArraySet<ComponentName>> getAllowedComponents(IntArray userIds) {
915         final int nUserIds = userIds.size();
916         final SparseArray<ArraySet<ComponentName>> componentsByUser = new SparseArray<>();
917 
918         for (int i = 0; i < nUserIds; ++i) {
919             final int userId = userIds.get(i);
920             synchronized (mApproved) {
921                 final ArrayMap<Boolean, ArraySet<String>> approvedLists = mApproved.get(userId);
922                 if (approvedLists != null) {
923                     final int N = approvedLists.size();
924                     for (int j = 0; j < N; j++) {
925                         ArraySet<ComponentName> approvedByUser = componentsByUser.get(userId);
926                         if (approvedByUser == null) {
927                             approvedByUser = new ArraySet<>();
928                             componentsByUser.put(userId, approvedByUser);
929                         }
930                         approvedByUser.addAll(
931                                 loadComponentNamesFromValues(approvedLists.valueAt(j), userId));
932                     }
933                 }
934             }
935         }
936         return componentsByUser;
937     }
938 
939     @GuardedBy("mMutex")
populateComponentsToBind(SparseArray<Set<ComponentName>> componentsToBind, final IntArray activeUsers, SparseArray<ArraySet<ComponentName>> approvedComponentsByUser)940     protected void populateComponentsToBind(SparseArray<Set<ComponentName>> componentsToBind,
941             final IntArray activeUsers,
942             SparseArray<ArraySet<ComponentName>> approvedComponentsByUser) {
943         mEnabledServicesForCurrentProfiles.clear();
944         mEnabledServicesPackageNames.clear();
945         final int nUserIds = activeUsers.size();
946 
947         for (int i = 0; i < nUserIds; ++i) {
948             // decode the list of components
949             final int userId = activeUsers.get(i);
950             final ArraySet<ComponentName> userComponents = approvedComponentsByUser.get(userId);
951             if (null == userComponents) {
952                 componentsToBind.put(userId, new ArraySet<>());
953                 continue;
954             }
955 
956             final Set<ComponentName> add = new HashSet<>(userComponents);
957             add.removeAll(mSnoozingForCurrentProfiles);
958 
959             componentsToBind.put(userId, add);
960 
961             mEnabledServicesForCurrentProfiles.addAll(userComponents);
962 
963             for (int j = 0; j < userComponents.size(); j++) {
964                 final ComponentName component = userComponents.valueAt(j);
965                 mEnabledServicesPackageNames.add(component.getPackageName());
966             }
967         }
968     }
969 
970     @GuardedBy("mMutex")
getRemovableConnectedServices()971     protected Set<ManagedServiceInfo> getRemovableConnectedServices() {
972         final Set<ManagedServiceInfo> removableBoundServices = new ArraySet<>();
973         for (ManagedServiceInfo service : mServices) {
974             if (!service.isSystem && !service.isGuest(this)) {
975                 removableBoundServices.add(service);
976             }
977         }
978         return removableBoundServices;
979     }
980 
populateComponentsToUnbind( boolean forceRebind, Set<ManagedServiceInfo> removableBoundServices, SparseArray<Set<ComponentName>> allowedComponentsToBind, SparseArray<Set<ComponentName>> componentsToUnbind)981     protected void populateComponentsToUnbind(
982             boolean forceRebind,
983             Set<ManagedServiceInfo> removableBoundServices,
984             SparseArray<Set<ComponentName>> allowedComponentsToBind,
985             SparseArray<Set<ComponentName>> componentsToUnbind) {
986         for (ManagedServiceInfo info : removableBoundServices) {
987             final Set<ComponentName> allowedComponents = allowedComponentsToBind.get(info.userid);
988             if (allowedComponents != null) {
989                 if (forceRebind || !allowedComponents.contains(info.component)) {
990                     Set<ComponentName> toUnbind =
991                             componentsToUnbind.get(info.userid, new ArraySet<>());
992                     toUnbind.add(info.component);
993                     componentsToUnbind.put(info.userid, toUnbind);
994                 }
995             }
996         }
997     }
998 
999     /**
1000      * Called whenever packages change, the user switches, or the secure setting
1001      * is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
1002      */
rebindServices(boolean forceRebind, int userToRebind)1003     protected void rebindServices(boolean forceRebind, int userToRebind) {
1004         if (DEBUG) Slog.d(TAG, "rebindServices " + forceRebind + " " + userToRebind);
1005         IntArray userIds = mUserProfiles.getCurrentProfileIds();
1006         if (userToRebind != USER_ALL) {
1007             userIds = new IntArray(1);
1008             userIds.add(userToRebind);
1009         }
1010 
1011         final SparseArray<Set<ComponentName>> componentsToBind = new SparseArray<>();
1012         final SparseArray<Set<ComponentName>> componentsToUnbind = new SparseArray<>();
1013 
1014         synchronized (mMutex) {
1015             final SparseArray<ArraySet<ComponentName>> approvedComponentsByUser =
1016                     getAllowedComponents(userIds);
1017             final Set<ManagedServiceInfo> removableBoundServices = getRemovableConnectedServices();
1018 
1019             // Filter approvedComponentsByUser to collect all of the components that are allowed
1020             // for the currently active user(s).
1021             populateComponentsToBind(componentsToBind, userIds, approvedComponentsByUser);
1022 
1023             // For every current non-system connection, disconnect services that are no longer
1024             // approved, or ALL services if we are force rebinding
1025             populateComponentsToUnbind(
1026                     forceRebind, removableBoundServices, componentsToBind, componentsToUnbind);
1027         }
1028 
1029         unbindFromServices(componentsToUnbind);
1030         bindToServices(componentsToBind);
1031     }
1032 
unbindFromServices(SparseArray<Set<ComponentName>> componentsToUnbind)1033     protected void unbindFromServices(SparseArray<Set<ComponentName>> componentsToUnbind) {
1034         for (int i = 0; i < componentsToUnbind.size(); i++) {
1035             final int userId = componentsToUnbind.keyAt(i);
1036             final Set<ComponentName> removableComponents = componentsToUnbind.get(userId);
1037             for (ComponentName cn : removableComponents) {
1038                 // No longer allowed to be bound, or must rebind.
1039                 Slog.v(TAG, "disabling " + getCaption() + " for user " + userId + ": " + cn);
1040                 unregisterService(cn, userId);
1041             }
1042         }
1043     }
1044 
1045     // Attempt to bind to services, skipping those that cannot be found or lack the permission.
bindToServices(SparseArray<Set<ComponentName>> componentsToBind)1046     private void bindToServices(SparseArray<Set<ComponentName>> componentsToBind) {
1047         for (int i = 0; i < componentsToBind.size(); i++) {
1048             final int userId = componentsToBind.keyAt(i);
1049             final Set<ComponentName> add = componentsToBind.get(userId);
1050             for (ComponentName component : add) {
1051                 try {
1052                     ServiceInfo info = mPm.getServiceInfo(component,
1053                             PackageManager.MATCH_DIRECT_BOOT_AWARE
1054                                     | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
1055                     if (info == null) {
1056                         Slog.w(TAG, "Not binding " + getCaption() + " service " + component
1057                                 + ": service not found");
1058                         continue;
1059                     }
1060                     if (!mConfig.bindPermission.equals(info.permission)) {
1061                         Slog.w(TAG, "Not binding " + getCaption() + " service " + component
1062                                 + ": it does not require the permission " + mConfig.bindPermission);
1063                         continue;
1064                     }
1065                     Slog.v(TAG,
1066                             "enabling " + getCaption() + " for " + userId + ": " + component);
1067                     registerService(component, userId);
1068                 } catch (RemoteException e) {
1069                     e.rethrowFromSystemServer();
1070                 }
1071             }
1072         }
1073     }
1074 
1075     /**
1076      * Version of registerService that takes the name of a service component to bind to.
1077      */
registerService(final ComponentName name, final int userid)1078     private void registerService(final ComponentName name, final int userid) {
1079         synchronized (mMutex) {
1080             registerServiceLocked(name, userid);
1081         }
1082     }
1083 
1084     /**
1085      * Inject a system service into the management list.
1086      */
registerSystemService(final ComponentName name, final int userid)1087     public void registerSystemService(final ComponentName name, final int userid) {
1088         synchronized (mMutex) {
1089             registerServiceLocked(name, userid, true /* isSystem */);
1090         }
1091     }
1092 
registerServiceLocked(final ComponentName name, final int userid)1093     private void registerServiceLocked(final ComponentName name, final int userid) {
1094         registerServiceLocked(name, userid, false /* isSystem */);
1095     }
1096 
registerServiceLocked(final ComponentName name, final int userid, final boolean isSystem)1097     private void registerServiceLocked(final ComponentName name, final int userid,
1098             final boolean isSystem) {
1099         if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid);
1100 
1101         final Pair<ComponentName, Integer> servicesBindingTag = Pair.create(name, userid);
1102         if (mServicesBound.contains(servicesBindingTag)) {
1103             Slog.v(TAG, "Not registering " + name + " is already bound");
1104             // stop registering this thing already! we're working on it
1105             return;
1106         }
1107         mServicesBound.add(servicesBindingTag);
1108 
1109         final int N = mServices.size();
1110         for (int i = N - 1; i >= 0; i--) {
1111             final ManagedServiceInfo info = mServices.get(i);
1112             if (name.equals(info.component)
1113                 && info.userid == userid) {
1114                 // cut old connections
1115                 Slog.v(TAG, "    disconnecting old " + getCaption() + ": " + info.service);
1116                 removeServiceLocked(i);
1117                 if (info.connection != null) {
1118                     unbindService(info.connection, info.component, info.userid);
1119                 }
1120             }
1121         }
1122 
1123         Intent intent = new Intent(mConfig.serviceInterface);
1124         intent.setComponent(name);
1125 
1126         intent.putExtra(Intent.EXTRA_CLIENT_LABEL, mConfig.clientLabel);
1127 
1128         final PendingIntent pendingIntent = PendingIntent.getActivity(
1129             mContext, 0, new Intent(mConfig.settingsAction), 0);
1130         intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent);
1131 
1132         ApplicationInfo appInfo = null;
1133         try {
1134             appInfo = mContext.getPackageManager().getApplicationInfo(
1135                 name.getPackageName(), 0);
1136         } catch (NameNotFoundException e) {
1137             // Ignore if the package doesn't exist we won't be able to bind to the service.
1138         }
1139         final int targetSdkVersion =
1140             appInfo != null ? appInfo.targetSdkVersion : Build.VERSION_CODES.BASE;
1141 
1142         try {
1143             Slog.v(TAG, "binding: " + intent);
1144             ServiceConnection serviceConnection = new ServiceConnection() {
1145                 IInterface mService;
1146 
1147                 @Override
1148                 public void onServiceConnected(ComponentName name, IBinder binder) {
1149                     Slog.v(TAG,  userid + " " + getCaption() + " service connected: " + name);
1150                     boolean added = false;
1151                     ManagedServiceInfo info = null;
1152                     synchronized (mMutex) {
1153                         mServicesRebinding.remove(servicesBindingTag);
1154                         try {
1155                             mService = asInterface(binder);
1156                             info = newServiceInfo(mService, name,
1157                                 userid, isSystem, this, targetSdkVersion);
1158                             binder.linkToDeath(info, 0);
1159                             added = mServices.add(info);
1160                         } catch (RemoteException e) {
1161                             Slog.e(TAG, "Failed to linkToDeath, already dead", e);
1162                         }
1163                     }
1164                     if (added) {
1165                         onServiceAdded(info);
1166                     }
1167                 }
1168 
1169                 @Override
1170                 public void onServiceDisconnected(ComponentName name) {
1171                     Slog.v(TAG, userid + " " + getCaption() + " connection lost: " + name);
1172                 }
1173 
1174                 @Override
1175                 public void onBindingDied(ComponentName name) {
1176                     Slog.w(TAG,  userid + " " + getCaption() + " binding died: " + name);
1177                     synchronized (mMutex) {
1178                         unbindService(this, name, userid);
1179                         if (!mServicesRebinding.contains(servicesBindingTag)) {
1180                             mServicesRebinding.add(servicesBindingTag);
1181                             mHandler.postDelayed(new Runnable() {
1182                                     @Override
1183                                     public void run() {
1184                                         registerService(name, userid);
1185                                     }
1186                                }, ON_BINDING_DIED_REBIND_DELAY_MS);
1187                         } else {
1188                             Slog.v(TAG, getCaption() + " not rebinding in user " + userid
1189                                     + " as a previous rebind attempt was made: " + name);
1190                         }
1191                     }
1192                 }
1193 
1194                 @Override
1195                 public void onNullBinding(ComponentName name) {
1196                     Slog.v(TAG, "onNullBinding() called with: name = [" + name + "]");
1197                     mServicesBound.remove(servicesBindingTag);
1198                 }
1199             };
1200             if (!mContext.bindServiceAsUser(intent,
1201                     serviceConnection,
1202                     getBindFlags(),
1203                     new UserHandle(userid))) {
1204                 mServicesBound.remove(servicesBindingTag);
1205                 Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent
1206                         + " in user " + userid);
1207                 return;
1208             }
1209         } catch (SecurityException ex) {
1210             mServicesBound.remove(servicesBindingTag);
1211             Slog.e(TAG, "Unable to bind " + getCaption() + " service: " + intent, ex);
1212         }
1213     }
1214 
isBound(ComponentName cn, int userId)1215     boolean isBound(ComponentName cn, int userId) {
1216         final Pair<ComponentName, Integer> servicesBindingTag = Pair.create(cn, userId);
1217         return mServicesBound.contains(servicesBindingTag);
1218     }
1219 
1220     /**
1221      * Remove a service for the given user by ComponentName
1222      */
unregisterService(ComponentName name, int userid)1223     private void unregisterService(ComponentName name, int userid) {
1224         synchronized (mMutex) {
1225             unregisterServiceLocked(name, userid);
1226         }
1227     }
1228 
unregisterServiceLocked(ComponentName name, int userid)1229     private void unregisterServiceLocked(ComponentName name, int userid) {
1230         final int N = mServices.size();
1231         for (int i = N - 1; i >= 0; i--) {
1232             final ManagedServiceInfo info = mServices.get(i);
1233             if (name.equals(info.component) && info.userid == userid) {
1234                 removeServiceLocked(i);
1235                 if (info.connection != null) {
1236                     unbindService(info.connection, info.component, info.userid);
1237                 }
1238             }
1239         }
1240     }
1241 
1242     /**
1243      * Removes a service from the list but does not unbind
1244      *
1245      * @return the removed service.
1246      */
removeServiceImpl(IInterface service, final int userid)1247     private ManagedServiceInfo removeServiceImpl(IInterface service, final int userid) {
1248         if (DEBUG) Slog.d(TAG, "removeServiceImpl service=" + service + " u=" + userid);
1249         ManagedServiceInfo serviceInfo = null;
1250         synchronized (mMutex) {
1251             final int N = mServices.size();
1252             for (int i = N - 1; i >= 0; i--) {
1253                 final ManagedServiceInfo info = mServices.get(i);
1254                 if (info.service.asBinder() == service.asBinder() && info.userid == userid) {
1255                     Slog.d(TAG, "Removing active service " + info.component);
1256                     serviceInfo = removeServiceLocked(i);
1257                 }
1258             }
1259         }
1260         return serviceInfo;
1261     }
1262 
removeServiceLocked(int i)1263     private ManagedServiceInfo removeServiceLocked(int i) {
1264         final ManagedServiceInfo info = mServices.remove(i);
1265         onServiceRemovedLocked(info);
1266         return info;
1267     }
1268 
checkNotNull(IInterface service)1269     private void checkNotNull(IInterface service) {
1270         if (service == null) {
1271             throw new IllegalArgumentException(getCaption() + " must not be null");
1272         }
1273     }
1274 
registerServiceImpl(final IInterface service, final ComponentName component, final int userid)1275     private ManagedServiceInfo registerServiceImpl(final IInterface service,
1276             final ComponentName component, final int userid) {
1277         ManagedServiceInfo info = newServiceInfo(service, component, userid,
1278                 true /*isSystem*/, null /*connection*/, Build.VERSION_CODES.LOLLIPOP);
1279         return registerServiceImpl(info);
1280     }
1281 
registerServiceImpl(ManagedServiceInfo info)1282     private ManagedServiceInfo registerServiceImpl(ManagedServiceInfo info) {
1283         synchronized (mMutex) {
1284             try {
1285                 info.service.asBinder().linkToDeath(info, 0);
1286                 mServices.add(info);
1287                 return info;
1288             } catch (RemoteException e) {
1289                 // already dead
1290             }
1291         }
1292         return null;
1293     }
1294 
1295     /**
1296      * Removes a service from the list and unbinds.
1297      */
unregisterServiceImpl(IInterface service, int userid)1298     private void unregisterServiceImpl(IInterface service, int userid) {
1299         ManagedServiceInfo info = removeServiceImpl(service, userid);
1300         if (info != null && info.connection != null && !info.isGuest(this)) {
1301             unbindService(info.connection, info.component, info.userid);
1302         }
1303     }
1304 
unbindService(ServiceConnection connection, ComponentName component, int userId)1305     private void unbindService(ServiceConnection connection, ComponentName component, int userId) {
1306         try {
1307             mContext.unbindService(connection);
1308         } catch (IllegalArgumentException e) {
1309             Slog.e(TAG, getCaption() + " " + component + " could not be unbound", e);
1310         }
1311         synchronized (mMutex) {
1312             mServicesBound.remove(Pair.create(component, userId));
1313         }
1314     }
1315 
1316     public class ManagedServiceInfo implements IBinder.DeathRecipient {
1317         public IInterface service;
1318         public ComponentName component;
1319         public int userid;
1320         public boolean isSystem;
1321         public ServiceConnection connection;
1322         public int targetSdkVersion;
1323 
ManagedServiceInfo(IInterface service, ComponentName component, int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion)1324         public ManagedServiceInfo(IInterface service, ComponentName component,
1325                 int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion) {
1326             this.service = service;
1327             this.component = component;
1328             this.userid = userid;
1329             this.isSystem = isSystem;
1330             this.connection = connection;
1331             this.targetSdkVersion = targetSdkVersion;
1332         }
1333 
isGuest(ManagedServices host)1334         public boolean isGuest(ManagedServices host) {
1335             return ManagedServices.this != host;
1336         }
1337 
getOwner()1338         public ManagedServices getOwner() {
1339             return ManagedServices.this;
1340         }
1341 
1342         @Override
toString()1343         public String toString() {
1344             return new StringBuilder("ManagedServiceInfo[")
1345                     .append("component=").append(component)
1346                     .append(",userid=").append(userid)
1347                     .append(",isSystem=").append(isSystem)
1348                     .append(",targetSdkVersion=").append(targetSdkVersion)
1349                     .append(",connection=").append(connection == null ? null : "<connection>")
1350                     .append(",service=").append(service)
1351                     .append(']').toString();
1352         }
1353 
writeToProto(ProtoOutputStream proto, long fieldId, ManagedServices host)1354         public void writeToProto(ProtoOutputStream proto, long fieldId, ManagedServices host) {
1355             final long token = proto.start(fieldId);
1356             component.writeToProto(proto, ManagedServiceInfoProto.COMPONENT);
1357             proto.write(ManagedServiceInfoProto.USER_ID, userid);
1358             proto.write(ManagedServiceInfoProto.SERVICE, service.getClass().getName());
1359             proto.write(ManagedServiceInfoProto.IS_SYSTEM, isSystem);
1360             proto.write(ManagedServiceInfoProto.IS_GUEST, isGuest(host));
1361             proto.end(token);
1362         }
1363 
isSameUser(int userId)1364         public boolean isSameUser(int userId) {
1365             if (!isEnabledForCurrentProfiles()) {
1366                 return false;
1367             }
1368             return this.userid == userId;
1369         }
1370 
enabledAndUserMatches(int nid)1371         public boolean enabledAndUserMatches(int nid) {
1372             if (!isEnabledForCurrentProfiles()) {
1373                 return false;
1374             }
1375             if (this.userid == USER_ALL) return true;
1376             if (this.isSystem) return true;
1377             if (nid == USER_ALL || nid == this.userid) return true;
1378             return supportsProfiles()
1379                     && mUserProfiles.isCurrentProfile(nid)
1380                     && isPermittedForProfile(nid);
1381         }
1382 
supportsProfiles()1383         public boolean supportsProfiles() {
1384             return targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP;
1385         }
1386 
1387         @Override
binderDied()1388         public void binderDied() {
1389             if (DEBUG) Slog.d(TAG, "binderDied");
1390             // Remove the service, but don't unbind from the service. The system will bring the
1391             // service back up, and the onServiceConnected handler will read the service with the
1392             // new binding. If this isn't a bound service, and is just a registered
1393             // service, just removing it from the list is all we need to do anyway.
1394             removeServiceImpl(this.service, this.userid);
1395         }
1396 
1397         /** convenience method for looking in mEnabledServicesForCurrentProfiles */
isEnabledForCurrentProfiles()1398         public boolean isEnabledForCurrentProfiles() {
1399             if (this.isSystem) return true;
1400             if (this.connection == null) return false;
1401             return mEnabledServicesForCurrentProfiles.contains(this.component);
1402         }
1403 
1404         /**
1405          * Returns true if this service is allowed to receive events for the given userId. A
1406          * managed profile owner can disallow non-system services running outside of the profile
1407          * from receiving events from the profile.
1408          */
isPermittedForProfile(int userId)1409         public boolean isPermittedForProfile(int userId) {
1410             if (!mUserProfiles.isManagedProfile(userId)) {
1411                 return true;
1412             }
1413             DevicePolicyManager dpm =
1414                     (DevicePolicyManager) mContext.getSystemService(DEVICE_POLICY_SERVICE);
1415             final long identity = Binder.clearCallingIdentity();
1416             try {
1417                 return dpm.isNotificationListenerServicePermitted(
1418                         component.getPackageName(), userId);
1419             } finally {
1420                 Binder.restoreCallingIdentity(identity);
1421             }
1422         }
1423 
1424         @Override
equals(Object o)1425         public boolean equals(Object o) {
1426             if (this == o) return true;
1427             if (o == null || getClass() != o.getClass()) return false;
1428             ManagedServiceInfo that = (ManagedServiceInfo) o;
1429             return userid == that.userid
1430                     && isSystem == that.isSystem
1431                     && targetSdkVersion == that.targetSdkVersion
1432                     && Objects.equals(service, that.service)
1433                     && Objects.equals(component, that.component)
1434                     && Objects.equals(connection, that.connection);
1435         }
1436 
1437         @Override
hashCode()1438         public int hashCode() {
1439             return Objects.hash(service, component, userid, isSystem, connection, targetSdkVersion);
1440         }
1441     }
1442 
1443     /** convenience method for looking in mEnabledServicesForCurrentProfiles */
isComponentEnabledForCurrentProfiles(ComponentName component)1444     public boolean isComponentEnabledForCurrentProfiles(ComponentName component) {
1445         return mEnabledServicesForCurrentProfiles.contains(component);
1446     }
1447 
1448     public static class UserProfiles {
1449         // Profiles of the current user.
1450         private final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>();
1451 
updateCache(@onNull Context context)1452         public void updateCache(@NonNull Context context) {
1453             UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
1454             if (userManager != null) {
1455                 int currentUserId = ActivityManager.getCurrentUser();
1456                 List<UserInfo> profiles = userManager.getProfiles(currentUserId);
1457                 synchronized (mCurrentProfiles) {
1458                     mCurrentProfiles.clear();
1459                     for (UserInfo user : profiles) {
1460                         mCurrentProfiles.put(user.id, user);
1461                     }
1462                 }
1463             }
1464         }
1465 
1466         /**
1467          * Returns the currently active users (generally one user and its work profile).
1468          */
getCurrentProfileIds()1469         public IntArray getCurrentProfileIds() {
1470             synchronized (mCurrentProfiles) {
1471                 IntArray users = new IntArray(mCurrentProfiles.size());
1472                 final int N = mCurrentProfiles.size();
1473                 for (int i = 0; i < N; ++i) {
1474                     users.add(mCurrentProfiles.keyAt(i));
1475                 }
1476                 return users;
1477             }
1478         }
1479 
isCurrentProfile(int userId)1480         public boolean isCurrentProfile(int userId) {
1481             synchronized (mCurrentProfiles) {
1482                 return mCurrentProfiles.get(userId) != null;
1483             }
1484         }
1485 
isManagedProfile(int userId)1486         public boolean isManagedProfile(int userId) {
1487             synchronized (mCurrentProfiles) {
1488                 UserInfo user = mCurrentProfiles.get(userId);
1489                 return user != null && user.isManagedProfile();
1490             }
1491         }
1492     }
1493 
1494     public static class Config {
1495         public String caption;
1496         public String serviceInterface;
1497         public String secureSettingName;
1498         public String secondarySettingName;
1499         public String xmlTag;
1500         public String bindPermission;
1501         public String settingsAction;
1502         public int clientLabel;
1503     }
1504 }
1505