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