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