2 * Copyright (c) 2014, The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server.notification;
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;
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;
60 import com.android.server.notification.NotificationManagerService.DumpFilter;
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;
71 * Manages the lifecycle of application-provided services bound by system server.
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.
80 abstract public class ManagedServices {
81 protected final String TAG = getClass().getSimpleName();
82 protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
84 protected static final String ENABLED_SERVICES_SEPARATOR = ":";
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;
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<>();
112 // Kept to de-dupe user change events (experienced after boot, when we receive a settings and a
114 private int[] mLastSeenProfileIds;
116 private final BroadcastReceiver mRestoreReceiver;
118 public ManagedServices(Context context, Handler handler, Object mutex,
119 UserProfiles userProfiles) {
122 mUserProfiles = userProfiles;
123 mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
124 mConfig = getConfig();
125 mSettingsObserver = new SettingsObserver(handler);
127 mRestoreReceiver = new SettingRestoredReceiver();
128 IntentFilter filter = new IntentFilter(Intent.ACTION_SETTING_RESTORED);
129 context.registerReceiver(mRestoreReceiver, filter);
130 rebuildRestoredPackages();
133 class SettingRestoredReceiver extends BroadcastReceiver {
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 int restoredFromSdkInt = intent.getIntExtra(
143 Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT, 0);
144 if (restoredFromSdkInt < Build.VERSION_CODES.O) {
145 // automatic system grants were added in O, so append the approved apps
146 // rather than wiping out the setting
147 if (!TextUtils.isEmpty(prevValue)) {
148 if (!TextUtils.isEmpty(newValue)) {
149 newValue = newValue + ENABLED_SERVICES_SEPARATOR + prevValue;
151 newValue = prevValue;
155 settingRestored(element, prevValue, newValue, getSendingUserId());
161 abstract protected Config getConfig();
163 private String getCaption() {
164 return mConfig.caption;
167 abstract protected IInterface asInterface(IBinder binder);
169 abstract protected boolean checkType(IInterface service);
171 abstract protected void onServiceAdded(ManagedServiceInfo info);
173 protected List<ManagedServiceInfo> getServices() {
174 synchronized (mMutex) {
175 List<ManagedServiceInfo> services = new ArrayList<>(mServices);
180 protected void onServiceRemovedLocked(ManagedServiceInfo removed) { }
182 private ManagedServiceInfo newServiceInfo(IInterface service,
183 ComponentName component, int userid, boolean isSystem, ServiceConnection connection,
184 int targetSdkVersion) {
185 return new ManagedServiceInfo(service, component, userid, isSystem, connection,
189 public void onBootPhaseAppsCanStart() {
190 mSettingsObserver.observe();
193 public void dump(PrintWriter pw, DumpFilter filter) {
194 pw.println(" All " + getCaption() + "s (" + mEnabledServicesForCurrentProfiles.size()
195 + ") enabled for current profiles:");
196 for (ComponentName cmpt : mEnabledServicesForCurrentProfiles) {
197 if (filter != null && !filter.matches(cmpt)) continue;
198 pw.println(" " + cmpt);
201 pw.println(" Live " + getCaption() + "s (" + mServices.size() + "):");
202 for (ManagedServiceInfo info : mServices) {
203 if (filter != null && !filter.matches(info.component)) continue;
204 pw.println(" " + info.component
205 + " (user " + info.userid + "): " + info.service
206 + (info.isSystem?" SYSTEM":"")
207 + (info.isGuest(this)?" GUEST":""));
210 pw.println(" Snoozed " + getCaption() + "s (" +
211 mSnoozingForCurrentProfiles.size() + "):");
212 for (ComponentName name : mSnoozingForCurrentProfiles) {
213 pw.println(" " + name.flattenToShortString());
217 // By convention, restored settings are replicated to another settings
218 // entry, named similarly but with a disambiguation suffix.
219 public static String restoredSettingName(String setting) {
220 return setting + ":restored";
223 // The OS has done a restore of this service's saved state. We clone it to the
224 // 'restored' reserve, and then once we return and the actual write to settings is
225 // performed, our observer will do the work of maintaining the restored vs live
227 public void settingRestored(String element, String oldValue, String newValue, int userid) {
228 if (DEBUG) Slog.d(TAG, "Restored managed service setting: " + element
229 + " ovalue=" + oldValue + " nvalue=" + newValue);
230 if (mConfig.secureSettingName.equals(element) ||
231 mConfig.secondarySettingName.equals(element)) {
232 if (element != null) {
233 Settings.Secure.putStringForUser(mContext.getContentResolver(),
234 restoredSettingName(element),
237 if (mConfig.secureSettingName.equals(element)) {
238 updateSettingsAccordingToInstalledServices(element, userid);
240 rebuildRestoredPackages();
245 public boolean isComponentEnabledForPackage(String pkg) {
246 return mEnabledServicesPackageNames.contains(pkg);
249 public void onPackagesChanged(boolean removingPackage, String[] pkgList) {
250 if (DEBUG) Slog.d(TAG, "onPackagesChanged removingPackage=" + removingPackage
251 + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList))
252 + " mEnabledServicesPackageNames=" + mEnabledServicesPackageNames);
253 boolean anyServicesInvolved = false;
255 if (pkgList != null && (pkgList.length > 0)) {
256 for (String pkgName : pkgList) {
257 if (mEnabledServicesPackageNames.contains(pkgName) ||
258 mRestoredPackages.contains(pkgName)) {
259 anyServicesInvolved = true;
264 if (anyServicesInvolved) {
265 // if we're not replacing a package, clean up orphaned bits
266 if (removingPackage) {
267 updateSettingsAccordingToInstalledServices();
268 rebuildRestoredPackages();
270 // make sure we're still bound to any of our services who may have just upgraded
271 rebindServices(false);
275 public void onUserSwitched(int user) {
276 if (DEBUG) Slog.d(TAG, "onUserSwitched u=" + user);
277 rebuildRestoredPackages();
278 if (Arrays.equals(mLastSeenProfileIds, mUserProfiles.getCurrentProfileIds())) {
279 if (DEBUG) Slog.d(TAG, "Current profile IDs didn't change, skipping rebindServices().");
282 rebindServices(true);
285 public void onUserUnlocked(int user) {
286 if (DEBUG) Slog.d(TAG, "onUserUnlocked u=" + user);
287 rebuildRestoredPackages();
288 rebindServices(false);
291 public ManagedServiceInfo getServiceFromTokenLocked(IInterface service) {
292 if (service == null) {
295 final IBinder token = service.asBinder();
296 final int N = mServices.size();
297 for (int i = 0; i < N; i++) {
298 final ManagedServiceInfo info = mServices.get(i);
299 if (info.service.asBinder() == token) return info;
304 public ManagedServiceInfo checkServiceTokenLocked(IInterface service) {
305 checkNotNull(service);
306 ManagedServiceInfo info = getServiceFromTokenLocked(service);
310 throw new SecurityException("Disallowed call from unknown " + getCaption() + ": "
314 public void unregisterService(IInterface service, int userid) {
315 checkNotNull(service);
316 // no need to check permissions; if your service binder is in the list,
317 // that's proof that you had permission to add it in the first place
318 unregisterServiceImpl(service, userid);
321 public void registerService(IInterface service, ComponentName component, int userid) {
322 checkNotNull(service);
323 ManagedServiceInfo info = registerServiceImpl(service, component, userid);
325 onServiceAdded(info);
330 * Add a service to our callbacks. The lifecycle of this service is managed externally,
331 * but unlike a system service, it should not be considered privledged.
333 public void registerGuestService(ManagedServiceInfo guest) {
334 checkNotNull(guest.service);
335 if (!checkType(guest.service)) {
336 throw new IllegalArgumentException();
338 if (registerServiceImpl(guest) != null) {
339 onServiceAdded(guest);
343 public void setComponentState(ComponentName component, boolean enabled) {
344 boolean previous = !mSnoozingForCurrentProfiles.contains(component);
345 if (previous == enabled) {
350 mSnoozingForCurrentProfiles.remove(component);
352 mSnoozingForCurrentProfiles.add(component);
357 Slog.d(TAG, ((enabled) ? "Enabling " : "Disabling ") + "component " +
358 component.flattenToShortString());
362 synchronized (mMutex) {
363 final int[] userIds = mUserProfiles.getCurrentProfileIds();
365 for (int userId : userIds) {
367 registerServiceLocked(component, userId);
369 unregisterServiceLocked(component, userId);
375 private void rebuildRestoredPackages() {
376 mRestoredPackages.clear();
377 String secureSettingName = restoredSettingName(mConfig.secureSettingName);
378 String secondarySettingName = mConfig.secondarySettingName == null
379 ? null : restoredSettingName(mConfig.secondarySettingName);
380 int[] userIds = mUserProfiles.getCurrentProfileIds();
381 final int N = userIds.length;
382 for (int i = 0; i < N; ++i) {
383 ArraySet<ComponentName> names =
384 loadComponentNamesFromSetting(secureSettingName, userIds[i]);
385 if (secondarySettingName != null) {
386 names.addAll(loadComponentNamesFromSetting(secondarySettingName, userIds[i]));
388 for (ComponentName name : names) {
389 mRestoredPackages.add(name.getPackageName());
395 protected @NonNull ArraySet<ComponentName> loadComponentNamesFromSetting(String settingName,
397 final ContentResolver cr = mContext.getContentResolver();
398 String settingValue = Settings.Secure.getStringForUser(
402 if (TextUtils.isEmpty(settingValue))
403 return new ArraySet<>();
404 String[] restored = settingValue.split(ENABLED_SERVICES_SEPARATOR);
405 ArraySet<ComponentName> result = new ArraySet<>(restored.length);
406 for (int i = 0; i < restored.length; i++) {
407 ComponentName value = ComponentName.unflattenFromString(restored[i]);
415 private void storeComponentsToSetting(Set<ComponentName> components,
418 String[] componentNames = null;
419 if (null != components) {
420 componentNames = new String[components.size()];
422 for (ComponentName c: components) {
423 componentNames[index++] = c.flattenToString();
426 final String value = (componentNames == null) ? "" :
427 TextUtils.join(ENABLED_SERVICES_SEPARATOR, componentNames);
428 final ContentResolver cr = mContext.getContentResolver();
429 Settings.Secure.putStringForUser(
437 * Remove access for any services that no longer exist.
439 private void updateSettingsAccordingToInstalledServices() {
440 int[] userIds = mUserProfiles.getCurrentProfileIds();
441 final int N = userIds.length;
442 for (int i = 0; i < N; ++i) {
443 updateSettingsAccordingToInstalledServices(mConfig.secureSettingName, userIds[i]);
444 if (mConfig.secondarySettingName != null) {
445 updateSettingsAccordingToInstalledServices(
446 mConfig.secondarySettingName, userIds[i]);
449 rebuildRestoredPackages();
452 protected Set<ComponentName> queryPackageForServices(String packageName, int userId) {
453 Set<ComponentName> installed = new ArraySet<>();
454 final PackageManager pm = mContext.getPackageManager();
455 Intent queryIntent = new Intent(mConfig.serviceInterface);
456 if (!TextUtils.isEmpty(packageName)) {
457 queryIntent.setPackage(packageName);
459 List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
461 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
464 Slog.v(TAG, mConfig.serviceInterface + " services: " + installedServices);
465 if (installedServices != null) {
466 for (int i = 0, count = installedServices.size(); i < count; i++) {
467 ResolveInfo resolveInfo = installedServices.get(i);
468 ServiceInfo info = resolveInfo.serviceInfo;
470 ComponentName component = new ComponentName(info.packageName, info.name);
471 if (!mConfig.bindPermission.equals(info.permission)) {
472 Slog.w(TAG, "Skipping " + getCaption() + " service "
473 + info.packageName + "/" + info.name
474 + ": it does not require the permission "
475 + mConfig.bindPermission);
478 installed.add(component);
484 private void updateSettingsAccordingToInstalledServices(String setting, int userId) {
485 boolean restoredChanged = false;
486 boolean currentChanged = false;
487 Set<ComponentName> restored =
488 loadComponentNamesFromSetting(restoredSettingName(setting), userId);
489 Set<ComponentName> current =
490 loadComponentNamesFromSetting(setting, userId);
491 // Load all services for all packages.
492 Set<ComponentName> installed = queryPackageForServices(null, userId);
494 ArraySet<ComponentName> retained = new ArraySet<>();
496 for (ComponentName component : installed) {
497 if (null != restored) {
498 boolean wasRestored = restored.remove(component);
500 // Freshly installed package has service that was mentioned in restored setting.
502 Slog.v(TAG, "Restoring " + component + " for user " + userId);
503 restoredChanged = true;
504 currentChanged = true;
505 retained.add(component);
510 if (null != current) {
511 if (current.contains(component))
512 retained.add(component);
516 currentChanged |= ((current == null ? 0 : current.size()) != retained.size());
518 if (currentChanged) {
519 if (DEBUG) Slog.v(TAG, "List of " + getCaption() + " services was updated " + current);
520 storeComponentsToSetting(retained, setting, userId);
523 if (restoredChanged) {
524 if (DEBUG) Slog.v(TAG,
525 "List of " + getCaption() + " restored services was updated " + restored);
526 storeComponentsToSetting(restored, restoredSettingName(setting), userId);
531 * Called whenever packages change, the user switches, or the secure setting
532 * is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
534 private void rebindServices(boolean forceRebind) {
535 if (DEBUG) Slog.d(TAG, "rebindServices");
536 final int[] userIds = mUserProfiles.getCurrentProfileIds();
537 final int nUserIds = userIds.length;
539 final SparseArray<ArraySet<ComponentName>> componentsByUser = new SparseArray<>();
541 for (int i = 0; i < nUserIds; ++i) {
542 componentsByUser.put(userIds[i],
543 loadComponentNamesFromSetting(mConfig.secureSettingName, userIds[i]));
544 if (mConfig.secondarySettingName != null) {
545 componentsByUser.get(userIds[i]).addAll(
546 loadComponentNamesFromSetting(mConfig.secondarySettingName, userIds[i]));
550 final ArrayList<ManagedServiceInfo> removableBoundServices = new ArrayList<>();
551 final SparseArray<Set<ComponentName>> toAdd = new SparseArray<>();
553 synchronized (mMutex) {
554 // Rebind to non-system services if user switched
555 for (ManagedServiceInfo service : mServices) {
556 if (!service.isSystem && !service.isGuest(this)) {
557 removableBoundServices.add(service);
561 mEnabledServicesForCurrentProfiles.clear();
562 mEnabledServicesPackageNames.clear();
564 for (int i = 0; i < nUserIds; ++i) {
565 // decode the list of components
566 final ArraySet<ComponentName> userComponents = componentsByUser.get(userIds[i]);
567 if (null == userComponents) {
568 toAdd.put(userIds[i], new ArraySet<ComponentName>());
572 final Set<ComponentName> add = new HashSet<>(userComponents);
573 add.removeAll(mSnoozingForCurrentProfiles);
575 toAdd.put(userIds[i], add);
577 mEnabledServicesForCurrentProfiles.addAll(userComponents);
579 for (int j = 0; j < userComponents.size(); j++) {
580 final ComponentName component = userComponents.valueAt(j);
581 mEnabledServicesPackageNames.add(component.getPackageName());
586 for (ManagedServiceInfo info : removableBoundServices) {
587 final ComponentName component = info.component;
588 final int oldUser = info.userid;
589 final Set<ComponentName> allowedComponents = toAdd.get(info.userid);
590 if (allowedComponents != null) {
591 if (allowedComponents.contains(component) && !forceRebind) {
592 // Already bound, don't need to bind again.
593 allowedComponents.remove(component);
595 // No longer allowed to be bound, or must rebind.
596 Slog.v(TAG, "disabling " + getCaption() + " for user "
597 + oldUser + ": " + component);
598 unregisterService(component, oldUser);
603 for (int i = 0; i < nUserIds; ++i) {
604 final Set<ComponentName> add = toAdd.get(userIds[i]);
605 for (ComponentName component : add) {
607 ServiceInfo info = mPm.getServiceInfo(component,
608 PackageManager.MATCH_DIRECT_BOOT_AWARE
609 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userIds[i]);
610 if (info == null || !mConfig.bindPermission.equals(info.permission)) {
611 Slog.w(TAG, "Skipping " + getCaption() + " service " + component
612 + ": it does not require the permission " + mConfig.bindPermission);
616 "enabling " + getCaption() + " for " + userIds[i] + ": " + component);
617 registerService(component, userIds[i]);
618 } catch (RemoteException e) {
619 e.rethrowFromSystemServer();
624 mLastSeenProfileIds = userIds;
628 * Version of registerService that takes the name of a service component to bind to.
630 private void registerService(final ComponentName name, final int userid) {
631 synchronized (mMutex) {
632 registerServiceLocked(name, userid);
637 * Inject a system service into the management list.
639 public void registerSystemService(final ComponentName name, final int userid) {
640 synchronized (mMutex) {
641 registerServiceLocked(name, userid, true /* isSystem */);
645 private void registerServiceLocked(final ComponentName name, final int userid) {
646 registerServiceLocked(name, userid, false /* isSystem */);
649 private void registerServiceLocked(final ComponentName name, final int userid,
650 final boolean isSystem) {
651 if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid);
653 final String servicesBindingTag = name.toString() + "/" + userid;
654 if (mServicesBinding.contains(servicesBindingTag)) {
655 // stop registering this thing already! we're working on it
658 mServicesBinding.add(servicesBindingTag);
660 final int N = mServices.size();
661 for (int i = N - 1; i >= 0; i--) {
662 final ManagedServiceInfo info = mServices.get(i);
663 if (name.equals(info.component)
664 && info.userid == userid) {
665 // cut old connections
666 if (DEBUG) Slog.v(TAG, " disconnecting old " + getCaption() + ": "
668 removeServiceLocked(i);
669 if (info.connection != null) {
670 mContext.unbindService(info.connection);
675 Intent intent = new Intent(mConfig.serviceInterface);
676 intent.setComponent(name);
678 intent.putExtra(Intent.EXTRA_CLIENT_LABEL, mConfig.clientLabel);
680 final PendingIntent pendingIntent = PendingIntent.getActivity(
681 mContext, 0, new Intent(mConfig.settingsAction), 0);
682 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent);
684 ApplicationInfo appInfo = null;
686 appInfo = mContext.getPackageManager().getApplicationInfo(
687 name.getPackageName(), 0);
688 } catch (NameNotFoundException e) {
689 // Ignore if the package doesn't exist we won't be able to bind to the service.
691 final int targetSdkVersion =
692 appInfo != null ? appInfo.targetSdkVersion : Build.VERSION_CODES.BASE;
695 if (DEBUG) Slog.v(TAG, "binding: " + intent);
696 ServiceConnection serviceConnection = new ServiceConnection() {
700 public void onServiceConnected(ComponentName name, IBinder binder) {
701 boolean added = false;
702 ManagedServiceInfo info = null;
703 synchronized (mMutex) {
704 mServicesBinding.remove(servicesBindingTag);
706 mService = asInterface(binder);
707 info = newServiceInfo(mService, name,
708 userid, isSystem, this, targetSdkVersion);
709 binder.linkToDeath(info, 0);
710 added = mServices.add(info);
711 } catch (RemoteException e) {
716 onServiceAdded(info);
721 public void onServiceDisconnected(ComponentName name) {
722 Slog.v(TAG, getCaption() + " connection lost: " + name);
725 if (!mContext.bindServiceAsUser(intent,
727 BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT,
728 new UserHandle(userid))) {
729 mServicesBinding.remove(servicesBindingTag);
730 Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent);
733 } catch (SecurityException ex) {
734 Slog.e(TAG, "Unable to bind " + getCaption() + " service: " + intent, ex);
740 * Remove a service for the given user by ComponentName
742 private void unregisterService(ComponentName name, int userid) {
743 synchronized (mMutex) {
744 unregisterServiceLocked(name, userid);
748 private void unregisterServiceLocked(ComponentName name, int userid) {
749 final int N = mServices.size();
750 for (int i = N - 1; i >= 0; i--) {
751 final ManagedServiceInfo info = mServices.get(i);
752 if (name.equals(info.component)
753 && info.userid == userid) {
754 removeServiceLocked(i);
755 if (info.connection != null) {
757 mContext.unbindService(info.connection);
758 } catch (IllegalArgumentException ex) {
759 // something happened to the service: we think we have a connection
761 Slog.e(TAG, getCaption() + " " + name + " could not be unbound: " + ex);
769 * Removes a service from the list but does not unbind
771 * @return the removed service.
773 private ManagedServiceInfo removeServiceImpl(IInterface service, final int userid) {
774 if (DEBUG) Slog.d(TAG, "removeServiceImpl service=" + service + " u=" + userid);
775 ManagedServiceInfo serviceInfo = null;
776 synchronized (mMutex) {
777 final int N = mServices.size();
778 for (int i = N - 1; i >= 0; i--) {
779 final ManagedServiceInfo info = mServices.get(i);
780 if (info.service.asBinder() == service.asBinder()
781 && info.userid == userid) {
782 if (DEBUG) Slog.d(TAG, "Removing active service " + info.component);
783 serviceInfo = removeServiceLocked(i);
790 private ManagedServiceInfo removeServiceLocked(int i) {
791 final ManagedServiceInfo info = mServices.remove(i);
792 onServiceRemovedLocked(info);
796 private void checkNotNull(IInterface service) {
797 if (service == null) {
798 throw new IllegalArgumentException(getCaption() + " must not be null");
802 private ManagedServiceInfo registerServiceImpl(final IInterface service,
803 final ComponentName component, final int userid) {
804 ManagedServiceInfo info = newServiceInfo(service, component, userid,
805 true /*isSystem*/, null /*connection*/, Build.VERSION_CODES.LOLLIPOP);
806 return registerServiceImpl(info);
809 private ManagedServiceInfo registerServiceImpl(ManagedServiceInfo info) {
810 synchronized (mMutex) {
812 info.service.asBinder().linkToDeath(info, 0);
815 } catch (RemoteException e) {
823 * Removes a service from the list and unbinds.
825 private void unregisterServiceImpl(IInterface service, int userid) {
826 ManagedServiceInfo info = removeServiceImpl(service, userid);
827 if (info != null && info.connection != null && !info.isGuest(this)) {
828 mContext.unbindService(info.connection);
832 private class SettingsObserver extends ContentObserver {
833 private final Uri mSecureSettingsUri = Settings.Secure.getUriFor(mConfig.secureSettingName);
834 private final Uri mSecondarySettingsUri;
836 private SettingsObserver(Handler handler) {
838 if (mConfig.secondarySettingName != null) {
839 mSecondarySettingsUri = Settings.Secure.getUriFor(mConfig.secondarySettingName);
841 mSecondarySettingsUri = null;
845 private void observe() {
846 ContentResolver resolver = mContext.getContentResolver();
847 resolver.registerContentObserver(mSecureSettingsUri,
848 false, this, UserHandle.USER_ALL);
849 if (mSecondarySettingsUri != null) {
850 resolver.registerContentObserver(mSecondarySettingsUri,
851 false, this, UserHandle.USER_ALL);
857 public void onChange(boolean selfChange, Uri uri) {
861 private void update(Uri uri) {
862 if (uri == null || mSecureSettingsUri.equals(uri)
863 || uri.equals(mSecondarySettingsUri)) {
864 if (DEBUG) Slog.d(TAG, "Setting changed: uri=" + uri);
865 rebindServices(false);
866 rebuildRestoredPackages();
871 public class ManagedServiceInfo implements IBinder.DeathRecipient {
872 public IInterface service;
873 public ComponentName component;
875 public boolean isSystem;
876 public ServiceConnection connection;
877 public int targetSdkVersion;
879 public ManagedServiceInfo(IInterface service, ComponentName component,
880 int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion) {
881 this.service = service;
882 this.component = component;
883 this.userid = userid;
884 this.isSystem = isSystem;
885 this.connection = connection;
886 this.targetSdkVersion = targetSdkVersion;
889 public boolean isGuest(ManagedServices host) {
890 return ManagedServices.this != host;
893 public ManagedServices getOwner() {
894 return ManagedServices.this;
898 public String toString() {
899 return new StringBuilder("ManagedServiceInfo[")
900 .append("component=").append(component)
901 .append(",userid=").append(userid)
902 .append(",isSystem=").append(isSystem)
903 .append(",targetSdkVersion=").append(targetSdkVersion)
904 .append(",connection=").append(connection == null ? null : "<connection>")
905 .append(",service=").append(service)
906 .append(']').toString();
909 public boolean enabledAndUserMatches(int nid) {
910 if (!isEnabledForCurrentProfiles()) {
913 if (this.userid == UserHandle.USER_ALL) return true;
914 if (this.isSystem) return true;
915 if (nid == UserHandle.USER_ALL || nid == this.userid) return true;
916 return supportsProfiles()
917 && mUserProfiles.isCurrentProfile(nid)
918 && isPermittedForProfile(nid);
921 public boolean supportsProfiles() {
922 return targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP;
926 public void binderDied() {
927 if (DEBUG) Slog.d(TAG, "binderDied");
928 // Remove the service, but don't unbind from the service. The system will bring the
929 // service back up, and the onServiceConnected handler will read the service with the
930 // new binding. If this isn't a bound service, and is just a registered
931 // service, just removing it from the list is all we need to do anyway.
932 removeServiceImpl(this.service, this.userid);
935 /** convenience method for looking in mEnabledServicesForCurrentProfiles */
936 public boolean isEnabledForCurrentProfiles() {
937 if (this.isSystem) return true;
938 if (this.connection == null) return false;
939 return mEnabledServicesForCurrentProfiles.contains(this.component);
943 * Returns true if this service is allowed to receive events for the given userId. A
944 * managed profile owner can disallow non-system services running outside of the profile
945 * from receiving events from the profile.
947 public boolean isPermittedForProfile(int userId) {
948 if (!mUserProfiles.isManagedProfile(userId)) {
951 DevicePolicyManager dpm =
952 (DevicePolicyManager) mContext.getSystemService(DEVICE_POLICY_SERVICE);
953 final long identity = Binder.clearCallingIdentity();
955 return dpm.isNotificationListenerServicePermitted(
956 component.getPackageName(), userId);
958 Binder.restoreCallingIdentity(identity);
963 /** convenience method for looking in mEnabledServicesForCurrentProfiles */
964 public boolean isComponentEnabledForCurrentProfiles(ComponentName component) {
965 return mEnabledServicesForCurrentProfiles.contains(component);
968 public static class UserProfiles {
969 // Profiles of the current user.
970 private final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>();
972 public void updateCache(@NonNull Context context) {
973 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
974 if (userManager != null) {
975 int currentUserId = ActivityManager.getCurrentUser();
976 List<UserInfo> profiles = userManager.getProfiles(currentUserId);
977 synchronized (mCurrentProfiles) {
978 mCurrentProfiles.clear();
979 for (UserInfo user : profiles) {
980 mCurrentProfiles.put(user.id, user);
986 public int[] getCurrentProfileIds() {
987 synchronized (mCurrentProfiles) {
988 int[] users = new int[mCurrentProfiles.size()];
989 final int N = mCurrentProfiles.size();
990 for (int i = 0; i < N; ++i) {
991 users[i] = mCurrentProfiles.keyAt(i);
997 public boolean isCurrentProfile(int userId) {
998 synchronized (mCurrentProfiles) {
999 return mCurrentProfiles.get(userId) != null;
1003 public boolean isManagedProfile(int userId) {
1004 synchronized (mCurrentProfiles) {
1005 UserInfo user = mCurrentProfiles.get(userId);
1006 return user != null && user.isManagedProfile();
1011 public static class Config {
1012 public String caption;
1013 public String serviceInterface;
1014 public String secureSettingName;
1015 public String secondarySettingName;
1016 public String bindPermission;
1017 public String settingsAction;
1018 public int clientLabel;