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.BroadcastReceiver;
     29 import android.content.ComponentName;
     30 import android.content.ContentResolver;
     31 import android.content.Context;
     32 import android.content.Intent;
     33 import android.content.IntentFilter;
     34 import android.content.ServiceConnection;
     35 import android.content.pm.ApplicationInfo;
     36 import android.content.pm.IPackageManager;
     37 import android.content.pm.PackageManager;
     38 import android.content.pm.PackageManager.NameNotFoundException;
     39 import android.content.pm.ResolveInfo;
     40 import android.content.pm.ServiceInfo;
     41 import android.content.pm.UserInfo;
     42 import android.database.ContentObserver;
     43 import android.net.Uri;
     44 import android.os.Binder;
     45 import android.os.Build;
     46 import android.os.Handler;
     47 import android.os.IBinder;
     48 import android.os.IInterface;
     49 import android.os.RemoteException;
     50 import android.os.ServiceManager;
     51 import android.os.UserHandle;
     52 import android.os.UserManager;
     53 import android.provider.Settings;
     54 import android.text.TextUtils;
     55 import android.util.ArraySet;
     56 import android.util.Log;
     57 import android.util.Slog;
     58 import android.util.SparseArray;
     59 
     60 import com.android.server.notification.NotificationManagerService.DumpFilter;
     61 
     62 import java.io.PrintWriter;
     63 import java.util.ArrayList;
     64 import java.util.Arrays;
     65 import java.util.HashSet;
     66 import java.util.List;
     67 import java.util.Objects;
     68 import java.util.Set;
     69 
     70 /**
     71  * Manages the lifecycle of application-provided services bound by system server.
     72  *
     73  * Services managed by this helper must have:
     74  *  - An associated system settings value with a list of enabled component names.
     75  *  - A well-known action for services to use in their intent-filter.
     76  *  - A system permission for services to require in order to ensure system has exclusive binding.
     77  *  - A settings page for user configuration of enabled services, and associated intent action.
     78  *  - A remote interface definition (aidl) provided by the service used for communication.
     79  */
     80 abstract public class ManagedServices {
     81     protected final String TAG = getClass().getSimpleName();
     82     protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     83 
     84     protected static final String ENABLED_SERVICES_SEPARATOR = ":";
     85 
     86     protected final Context mContext;
     87     protected final Object mMutex;
     88     private final UserProfiles mUserProfiles;
     89     private final SettingsObserver mSettingsObserver;
     90     private final IPackageManager mPm;
     91     private final Config mConfig;
     92     private ArraySet<String> mRestored;
     93 
     94     // contains connections to all connected services, including app services
     95     // and system services
     96     private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<ManagedServiceInfo>();
     97     // things that will be put into mServices as soon as they're ready
     98     private final ArrayList<String> mServicesBinding = new ArrayList<String>();
     99     // lists the component names of all enabled (and therefore potentially connected)
    100     // app services for current profiles.
    101     private ArraySet<ComponentName> mEnabledServicesForCurrentProfiles
    102             = new ArraySet<ComponentName>();
    103     // Just the packages from mEnabledServicesForCurrentProfiles
    104     private ArraySet<String> mEnabledServicesPackageNames = new ArraySet<String>();
    105     // List of packages in restored setting across all mUserProfiles, for quick
    106     // filtering upon package updates.
    107     private ArraySet<String> mRestoredPackages = new ArraySet<>();
    108     // List of enabled packages that have nevertheless asked not to be run
    109     private ArraySet<ComponentName> mSnoozingForCurrentProfiles = new ArraySet<>();
    110 
    111 
    112     // Kept to de-dupe user change events (experienced after boot, when we receive a settings and a
    113     // user change).
    114     private int[] mLastSeenProfileIds;
    115 
    116     private final BroadcastReceiver mRestoreReceiver;
    117 
    118     public ManagedServices(Context context, Handler handler, Object mutex,
    119             UserProfiles userProfiles) {
    120         mContext = context;
    121         mMutex = mutex;
    122         mUserProfiles = userProfiles;
    123         mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
    124         mConfig = getConfig();
    125         mSettingsObserver = new SettingsObserver(handler);
    126 
    127         mRestoreReceiver = new SettingRestoredReceiver();
    128         IntentFilter filter = new IntentFilter(Intent.ACTION_SETTING_RESTORED);
    129         context.registerReceiver(mRestoreReceiver, filter);
    130         rebuildRestoredPackages();
    131     }
    132 
    133     class SettingRestoredReceiver extends BroadcastReceiver {
    134         @Override
    135         public void onReceive(Context context, Intent intent) {
    136             if (Intent.ACTION_SETTING_RESTORED.equals(intent.getAction())) {
    137                 String element = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
    138                 if (Objects.equals(element, mConfig.secureSettingName)
    139                         || Objects.equals(element, mConfig.secondarySettingName)) {
    140                     String prevValue = intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE);
    141                     String newValue = intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE);
    142                     settingRestored(element, prevValue, newValue, getSendingUserId());
    143                 }
    144             }
    145         }
    146     }
    147 
    148     abstract protected Config getConfig();
    149 
    150     private String getCaption() {
    151         return mConfig.caption;
    152     }
    153 
    154     abstract protected IInterface asInterface(IBinder binder);
    155 
    156     abstract protected boolean checkType(IInterface service);
    157 
    158     abstract protected void onServiceAdded(ManagedServiceInfo info);
    159 
    160     protected List<ManagedServiceInfo> getServices() {
    161         synchronized (mMutex) {
    162             List<ManagedServiceInfo> services = new ArrayList<>(mServices);
    163             return services;
    164         }
    165     }
    166 
    167     protected void onServiceRemovedLocked(ManagedServiceInfo removed) { }
    168 
    169     private ManagedServiceInfo newServiceInfo(IInterface service,
    170             ComponentName component, int userid, boolean isSystem, ServiceConnection connection,
    171             int targetSdkVersion) {
    172         return new ManagedServiceInfo(service, component, userid, isSystem, connection,
    173                 targetSdkVersion);
    174     }
    175 
    176     public void onBootPhaseAppsCanStart() {
    177         mSettingsObserver.observe();
    178     }
    179 
    180     public void dump(PrintWriter pw, DumpFilter filter) {
    181         pw.println("    All " + getCaption() + "s (" + mEnabledServicesForCurrentProfiles.size()
    182                 + ") enabled for current profiles:");
    183         for (ComponentName cmpt : mEnabledServicesForCurrentProfiles) {
    184             if (filter != null && !filter.matches(cmpt)) continue;
    185             pw.println("      " + cmpt);
    186         }
    187 
    188         pw.println("    Live " + getCaption() + "s (" + mServices.size() + "):");
    189         for (ManagedServiceInfo info : mServices) {
    190             if (filter != null && !filter.matches(info.component)) continue;
    191             pw.println("      " + info.component
    192                     + " (user " + info.userid + "): " + info.service
    193                     + (info.isSystem?" SYSTEM":"")
    194                     + (info.isGuest(this)?" GUEST":""));
    195         }
    196 
    197         pw.println("    Snoozed " + getCaption() + "s (" +
    198                 mSnoozingForCurrentProfiles.size() + "):");
    199         for (ComponentName name : mSnoozingForCurrentProfiles) {
    200             pw.println("      " + name.flattenToShortString());
    201         }
    202     }
    203 
    204     // By convention, restored settings are replicated to another settings
    205     // entry, named similarly but with a disambiguation suffix.
    206     public static String restoredSettingName(String setting) {
    207         return setting + ":restored";
    208     }
    209 
    210     // The OS has done a restore of this service's saved state.  We clone it to the
    211     // 'restored' reserve, and then once we return and the actual write to settings is
    212     // performed, our observer will do the work of maintaining the restored vs live
    213     // settings data.
    214     public void settingRestored(String element, String oldValue, String newValue, int userid) {
    215         if (DEBUG) Slog.d(TAG, "Restored managed service setting: " + element
    216                 + " ovalue=" + oldValue + " nvalue=" + newValue);
    217         if (mConfig.secureSettingName.equals(element) ||
    218                 mConfig.secondarySettingName.equals(element)) {
    219             if (element != null) {
    220                 Settings.Secure.putStringForUser(mContext.getContentResolver(),
    221                         restoredSettingName(element),
    222                         newValue,
    223                         userid);
    224                 if (mConfig.secureSettingName.equals(element)) {
    225                     updateSettingsAccordingToInstalledServices(element, userid);
    226                 }
    227                 rebuildRestoredPackages();
    228             }
    229         }
    230     }
    231 
    232     public boolean isComponentEnabledForPackage(String pkg) {
    233         return mEnabledServicesPackageNames.contains(pkg);
    234     }
    235 
    236     public void onPackagesChanged(boolean removingPackage, String[] pkgList) {
    237         if (DEBUG) Slog.d(TAG, "onPackagesChanged removingPackage=" + removingPackage
    238                 + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList))
    239                 + " mEnabledServicesPackageNames=" + mEnabledServicesPackageNames);
    240         boolean anyServicesInvolved = false;
    241 
    242         if (pkgList != null && (pkgList.length > 0)) {
    243             for (String pkgName : pkgList) {
    244                 if (mEnabledServicesPackageNames.contains(pkgName) ||
    245                         mRestoredPackages.contains(pkgName)) {
    246                     anyServicesInvolved = true;
    247                 }
    248             }
    249         }
    250 
    251         if (anyServicesInvolved) {
    252             // if we're not replacing a package, clean up orphaned bits
    253             if (removingPackage) {
    254                 updateSettingsAccordingToInstalledServices();
    255                 rebuildRestoredPackages();
    256             }
    257             // make sure we're still bound to any of our services who may have just upgraded
    258             rebindServices(false);
    259         }
    260     }
    261 
    262     public void onUserSwitched(int user) {
    263         if (DEBUG) Slog.d(TAG, "onUserSwitched u=" + user);
    264         rebuildRestoredPackages();
    265         if (Arrays.equals(mLastSeenProfileIds, mUserProfiles.getCurrentProfileIds())) {
    266             if (DEBUG) Slog.d(TAG, "Current profile IDs didn't change, skipping rebindServices().");
    267             return;
    268         }
    269         rebindServices(true);
    270     }
    271 
    272     public void onUserUnlocked(int user) {
    273         if (DEBUG) Slog.d(TAG, "onUserUnlocked u=" + user);
    274         rebuildRestoredPackages();
    275         rebindServices(false);
    276     }
    277 
    278     public ManagedServiceInfo getServiceFromTokenLocked(IInterface service) {
    279         if (service == null) {
    280             return null;
    281         }
    282         final IBinder token = service.asBinder();
    283         final int N = mServices.size();
    284         for (int i = 0; i < N; i++) {
    285             final ManagedServiceInfo info = mServices.get(i);
    286             if (info.service.asBinder() == token) return info;
    287         }
    288         return null;
    289     }
    290 
    291     public ManagedServiceInfo checkServiceTokenLocked(IInterface service) {
    292         checkNotNull(service);
    293         ManagedServiceInfo info = getServiceFromTokenLocked(service);
    294         if (info != null) {
    295             return info;
    296         }
    297         throw new SecurityException("Disallowed call from unknown " + getCaption() + ": "
    298                 + service);
    299     }
    300 
    301     public void unregisterService(IInterface service, int userid) {
    302         checkNotNull(service);
    303         // no need to check permissions; if your service binder is in the list,
    304         // that's proof that you had permission to add it in the first place
    305         unregisterServiceImpl(service, userid);
    306     }
    307 
    308     public void registerService(IInterface service, ComponentName component, int userid) {
    309         checkNotNull(service);
    310         ManagedServiceInfo info = registerServiceImpl(service, component, userid);
    311         if (info != null) {
    312             onServiceAdded(info);
    313         }
    314     }
    315 
    316     /**
    317      * Add a service to our callbacks. The lifecycle of this service is managed externally,
    318      * but unlike a system service, it should not be considered privledged.
    319      * */
    320     public void registerGuestService(ManagedServiceInfo guest) {
    321         checkNotNull(guest.service);
    322         if (!checkType(guest.service)) {
    323             throw new IllegalArgumentException();
    324         }
    325         if (registerServiceImpl(guest) != null) {
    326             onServiceAdded(guest);
    327         }
    328     }
    329 
    330     public void setComponentState(ComponentName component, boolean enabled) {
    331         boolean previous = !mSnoozingForCurrentProfiles.contains(component);
    332         if (previous == enabled) {
    333             return;
    334         }
    335 
    336         if (enabled) {
    337             mSnoozingForCurrentProfiles.remove(component);
    338         } else {
    339             mSnoozingForCurrentProfiles.add(component);
    340         }
    341 
    342         // State changed
    343         if (DEBUG) {
    344             Slog.d(TAG, ((enabled) ? "Enabling " : "Disabling ") + "component " +
    345                     component.flattenToShortString());
    346         }
    347 
    348 
    349         synchronized (mMutex) {
    350             final int[] userIds = mUserProfiles.getCurrentProfileIds();
    351 
    352             for (int userId : userIds) {
    353                 if (enabled) {
    354                     registerServiceLocked(component, userId);
    355                 } else {
    356                     unregisterServiceLocked(component, userId);
    357                 }
    358             }
    359         }
    360     }
    361 
    362     private void rebuildRestoredPackages() {
    363         mRestoredPackages.clear();
    364         String secureSettingName = restoredSettingName(mConfig.secureSettingName);
    365         String secondarySettingName = mConfig.secondarySettingName == null
    366                 ? null : restoredSettingName(mConfig.secondarySettingName);
    367         int[] userIds = mUserProfiles.getCurrentProfileIds();
    368         final int N = userIds.length;
    369         for (int i = 0; i < N; ++i) {
    370             ArraySet<ComponentName> names =
    371                     loadComponentNamesFromSetting(secureSettingName, userIds[i]);
    372             if (secondarySettingName != null) {
    373                 names.addAll(loadComponentNamesFromSetting(secondarySettingName, userIds[i]));
    374             }
    375             for (ComponentName name : names) {
    376                 mRestoredPackages.add(name.getPackageName());
    377             }
    378         }
    379     }
    380 
    381 
    382     protected @NonNull ArraySet<ComponentName> loadComponentNamesFromSetting(String settingName,
    383             int userId) {
    384         final ContentResolver cr = mContext.getContentResolver();
    385         String settingValue = Settings.Secure.getStringForUser(
    386             cr,
    387             settingName,
    388             userId);
    389         if (TextUtils.isEmpty(settingValue))
    390             return new ArraySet<>();
    391         String[] restored = settingValue.split(ENABLED_SERVICES_SEPARATOR);
    392         ArraySet<ComponentName> result = new ArraySet<>(restored.length);
    393         for (int i = 0; i < restored.length; i++) {
    394             ComponentName value = ComponentName.unflattenFromString(restored[i]);
    395             if (null != value) {
    396                 result.add(value);
    397             }
    398         }
    399         return result;
    400     }
    401 
    402     private void storeComponentsToSetting(Set<ComponentName> components,
    403                                           String settingName,
    404                                           int userId) {
    405         String[] componentNames = null;
    406         if (null != components) {
    407             componentNames = new String[components.size()];
    408             int index = 0;
    409             for (ComponentName c: components) {
    410                 componentNames[index++] = c.flattenToString();
    411             }
    412         }
    413         final String value = (componentNames == null) ? "" :
    414                 TextUtils.join(ENABLED_SERVICES_SEPARATOR, componentNames);
    415         final ContentResolver cr = mContext.getContentResolver();
    416         Settings.Secure.putStringForUser(
    417             cr,
    418             settingName,
    419             value,
    420             userId);
    421     }
    422 
    423     /**
    424      * Remove access for any services that no longer exist.
    425      */
    426     private void updateSettingsAccordingToInstalledServices() {
    427         int[] userIds = mUserProfiles.getCurrentProfileIds();
    428         final int N = userIds.length;
    429         for (int i = 0; i < N; ++i) {
    430             updateSettingsAccordingToInstalledServices(mConfig.secureSettingName, userIds[i]);
    431             if (mConfig.secondarySettingName != null) {
    432                 updateSettingsAccordingToInstalledServices(
    433                         mConfig.secondarySettingName, userIds[i]);
    434             }
    435         }
    436         rebuildRestoredPackages();
    437     }
    438 
    439     protected Set<ComponentName> queryPackageForServices(String packageName, int userId) {
    440         Set<ComponentName> installed = new ArraySet<>();
    441         final PackageManager pm = mContext.getPackageManager();
    442         Intent queryIntent = new Intent(mConfig.serviceInterface);
    443         if (!TextUtils.isEmpty(packageName)) {
    444             queryIntent.setPackage(packageName);
    445         }
    446         List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
    447                 queryIntent,
    448                 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
    449                 userId);
    450         if (DEBUG)
    451             Slog.v(TAG, mConfig.serviceInterface + " services: " + installedServices);
    452         if (installedServices != null) {
    453             for (int i = 0, count = installedServices.size(); i < count; i++) {
    454                 ResolveInfo resolveInfo = installedServices.get(i);
    455                 ServiceInfo info = resolveInfo.serviceInfo;
    456 
    457                 ComponentName component = new ComponentName(info.packageName, info.name);
    458                 if (!mConfig.bindPermission.equals(info.permission)) {
    459                     Slog.w(TAG, "Skipping " + getCaption() + " service "
    460                         + info.packageName + "/" + info.name
    461                         + ": it does not require the permission "
    462                         + mConfig.bindPermission);
    463                     continue;
    464                 }
    465                 installed.add(component);
    466             }
    467         }
    468         return installed;
    469     }
    470 
    471     private void updateSettingsAccordingToInstalledServices(String setting, int userId) {
    472         boolean restoredChanged = false;
    473         boolean currentChanged = false;
    474         Set<ComponentName> restored =
    475                 loadComponentNamesFromSetting(restoredSettingName(setting), userId);
    476         Set<ComponentName> current =
    477                 loadComponentNamesFromSetting(setting, userId);
    478         // Load all services for all packages.
    479         Set<ComponentName> installed = queryPackageForServices(null, userId);
    480 
    481         ArraySet<ComponentName> retained = new ArraySet<>();
    482 
    483         for (ComponentName component : installed) {
    484             if (null != restored) {
    485                 boolean wasRestored = restored.remove(component);
    486                 if (wasRestored) {
    487                     // Freshly installed package has service that was mentioned in restored setting.
    488                     if (DEBUG)
    489                         Slog.v(TAG, "Restoring " + component + " for user " + userId);
    490                     restoredChanged = true;
    491                     currentChanged = true;
    492                     retained.add(component);
    493                     continue;
    494                 }
    495             }
    496 
    497             if (null != current) {
    498                 if (current.contains(component))
    499                     retained.add(component);
    500             }
    501         }
    502 
    503         currentChanged |= ((current == null ? 0 : current.size()) != retained.size());
    504 
    505         if (currentChanged) {
    506             if (DEBUG) Slog.v(TAG, "List of  " + getCaption() + " services was updated " + current);
    507             storeComponentsToSetting(retained, setting, userId);
    508         }
    509 
    510         if (restoredChanged) {
    511             if (DEBUG) Slog.v(TAG,
    512                     "List of  " + getCaption() + " restored services was updated " + restored);
    513             storeComponentsToSetting(restored, restoredSettingName(setting), userId);
    514         }
    515     }
    516 
    517     /**
    518      * Called whenever packages change, the user switches, or the secure setting
    519      * is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
    520      */
    521     private void rebindServices(boolean forceRebind) {
    522         if (DEBUG) Slog.d(TAG, "rebindServices");
    523         final int[] userIds = mUserProfiles.getCurrentProfileIds();
    524         final int nUserIds = userIds.length;
    525 
    526         final SparseArray<ArraySet<ComponentName>> componentsByUser = new SparseArray<>();
    527 
    528         for (int i = 0; i < nUserIds; ++i) {
    529             componentsByUser.put(userIds[i],
    530                     loadComponentNamesFromSetting(mConfig.secureSettingName, userIds[i]));
    531             if (mConfig.secondarySettingName != null) {
    532                 componentsByUser.get(userIds[i]).addAll(
    533                         loadComponentNamesFromSetting(mConfig.secondarySettingName, userIds[i]));
    534             }
    535         }
    536 
    537         final ArrayList<ManagedServiceInfo> removableBoundServices = new ArrayList<>();
    538         final SparseArray<Set<ComponentName>> toAdd = new SparseArray<>();
    539 
    540         synchronized (mMutex) {
    541             // Rebind to non-system services if user switched
    542             for (ManagedServiceInfo service : mServices) {
    543                 if (!service.isSystem && !service.isGuest(this)) {
    544                     removableBoundServices.add(service);
    545                 }
    546             }
    547 
    548             mEnabledServicesForCurrentProfiles.clear();
    549             mEnabledServicesPackageNames.clear();
    550 
    551             for (int i = 0; i < nUserIds; ++i) {
    552                 // decode the list of components
    553                 final ArraySet<ComponentName> userComponents = componentsByUser.get(userIds[i]);
    554                 if (null == userComponents) {
    555                     toAdd.put(userIds[i], new ArraySet<ComponentName>());
    556                     continue;
    557                 }
    558 
    559                 final Set<ComponentName> add = new HashSet<>(userComponents);
    560                 add.removeAll(mSnoozingForCurrentProfiles);
    561 
    562                 toAdd.put(userIds[i], add);
    563 
    564                 mEnabledServicesForCurrentProfiles.addAll(userComponents);
    565 
    566                 for (int j = 0; j < userComponents.size(); j++) {
    567                     final ComponentName component = userComponents.valueAt(j);
    568                     mEnabledServicesPackageNames.add(component.getPackageName());
    569                 }
    570             }
    571         }
    572 
    573         for (ManagedServiceInfo info : removableBoundServices) {
    574             final ComponentName component = info.component;
    575             final int oldUser = info.userid;
    576             final Set<ComponentName> allowedComponents = toAdd.get(info.userid);
    577             if (allowedComponents != null) {
    578                 if (allowedComponents.contains(component) && !forceRebind) {
    579                     // Already bound, don't need to bind again.
    580                     allowedComponents.remove(component);
    581                 } else {
    582                     // No longer allowed to be bound, or must rebind.
    583                     Slog.v(TAG, "disabling " + getCaption() + " for user "
    584                             + oldUser + ": " + component);
    585                     unregisterService(component, oldUser);
    586                 }
    587             }
    588         }
    589 
    590         for (int i = 0; i < nUserIds; ++i) {
    591             final Set<ComponentName> add = toAdd.get(userIds[i]);
    592             for (ComponentName component : add) {
    593                 try {
    594                     ServiceInfo info = mPm.getServiceInfo(component,
    595                             PackageManager.MATCH_DIRECT_BOOT_AWARE
    596                                     | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userIds[i]);
    597                     if (info == null || !mConfig.bindPermission.equals(info.permission)) {
    598                         Slog.w(TAG, "Skipping " + getCaption() + " service " + component
    599                                 + ": it does not require the permission " + mConfig.bindPermission);
    600                         continue;
    601                     }
    602                     Slog.v(TAG,
    603                             "enabling " + getCaption() + " for " + userIds[i] + ": " + component);
    604                     registerService(component, userIds[i]);
    605                 } catch (RemoteException e) {
    606                     e.rethrowFromSystemServer();
    607                 }
    608             }
    609         }
    610 
    611         mLastSeenProfileIds = userIds;
    612     }
    613 
    614     /**
    615      * Version of registerService that takes the name of a service component to bind to.
    616      */
    617     private void registerService(final ComponentName name, final int userid) {
    618         synchronized (mMutex) {
    619             registerServiceLocked(name, userid);
    620         }
    621     }
    622 
    623     /**
    624      * Inject a system service into the management list.
    625      */
    626     public void registerSystemService(final ComponentName name, final int userid) {
    627         synchronized (mMutex) {
    628             registerServiceLocked(name, userid, true /* isSystem */);
    629         }
    630     }
    631 
    632     private void registerServiceLocked(final ComponentName name, final int userid) {
    633         registerServiceLocked(name, userid, false /* isSystem */);
    634     }
    635 
    636     private void registerServiceLocked(final ComponentName name, final int userid,
    637             final boolean isSystem) {
    638         if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid);
    639 
    640         final String servicesBindingTag = name.toString() + "/" + userid;
    641         if (mServicesBinding.contains(servicesBindingTag)) {
    642             // stop registering this thing already! we're working on it
    643             return;
    644         }
    645         mServicesBinding.add(servicesBindingTag);
    646 
    647         final int N = mServices.size();
    648         for (int i = N - 1; i >= 0; i--) {
    649             final ManagedServiceInfo info = mServices.get(i);
    650             if (name.equals(info.component)
    651                 && info.userid == userid) {
    652                 // cut old connections
    653                 if (DEBUG) Slog.v(TAG, "    disconnecting old " + getCaption() + ": "
    654                     + info.service);
    655                 removeServiceLocked(i);
    656                 if (info.connection != null) {
    657                     mContext.unbindService(info.connection);
    658                 }
    659             }
    660         }
    661 
    662         Intent intent = new Intent(mConfig.serviceInterface);
    663         intent.setComponent(name);
    664 
    665         intent.putExtra(Intent.EXTRA_CLIENT_LABEL, mConfig.clientLabel);
    666 
    667         final PendingIntent pendingIntent = PendingIntent.getActivity(
    668             mContext, 0, new Intent(mConfig.settingsAction), 0);
    669         intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent);
    670 
    671         ApplicationInfo appInfo = null;
    672         try {
    673             appInfo = mContext.getPackageManager().getApplicationInfo(
    674                 name.getPackageName(), 0);
    675         } catch (NameNotFoundException e) {
    676             // Ignore if the package doesn't exist we won't be able to bind to the service.
    677         }
    678         final int targetSdkVersion =
    679             appInfo != null ? appInfo.targetSdkVersion : Build.VERSION_CODES.BASE;
    680 
    681         try {
    682             if (DEBUG) Slog.v(TAG, "binding: " + intent);
    683             ServiceConnection serviceConnection = new ServiceConnection() {
    684                 IInterface mService;
    685 
    686                 @Override
    687                 public void onServiceConnected(ComponentName name, IBinder binder) {
    688                     boolean added = false;
    689                     ManagedServiceInfo info = null;
    690                     synchronized (mMutex) {
    691                         mServicesBinding.remove(servicesBindingTag);
    692                         try {
    693                             mService = asInterface(binder);
    694                             info = newServiceInfo(mService, name,
    695                                 userid, isSystem, this, targetSdkVersion);
    696                             binder.linkToDeath(info, 0);
    697                             added = mServices.add(info);
    698                         } catch (RemoteException e) {
    699                             // already dead
    700                         }
    701                     }
    702                     if (added) {
    703                         onServiceAdded(info);
    704                     }
    705                 }
    706 
    707                 @Override
    708                 public void onServiceDisconnected(ComponentName name) {
    709                     Slog.v(TAG, getCaption() + " connection lost: " + name);
    710                 }
    711             };
    712             if (!mContext.bindServiceAsUser(intent,
    713                 serviceConnection,
    714                 BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT,
    715                 new UserHandle(userid))) {
    716                 mServicesBinding.remove(servicesBindingTag);
    717                 Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent);
    718                 return;
    719             }
    720         } catch (SecurityException ex) {
    721             Slog.e(TAG, "Unable to bind " + getCaption() + " service: " + intent, ex);
    722             return;
    723         }
    724     }
    725 
    726     /**
    727      * Remove a service for the given user by ComponentName
    728      */
    729     private void unregisterService(ComponentName name, int userid) {
    730         synchronized (mMutex) {
    731             unregisterServiceLocked(name, userid);
    732         }
    733     }
    734 
    735     private void unregisterServiceLocked(ComponentName name, int userid) {
    736         final int N = mServices.size();
    737         for (int i = N - 1; i >= 0; i--) {
    738             final ManagedServiceInfo info = mServices.get(i);
    739             if (name.equals(info.component)
    740                 && info.userid == userid) {
    741                 removeServiceLocked(i);
    742                 if (info.connection != null) {
    743                     try {
    744                         mContext.unbindService(info.connection);
    745                     } catch (IllegalArgumentException ex) {
    746                         // something happened to the service: we think we have a connection
    747                         // but it's bogus.
    748                         Slog.e(TAG, getCaption() + " " + name + " could not be unbound: " + ex);
    749                     }
    750                 }
    751             }
    752         }
    753     }
    754 
    755     /**
    756      * Removes a service from the list but does not unbind
    757      *
    758      * @return the removed service.
    759      */
    760     private ManagedServiceInfo removeServiceImpl(IInterface service, final int userid) {
    761         if (DEBUG) Slog.d(TAG, "removeServiceImpl service=" + service + " u=" + userid);
    762         ManagedServiceInfo serviceInfo = null;
    763         synchronized (mMutex) {
    764             final int N = mServices.size();
    765             for (int i = N - 1; i >= 0; i--) {
    766                 final ManagedServiceInfo info = mServices.get(i);
    767                 if (info.service.asBinder() == service.asBinder()
    768                         && info.userid == userid) {
    769                     if (DEBUG) Slog.d(TAG, "Removing active service " + info.component);
    770                     serviceInfo = removeServiceLocked(i);
    771                 }
    772             }
    773         }
    774         return serviceInfo;
    775     }
    776 
    777     private ManagedServiceInfo removeServiceLocked(int i) {
    778         final ManagedServiceInfo info = mServices.remove(i);
    779         onServiceRemovedLocked(info);
    780         return info;
    781     }
    782 
    783     private void checkNotNull(IInterface service) {
    784         if (service == null) {
    785             throw new IllegalArgumentException(getCaption() + " must not be null");
    786         }
    787     }
    788 
    789     private ManagedServiceInfo registerServiceImpl(final IInterface service,
    790             final ComponentName component, final int userid) {
    791         ManagedServiceInfo info = newServiceInfo(service, component, userid,
    792                 true /*isSystem*/, null /*connection*/, Build.VERSION_CODES.LOLLIPOP);
    793         return registerServiceImpl(info);
    794     }
    795 
    796     private ManagedServiceInfo registerServiceImpl(ManagedServiceInfo info) {
    797         synchronized (mMutex) {
    798             try {
    799                 info.service.asBinder().linkToDeath(info, 0);
    800                 mServices.add(info);
    801                 return info;
    802             } catch (RemoteException e) {
    803                 // already dead
    804             }
    805         }
    806         return null;
    807     }
    808 
    809     /**
    810      * Removes a service from the list and unbinds.
    811      */
    812     private void unregisterServiceImpl(IInterface service, int userid) {
    813         ManagedServiceInfo info = removeServiceImpl(service, userid);
    814         if (info != null && info.connection != null && !info.isGuest(this)) {
    815             mContext.unbindService(info.connection);
    816         }
    817     }
    818 
    819     private class SettingsObserver extends ContentObserver {
    820         private final Uri mSecureSettingsUri = Settings.Secure.getUriFor(mConfig.secureSettingName);
    821         private final Uri mSecondarySettingsUri;
    822 
    823         private SettingsObserver(Handler handler) {
    824             super(handler);
    825             if (mConfig.secondarySettingName != null) {
    826                 mSecondarySettingsUri = Settings.Secure.getUriFor(mConfig.secondarySettingName);
    827             } else {
    828                 mSecondarySettingsUri = null;
    829             }
    830         }
    831 
    832         private void observe() {
    833             ContentResolver resolver = mContext.getContentResolver();
    834             resolver.registerContentObserver(mSecureSettingsUri,
    835                     false, this, UserHandle.USER_ALL);
    836             if (mSecondarySettingsUri != null) {
    837                 resolver.registerContentObserver(mSecondarySettingsUri,
    838                         false, this, UserHandle.USER_ALL);
    839             }
    840             update(null);
    841         }
    842 
    843         @Override
    844         public void onChange(boolean selfChange, Uri uri) {
    845             update(uri);
    846         }
    847 
    848         private void update(Uri uri) {
    849             if (uri == null || mSecureSettingsUri.equals(uri)
    850                     || uri.equals(mSecondarySettingsUri)) {
    851                 if (DEBUG) Slog.d(TAG, "Setting changed: uri=" + uri);
    852                 rebindServices(false);
    853                 rebuildRestoredPackages();
    854             }
    855         }
    856     }
    857 
    858     public class ManagedServiceInfo implements IBinder.DeathRecipient {
    859         public IInterface service;
    860         public ComponentName component;
    861         public int userid;
    862         public boolean isSystem;
    863         public ServiceConnection connection;
    864         public int targetSdkVersion;
    865 
    866         public ManagedServiceInfo(IInterface service, ComponentName component,
    867                 int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion) {
    868             this.service = service;
    869             this.component = component;
    870             this.userid = userid;
    871             this.isSystem = isSystem;
    872             this.connection = connection;
    873             this.targetSdkVersion = targetSdkVersion;
    874         }
    875 
    876         public boolean isGuest(ManagedServices host) {
    877             return ManagedServices.this != host;
    878         }
    879 
    880         public ManagedServices getOwner() {
    881             return ManagedServices.this;
    882         }
    883 
    884         @Override
    885         public String toString() {
    886             return new StringBuilder("ManagedServiceInfo[")
    887                     .append("component=").append(component)
    888                     .append(",userid=").append(userid)
    889                     .append(",isSystem=").append(isSystem)
    890                     .append(",targetSdkVersion=").append(targetSdkVersion)
    891                     .append(",connection=").append(connection == null ? null : "<connection>")
    892                     .append(",service=").append(service)
    893                     .append(']').toString();
    894         }
    895 
    896         public boolean enabledAndUserMatches(int nid) {
    897             if (!isEnabledForCurrentProfiles()) {
    898                 return false;
    899             }
    900             if (this.userid == UserHandle.USER_ALL) return true;
    901             if (this.isSystem) return true;
    902             if (nid == UserHandle.USER_ALL || nid == this.userid) return true;
    903             return supportsProfiles()
    904                     && mUserProfiles.isCurrentProfile(nid)
    905                     && isPermittedForProfile(nid);
    906         }
    907 
    908         public boolean supportsProfiles() {
    909             return targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP;
    910         }
    911 
    912         @Override
    913         public void binderDied() {
    914             if (DEBUG) Slog.d(TAG, "binderDied");
    915             // Remove the service, but don't unbind from the service. The system will bring the
    916             // service back up, and the onServiceConnected handler will read the service with the
    917             // new binding. If this isn't a bound service, and is just a registered
    918             // service, just removing it from the list is all we need to do anyway.
    919             removeServiceImpl(this.service, this.userid);
    920         }
    921 
    922         /** convenience method for looking in mEnabledServicesForCurrentProfiles */
    923         public boolean isEnabledForCurrentProfiles() {
    924             if (this.isSystem) return true;
    925             if (this.connection == null) return false;
    926             return mEnabledServicesForCurrentProfiles.contains(this.component);
    927         }
    928 
    929         /**
    930          * Returns true if this service is allowed to receive events for the given userId. A
    931          * managed profile owner can disallow non-system services running outside of the profile
    932          * from receiving events from the profile.
    933          */
    934         public boolean isPermittedForProfile(int userId) {
    935             if (!mUserProfiles.isManagedProfile(userId)) {
    936                 return true;
    937             }
    938             DevicePolicyManager dpm =
    939                     (DevicePolicyManager) mContext.getSystemService(DEVICE_POLICY_SERVICE);
    940             final long identity = Binder.clearCallingIdentity();
    941             try {
    942                 return dpm.isNotificationListenerServicePermitted(
    943                         component.getPackageName(), userId);
    944             } finally {
    945                 Binder.restoreCallingIdentity(identity);
    946             }
    947         }
    948     }
    949 
    950     /** convenience method for looking in mEnabledServicesForCurrentProfiles */
    951     public boolean isComponentEnabledForCurrentProfiles(ComponentName component) {
    952         return mEnabledServicesForCurrentProfiles.contains(component);
    953     }
    954 
    955     public static class UserProfiles {
    956         // Profiles of the current user.
    957         private final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>();
    958 
    959         public void updateCache(@NonNull Context context) {
    960             UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
    961             if (userManager != null) {
    962                 int currentUserId = ActivityManager.getCurrentUser();
    963                 List<UserInfo> profiles = userManager.getProfiles(currentUserId);
    964                 synchronized (mCurrentProfiles) {
    965                     mCurrentProfiles.clear();
    966                     for (UserInfo user : profiles) {
    967                         mCurrentProfiles.put(user.id, user);
    968                     }
    969                 }
    970             }
    971         }
    972 
    973         public int[] getCurrentProfileIds() {
    974             synchronized (mCurrentProfiles) {
    975                 int[] users = new int[mCurrentProfiles.size()];
    976                 final int N = mCurrentProfiles.size();
    977                 for (int i = 0; i < N; ++i) {
    978                     users[i] = mCurrentProfiles.keyAt(i);
    979                 }
    980                 return users;
    981             }
    982         }
    983 
    984         public boolean isCurrentProfile(int userId) {
    985             synchronized (mCurrentProfiles) {
    986                 return mCurrentProfiles.get(userId) != null;
    987             }
    988         }
    989 
    990         public boolean isManagedProfile(int userId) {
    991             synchronized (mCurrentProfiles) {
    992                 UserInfo user = mCurrentProfiles.get(userId);
    993                 return user != null && user.isManagedProfile();
    994             }
    995         }
    996     }
    997 
    998     public static class Config {
    999         public String caption;
   1000         public String serviceInterface;
   1001         public String secureSettingName;
   1002         public String secondarySettingName;
   1003         public String bindPermission;
   1004         public String settingsAction;
   1005         public int clientLabel;
   1006     }
   1007 }
   1008