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