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 ManagedServices(Context context, Handler handler, Object mutex, UserProfiles userProfiles)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 onReceive(Context context, Intent intent)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 getConfig()141 abstract protected Config getConfig(); 142 getCaption()143 private String getCaption() { 144 return mConfig.caption; 145 } 146 asInterface(IBinder binder)147 abstract protected IInterface asInterface(IBinder binder); 148 checkType(IInterface service)149 abstract protected boolean checkType(IInterface service); 150 onServiceAdded(ManagedServiceInfo info)151 abstract protected void onServiceAdded(ManagedServiceInfo info); 152 onServiceRemovedLocked(ManagedServiceInfo removed)153 protected void onServiceRemovedLocked(ManagedServiceInfo removed) { } 154 newServiceInfo(IInterface service, ComponentName component, int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion)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 onBootPhaseAppsCanStart()162 public void onBootPhaseAppsCanStart() { 163 mSettingsObserver.observe(); 164 } 165 dump(PrintWriter pw, DumpFilter filter)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. restoredSettingName(String setting)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. settingRestored(String element, String oldValue, String newValue, int userid)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 isComponentEnabledForPackage(String pkg)216 public boolean isComponentEnabledForPackage(String pkg) { 217 return mEnabledServicesPackageNames.contains(pkg); 218 } 219 onPackagesChanged(boolean removingPackage, String[] pkgList)220 public void onPackagesChanged(boolean removingPackage, String[] pkgList) { 221 if (DEBUG) Slog.d(TAG, "onPackagesChanged removingPackage=" + removingPackage 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 (removingPackage) { 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 onUserSwitched(int user)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 onUserUnlocked(int user)256 public void onUserUnlocked(int user) { 257 if (DEBUG) Slog.d(TAG, "onUserUnlocked u=" + user); 258 rebuildRestoredPackages(); 259 rebindServices(false); 260 } 261 getServiceFromTokenLocked(IInterface service)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 checkServiceTokenLocked(IInterface service)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 unregisterService(IInterface service, int userid)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 registerService(IInterface service, ComponentName component, int userid)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 * */ registerGuestService(ManagedServiceInfo guest)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 setComponentState(ComponentName component, boolean enabled)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 rebuildRestoredPackages()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 loadComponentNamesFromSetting(String settingName, int userId)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 storeComponentsToSetting(Set<ComponentName> components, String settingName, int userId)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 */ updateSettingsAccordingToInstalledServices()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 queryPackageForServices(String packageName, int userId)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 updateSettingsAccordingToInstalledServices(String setting, int userId)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 */ rebindServices(boolean forceRebind)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 */ registerService(final ComponentName name, final int userid)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 */ registerSystemService(final ComponentName name, final int userid)598 public void registerSystemService(final ComponentName name, final int userid) { 599 synchronized (mMutex) { 600 registerServiceLocked(name, userid, true /* isSystem */); 601 } 602 } 603 registerServiceLocked(final ComponentName name, final int userid)604 private void registerServiceLocked(final ComponentName name, final int userid) { 605 registerServiceLocked(name, userid, false /* isSystem */); 606 } 607 registerServiceLocked(final ComponentName name, final int userid, final boolean isSystem)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 */ unregisterService(ComponentName name, int userid)701 private void unregisterService(ComponentName name, int userid) { 702 synchronized (mMutex) { 703 unregisterServiceLocked(name, userid); 704 } 705 } 706 unregisterServiceLocked(ComponentName name, int userid)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 */ removeServiceImpl(IInterface service, final int userid)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 removeServiceLocked(int i)749 private ManagedServiceInfo removeServiceLocked(int i) { 750 final ManagedServiceInfo info = mServices.remove(i); 751 onServiceRemovedLocked(info); 752 return info; 753 } 754 checkNotNull(IInterface service)755 private void checkNotNull(IInterface service) { 756 if (service == null) { 757 throw new IllegalArgumentException(getCaption() + " must not be null"); 758 } 759 } 760 registerServiceImpl(final IInterface service, final ComponentName component, final int userid)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 registerServiceImpl(ManagedServiceInfo info)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 */ unregisterServiceImpl(IInterface service, int userid)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 SettingsObserver(Handler handler)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 observe()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 onChange(boolean selfChange, Uri uri)816 public void onChange(boolean selfChange, Uri uri) { 817 update(uri); 818 } 819 update(Uri uri)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 ManagedServiceInfo(IInterface service, ComponentName component, int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion)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 isGuest(ManagedServices host)848 public boolean isGuest(ManagedServices host) { 849 return ManagedServices.this != host; 850 } 851 getOwner()852 public ManagedServices getOwner() { 853 return ManagedServices.this; 854 } 855 856 @Override toString()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 enabledAndUserMatches(int nid)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 supportsProfiles()878 public boolean supportsProfiles() { 879 return targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP; 880 } 881 882 @Override binderDied()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 */ isEnabledForCurrentProfiles()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 */ isComponentEnabledForCurrentProfiles(ComponentName component)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 updateCache(@onNull Context context)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 getCurrentProfileIds()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 isCurrentProfile(int userId)934 public boolean isCurrentProfile(int userId) { 935 synchronized (mCurrentProfiles) { 936 return mCurrentProfiles.get(userId) != null; 937 } 938 } 939 } 940 941 public static class Config { 942 public String caption; 943 public String serviceInterface; 944 public String secureSettingName; 945 public String secondarySettingName; 946 public String bindPermission; 947 public String settingsAction; 948 public int clientLabel; 949 } 950 } 951