OSDN Git Service

DO NOT MERGE Remove window obscurement information. am: c3c2ed94ff am: 96fe6421f6...
[android-x86/frameworks-base.git] / services / core / java / com / android / server / notification / ManagedServices.java
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 }