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