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