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 import static android.content.Context.DEVICE_POLICY_SERVICE; 23 24 import android.annotation.NonNull; 25 import android.app.ActivityManager; 26 import android.app.PendingIntent; 27 import android.app.admin.DevicePolicyManager; 28 import android.content.ComponentName; 29 import android.content.ContentResolver; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.content.ServiceConnection; 33 import android.content.pm.ApplicationInfo; 34 import android.content.pm.IPackageManager; 35 import android.content.pm.PackageManager; 36 import android.content.pm.PackageManager.NameNotFoundException; 37 import android.content.pm.ResolveInfo; 38 import android.content.pm.ServiceInfo; 39 import android.content.pm.UserInfo; 40 import android.os.Binder; 41 import android.os.Build; 42 import android.os.Handler; 43 import android.os.IBinder; 44 import android.os.IInterface; 45 import android.os.Looper; 46 import android.os.RemoteException; 47 import android.os.UserHandle; 48 import android.os.UserManager; 49 import android.provider.Settings; 50 import android.service.notification.ManagedServiceInfoProto; 51 import android.service.notification.ManagedServicesProto; 52 import android.service.notification.ManagedServicesProto.ServiceProto; 53 import android.text.TextUtils; 54 import android.util.ArrayMap; 55 import android.util.ArraySet; 56 import android.util.Log; 57 import android.util.Slog; 58 import android.util.SparseArray; 59 import android.util.proto.ProtoOutputStream; 60 61 import com.android.internal.util.XmlUtils; 62 import com.android.server.notification.NotificationManagerService.DumpFilter; 63 64 import org.xmlpull.v1.XmlPullParser; 65 import org.xmlpull.v1.XmlPullParserException; 66 import org.xmlpull.v1.XmlSerializer; 67 68 import java.io.IOException; 69 import java.io.PrintWriter; 70 import java.util.ArrayList; 71 import java.util.Arrays; 72 import java.util.HashSet; 73 import java.util.List; 74 import java.util.Set; 75 import java.util.function.Predicate; 76 import java.util.stream.Collectors; 77 78 /** 79 * Manages the lifecycle of application-provided services bound by system server. 80 * 81 * Services managed by this helper must have: 82 * - An associated system settings value with a list of enabled component names. 83 * - A well-known action for services to use in their intent-filter. 84 * - A system permission for services to require in order to ensure system has exclusive binding. 85 * - A settings page for user configuration of enabled services, and associated intent action. 86 * - A remote interface definition (aidl) provided by the service used for communication. 87 */ 88 abstract public class ManagedServices { 89 protected final String TAG = getClass().getSimpleName(); 90 protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 91 92 private static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000; 93 protected static final String ENABLED_SERVICES_SEPARATOR = ":"; 94 95 /** 96 * List of components and apps that can have running {@link ManagedServices}. 97 */ 98 static final String TAG_MANAGED_SERVICES = "service_listing"; 99 static final String ATT_APPROVED_LIST = "approved"; 100 static final String ATT_USER_ID = "user"; 101 static final String ATT_IS_PRIMARY = "primary"; 102 static final String ATT_VERSION = "version"; 103 104 static final int DB_VERSION = 1; 105 106 static final int APPROVAL_BY_PACKAGE = 0; 107 static final int APPROVAL_BY_COMPONENT = 1; 108 109 protected final Context mContext; 110 protected final Object mMutex; 111 private final UserProfiles mUserProfiles; 112 private final IPackageManager mPm; 113 protected final UserManager mUm; 114 private final Config mConfig; 115 private final Handler mHandler = new Handler(Looper.getMainLooper()); 116 117 // contains connections to all connected services, including app services 118 // and system services 119 private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<>(); 120 // things that will be put into mServices as soon as they're ready 121 private final ArrayList<String> mServicesBinding = new ArrayList<>(); 122 private final ArraySet<String> mServicesRebinding = new ArraySet<>(); 123 124 // lists the component names of all enabled (and therefore potentially connected) 125 // app services for current profiles. 126 private ArraySet<ComponentName> mEnabledServicesForCurrentProfiles 127 = new ArraySet<>(); 128 // Just the packages from mEnabledServicesForCurrentProfiles 129 private ArraySet<String> mEnabledServicesPackageNames = new ArraySet<>(); 130 // List of enabled packages that have nevertheless asked not to be run 131 private ArraySet<ComponentName> mSnoozingForCurrentProfiles = new ArraySet<>(); 132 133 // List of approved packages or components (by user, then by primary/secondary) that are 134 // allowed to be bound as managed services. A package or component appearing in this list does 135 // not mean that we are currently bound to said package/component. 136 private ArrayMap<Integer, ArrayMap<Boolean, ArraySet<String>>> mApproved = new ArrayMap<>(); 137 138 // Kept to de-dupe user change events (experienced after boot, when we receive a settings and a 139 // user change). 140 private int[] mLastSeenProfileIds; 141 142 // True if approved services are stored in xml, not settings. 143 private boolean mUseXml; 144 145 // Whether managed services are approved individually or package wide 146 protected int mApprovalLevel; 147 148 public ManagedServices(Context context, Object mutex, UserProfiles userProfiles, 149 IPackageManager pm) { 150 mContext = context; 151 mMutex = mutex; 152 mUserProfiles = userProfiles; 153 mPm = pm; 154 mConfig = getConfig(); 155 mApprovalLevel = APPROVAL_BY_COMPONENT; 156 mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 157 } 158 159 abstract protected Config getConfig(); 160 161 private String getCaption() { 162 return mConfig.caption; 163 } 164 165 abstract protected IInterface asInterface(IBinder binder); 166 167 abstract protected boolean checkType(IInterface service); 168 169 abstract protected void onServiceAdded(ManagedServiceInfo info); 170 171 protected List<ManagedServiceInfo> getServices() { 172 synchronized (mMutex) { 173 List<ManagedServiceInfo> services = new ArrayList<>(mServices); 174 return services; 175 } 176 } 177 178 protected void onServiceRemovedLocked(ManagedServiceInfo removed) { } 179 180 private ManagedServiceInfo newServiceInfo(IInterface service, 181 ComponentName component, int userId, boolean isSystem, ServiceConnection connection, 182 int targetSdkVersion) { 183 return new ManagedServiceInfo(service, component, userId, isSystem, connection, 184 targetSdkVersion); 185 } 186 187 public void onBootPhaseAppsCanStart() {} 188 189 public void dump(PrintWriter pw, DumpFilter filter) { 190 pw.println(" Allowed " + getCaption() + "s:"); 191 final int N = mApproved.size(); 192 for (int i = 0 ; i < N; i++) { 193 final int userId = mApproved.keyAt(i); 194 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i); 195 if (approvedByType != null) { 196 final int M = approvedByType.size(); 197 for (int j = 0; j < M; j++) { 198 final boolean isPrimary = approvedByType.keyAt(j); 199 final ArraySet<String> approved = approvedByType.valueAt(j); 200 if (approvedByType != null && approvedByType.size() > 0) { 201 pw.println(" " + String.join(ENABLED_SERVICES_SEPARATOR, approved) 202 + " (user: " + userId + " isPrimary: " + isPrimary + ")"); 203 } 204 } 205 } 206 } 207 208 pw.println(" All " + getCaption() + "s (" + mEnabledServicesForCurrentProfiles.size() 209 + ") enabled for current profiles:"); 210 for (ComponentName cmpt : mEnabledServicesForCurrentProfiles) { 211 if (filter != null && !filter.matches(cmpt)) continue; 212 pw.println(" " + cmpt); 213 } 214 215 pw.println(" Live " + getCaption() + "s (" + mServices.size() + "):"); 216 for (ManagedServiceInfo info : mServices) { 217 if (filter != null && !filter.matches(info.component)) continue; 218 pw.println(" " + info.component 219 + " (user " + info.userid + "): " + info.service 220 + (info.isSystem?" SYSTEM":"") 221 + (info.isGuest(this)?" GUEST":"")); 222 } 223 224 pw.println(" Snoozed " + getCaption() + "s (" + 225 mSnoozingForCurrentProfiles.size() + "):"); 226 for (ComponentName name : mSnoozingForCurrentProfiles) { 227 pw.println(" " + name.flattenToShortString()); 228 } 229 } 230 231 public void dump(ProtoOutputStream proto, DumpFilter filter) { 232 proto.write(ManagedServicesProto.CAPTION, getCaption()); 233 final int N = mApproved.size(); 234 for (int i = 0 ; i < N; i++) { 235 final int userId = mApproved.keyAt(i); 236 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i); 237 if (approvedByType != null) { 238 final int M = approvedByType.size(); 239 for (int j = 0; j < M; j++) { 240 final boolean isPrimary = approvedByType.keyAt(j); 241 final ArraySet<String> approved = approvedByType.valueAt(j); 242 if (approvedByType != null && approvedByType.size() > 0) { 243 final long sToken = proto.start(ManagedServicesProto.APPROVED); 244 for (String s : approved) { 245 proto.write(ServiceProto.NAME, s); 246 } 247 proto.write(ServiceProto.USER_ID, userId); 248 proto.write(ServiceProto.IS_PRIMARY, isPrimary); 249 proto.end(sToken); 250 } 251 } 252 } 253 } 254 255 for (ComponentName cmpt : mEnabledServicesForCurrentProfiles) { 256 if (filter != null && !filter.matches(cmpt)) continue; 257 cmpt.writeToProto(proto, ManagedServicesProto.ENABLED); 258 } 259 260 for (ManagedServiceInfo info : mServices) { 261 if (filter != null && !filter.matches(info.component)) continue; 262 info.writeToProto(proto, ManagedServicesProto.LIVE_SERVICES, this); 263 } 264 265 for (ComponentName name : mSnoozingForCurrentProfiles) { 266 name.writeToProto(proto, ManagedServicesProto.SNOOZED); 267 } 268 } 269 270 protected void onSettingRestored(String element, String value, int backupSdkInt, int userId) { 271 if (!mUseXml) { 272 Slog.d(TAG, "Restored managed service setting: " + element); 273 if (mConfig.secureSettingName.equals(element) || 274 (mConfig.secondarySettingName != null 275 && mConfig.secondarySettingName.equals(element))) { 276 if (backupSdkInt < Build.VERSION_CODES.O) { 277 // automatic system grants were added in O, so append the approved apps 278 // rather than wiping out the setting 279 String currentSetting = 280 getApproved(userId, mConfig.secureSettingName.equals(element)); 281 if (!TextUtils.isEmpty(currentSetting)) { 282 if (!TextUtils.isEmpty(value)) { 283 value = value + ENABLED_SERVICES_SEPARATOR + currentSetting; 284 } else { 285 value = currentSetting; 286 } 287 } 288 } 289 Settings.Secure.putStringForUser( 290 mContext.getContentResolver(), element, value, userId); 291 loadAllowedComponentsFromSettings(); 292 rebindServices(false); 293 } 294 } 295 } 296 297 public void writeXml(XmlSerializer out, boolean forBackup) throws IOException { 298 out.startTag(null, getConfig().xmlTag); 299 300 out.attribute(null, ATT_VERSION, String.valueOf(DB_VERSION)); 301 302 if (forBackup) { 303 trimApprovedListsAccordingToInstalledServices(); 304 } 305 306 final int N = mApproved.size(); 307 for (int i = 0 ; i < N; i++) { 308 final int userId = mApproved.keyAt(i); 309 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i); 310 if (approvedByType != null) { 311 final int M = approvedByType.size(); 312 for (int j = 0; j < M; j++) { 313 final boolean isPrimary = approvedByType.keyAt(j); 314 final Set<String> approved = approvedByType.valueAt(j); 315 if (approved != null) { 316 String allowedItems = String.join(ENABLED_SERVICES_SEPARATOR, approved); 317 out.startTag(null, TAG_MANAGED_SERVICES); 318 out.attribute(null, ATT_APPROVED_LIST, allowedItems); 319 out.attribute(null, ATT_USER_ID, Integer.toString(userId)); 320 out.attribute(null, ATT_IS_PRIMARY, Boolean.toString(isPrimary)); 321 out.endTag(null, TAG_MANAGED_SERVICES); 322 323 if (!forBackup && isPrimary) { 324 // Also write values to settings, for observers who haven't migrated yet 325 Settings.Secure.putStringForUser(mContext.getContentResolver(), 326 getConfig().secureSettingName, allowedItems, userId); 327 } 328 329 } 330 } 331 } 332 } 333 334 out.endTag(null, getConfig().xmlTag); 335 } 336 337 protected void migrateToXml() { 338 loadAllowedComponentsFromSettings(); 339 } 340 341 public void readXml(XmlPullParser parser, Predicate<String> allowedManagedServicePackages) 342 throws XmlPullParserException, IOException { 343 // upgrade xml 344 int xmlVersion = XmlUtils.readIntAttribute(parser, ATT_VERSION, 0); 345 final List<UserInfo> activeUsers = mUm.getUsers(true); 346 for (UserInfo userInfo : activeUsers) { 347 upgradeXml(xmlVersion, userInfo.getUserHandle().getIdentifier()); 348 } 349 350 // read grants 351 int type; 352 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 353 String tag = parser.getName(); 354 if (type == XmlPullParser.END_TAG 355 && getConfig().xmlTag.equals(tag)) { 356 break; 357 } 358 if (type == XmlPullParser.START_TAG) { 359 if (TAG_MANAGED_SERVICES.equals(tag)) { 360 Slog.i(TAG, "Read " + mConfig.caption + " permissions from xml"); 361 362 final String approved = XmlUtils.readStringAttribute(parser, ATT_APPROVED_LIST); 363 final int userId = XmlUtils.readIntAttribute(parser, ATT_USER_ID, 0); 364 final boolean isPrimary = 365 XmlUtils.readBooleanAttribute(parser, ATT_IS_PRIMARY, true); 366 367 if (allowedManagedServicePackages == null || 368 allowedManagedServicePackages.test(getPackageName(approved))) { 369 if (mUm.getUserInfo(userId) != null) { 370 addApprovedList(approved, userId, isPrimary); 371 } 372 mUseXml = true; 373 } 374 } 375 } 376 } 377 rebindServices(false); 378 } 379 380 protected void upgradeXml(final int xmlVersion, final int userId) {} 381 382 private void loadAllowedComponentsFromSettings() { 383 for (UserInfo user : mUm.getUsers()) { 384 final ContentResolver cr = mContext.getContentResolver(); 385 addApprovedList(Settings.Secure.getStringForUser( 386 cr, 387 getConfig().secureSettingName, 388 user.id), user.id, true); 389 if (!TextUtils.isEmpty(getConfig().secondarySettingName)) { 390 addApprovedList(Settings.Secure.getStringForUser( 391 cr, 392 getConfig().secondarySettingName, 393 user.id), user.id, false); 394 } 395 } 396 Slog.d(TAG, "Done loading approved values from settings"); 397 } 398 399 protected void addApprovedList(String approved, int userId, boolean isPrimary) { 400 if (TextUtils.isEmpty(approved)) { 401 approved = ""; 402 } 403 ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId); 404 if (approvedByType == null) { 405 approvedByType = new ArrayMap<>(); 406 mApproved.put(userId, approvedByType); 407 } 408 409 ArraySet<String> approvedList = approvedByType.get(isPrimary); 410 if (approvedList == null) { 411 approvedList = new ArraySet<>(); 412 approvedByType.put(isPrimary, approvedList); 413 } 414 415 String[] approvedArray = approved.split(ENABLED_SERVICES_SEPARATOR); 416 for (String pkgOrComponent : approvedArray) { 417 String approvedItem = getApprovedValue(pkgOrComponent); 418 if (approvedItem != null) { 419 approvedList.add(approvedItem); 420 } 421 } 422 } 423 424 protected boolean isComponentEnabledForPackage(String pkg) { 425 return mEnabledServicesPackageNames.contains(pkg); 426 } 427 428 protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId, 429 boolean isPrimary, boolean enabled) { 430 Slog.i(TAG, 431 (enabled ? " Allowing " : "Disallowing ") + mConfig.caption + " " + pkgOrComponent); 432 ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.get(userId); 433 if (allowedByType == null) { 434 allowedByType = new ArrayMap<>(); 435 mApproved.put(userId, allowedByType); 436 } 437 ArraySet<String> approved = allowedByType.get(isPrimary); 438 if (approved == null) { 439 approved = new ArraySet<>(); 440 allowedByType.put(isPrimary, approved); 441 } 442 String approvedItem = getApprovedValue(pkgOrComponent); 443 444 if (approvedItem != null) { 445 if (enabled) { 446 approved.add(approvedItem); 447 } else { 448 approved.remove(approvedItem); 449 } 450 } 451 452 rebindServices(false); 453 } 454 455 private String getApprovedValue(String pkgOrComponent) { 456 if (mApprovalLevel == APPROVAL_BY_COMPONENT) { 457 if(ComponentName.unflattenFromString(pkgOrComponent) != null) { 458 return pkgOrComponent; 459 } 460 return null; 461 } else { 462 return getPackageName(pkgOrComponent); 463 } 464 } 465 466 protected String getApproved(int userId, boolean primary) { 467 final ArrayMap<Boolean, ArraySet<String>> allowedByType = 468 mApproved.getOrDefault(userId, new ArrayMap<>()); 469 ArraySet<String> approved = allowedByType.getOrDefault(primary, new ArraySet<>()); 470 return String.join(ENABLED_SERVICES_SEPARATOR, approved); 471 } 472 473 protected List<ComponentName> getAllowedComponents(int userId) { 474 final List<ComponentName> allowedComponents = new ArrayList<>(); 475 final ArrayMap<Boolean, ArraySet<String>> allowedByType = 476 mApproved.getOrDefault(userId, new ArrayMap<>()); 477 for (int i = 0; i < allowedByType.size(); i++) { 478 final ArraySet<String> allowed = allowedByType.valueAt(i); 479 for (int j = 0; j < allowed.size(); j++) { 480 ComponentName cn = ComponentName.unflattenFromString(allowed.valueAt(j)); 481 if (cn != null) { 482 allowedComponents.add(cn); 483 } 484 } 485 } 486 return allowedComponents; 487 } 488 489 protected List<String> getAllowedPackages(int userId) { 490 final List<String> allowedPackages = new ArrayList<>(); 491 final ArrayMap<Boolean, ArraySet<String>> allowedByType = 492 mApproved.getOrDefault(userId, new ArrayMap<>()); 493 for (int i = 0; i < allowedByType.size(); i++) { 494 final ArraySet<String> allowed = allowedByType.valueAt(i); 495 for (int j = 0; j < allowed.size(); j++) { 496 String pkgName = getPackageName(allowed.valueAt(j)); 497 if (!TextUtils.isEmpty(pkgName)) { 498 allowedPackages.add(pkgName); 499 } 500 } 501 } 502 return allowedPackages; 503 } 504 505 protected boolean isPackageOrComponentAllowed(String pkgOrComponent, int userId) { 506 ArrayMap<Boolean, ArraySet<String>> allowedByType = 507 mApproved.getOrDefault(userId, new ArrayMap<>()); 508 for (int i = 0; i < allowedByType.size(); i++) { 509 ArraySet<String> allowed = allowedByType.valueAt(i); 510 if (allowed.contains(pkgOrComponent)) { 511 return true; 512 } 513 } 514 return false; 515 } 516 517 public void onPackagesChanged(boolean removingPackage, String[] pkgList, int[] uidList) { 518 if (DEBUG) Slog.d(TAG, "onPackagesChanged removingPackage=" + removingPackage 519 + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList)) 520 + " mEnabledServicesPackageNames=" + mEnabledServicesPackageNames); 521 522 if (pkgList != null && (pkgList.length > 0)) { 523 boolean anyServicesInvolved = false; 524 // Remove notification settings for uninstalled package 525 if (removingPackage) { 526 int size = Math.min(pkgList.length, uidList.length); 527 for (int i = 0; i < size; i++) { 528 final String pkg = pkgList[i]; 529 final int userId = UserHandle.getUserId(uidList[i]); 530 anyServicesInvolved = removeUninstalledItemsFromApprovedLists(userId, pkg); 531 } 532 } 533 for (String pkgName : pkgList) { 534 if (mEnabledServicesPackageNames.contains(pkgName)) { 535 anyServicesInvolved = true; 536 } 537 } 538 539 if (anyServicesInvolved) { 540 // make sure we're still bound to any of our services who may have just upgraded 541 rebindServices(false); 542 } 543 } 544 } 545 546 public void onUserRemoved(int user) { 547 Slog.i(TAG, "Removing approved services for removed user " + user); 548 mApproved.remove(user); 549 rebindServices(true); 550 } 551 552 public void onUserSwitched(int user) { 553 if (DEBUG) Slog.d(TAG, "onUserSwitched u=" + user); 554 if (Arrays.equals(mLastSeenProfileIds, mUserProfiles.getCurrentProfileIds())) { 555 if (DEBUG) Slog.d(TAG, "Current profile IDs didn't change, skipping rebindServices()."); 556 return; 557 } 558 rebindServices(true); 559 } 560 561 public void onUserUnlocked(int user) { 562 if (DEBUG) Slog.d(TAG, "onUserUnlocked u=" + user); 563 rebindServices(false); 564 } 565 566 private ManagedServiceInfo getServiceFromTokenLocked(IInterface service) { 567 if (service == null) { 568 return null; 569 } 570 final IBinder token = service.asBinder(); 571 final int N = mServices.size(); 572 for (int i = 0; i < N; i++) { 573 final ManagedServiceInfo info = mServices.get(i); 574 if (info.service.asBinder() == token) return info; 575 } 576 return null; 577 } 578 579 protected boolean isServiceTokenValidLocked(IInterface service) { 580 if (service == null) { 581 return false; 582 } 583 ManagedServiceInfo info = getServiceFromTokenLocked(service); 584 if (info != null) { 585 return true; 586 } 587 return false; 588 } 589 590 protected ManagedServiceInfo checkServiceTokenLocked(IInterface service) { 591 checkNotNull(service); 592 ManagedServiceInfo info = getServiceFromTokenLocked(service); 593 if (info != null) { 594 return info; 595 } 596 throw new SecurityException("Disallowed call from unknown " + getCaption() + ": " 597 + service + " " + service.getClass()); 598 } 599 600 public void unregisterService(IInterface service, int userid) { 601 checkNotNull(service); 602 // no need to check permissions; if your service binder is in the list, 603 // that's proof that you had permission to add it in the first place 604 unregisterServiceImpl(service, userid); 605 } 606 607 public void registerService(IInterface service, ComponentName component, int userid) { 608 checkNotNull(service); 609 ManagedServiceInfo info = registerServiceImpl(service, component, userid); 610 if (info != null) { 611 onServiceAdded(info); 612 } 613 } 614 615 /** 616 * Add a service to our callbacks. The lifecycle of this service is managed externally, 617 * but unlike a system service, it should not be considered privileged. 618 * */ 619 protected void registerGuestService(ManagedServiceInfo guest) { 620 checkNotNull(guest.service); 621 if (!checkType(guest.service)) { 622 throw new IllegalArgumentException(); 623 } 624 if (registerServiceImpl(guest) != null) { 625 onServiceAdded(guest); 626 } 627 } 628 629 protected void setComponentState(ComponentName component, boolean enabled) { 630 boolean previous = !mSnoozingForCurrentProfiles.contains(component); 631 if (previous == enabled) { 632 return; 633 } 634 635 if (enabled) { 636 mSnoozingForCurrentProfiles.remove(component); 637 } else { 638 mSnoozingForCurrentProfiles.add(component); 639 } 640 641 // State changed 642 Slog.d(TAG, ((enabled) ? "Enabling " : "Disabling ") + "component " + 643 component.flattenToShortString()); 644 645 synchronized (mMutex) { 646 final int[] userIds = mUserProfiles.getCurrentProfileIds(); 647 648 for (int userId : userIds) { 649 if (enabled) { 650 registerServiceLocked(component, userId); 651 } else { 652 unregisterServiceLocked(component, userId); 653 } 654 } 655 } 656 } 657 658 private @NonNull ArraySet<ComponentName> loadComponentNamesFromValues( 659 ArraySet<String> approved, int userId) { 660 if (approved == null || approved.size() == 0) 661 return new ArraySet<>(); 662 ArraySet<ComponentName> result = new ArraySet<>(approved.size()); 663 for (int i = 0; i < approved.size(); i++) { 664 final String packageOrComponent = approved.valueAt(i); 665 if (!TextUtils.isEmpty(packageOrComponent)) { 666 ComponentName component = ComponentName.unflattenFromString(packageOrComponent); 667 if (component != null) { 668 result.add(component); 669 } else { 670 result.addAll(queryPackageForServices(packageOrComponent, userId)); 671 } 672 } 673 } 674 return result; 675 } 676 677 protected Set<ComponentName> queryPackageForServices(String packageName, int userId) { 678 return queryPackageForServices(packageName, 0, userId); 679 } 680 681 protected Set<ComponentName> queryPackageForServices(String packageName, int extraFlags, 682 int userId) { 683 Set<ComponentName> installed = new ArraySet<>(); 684 final PackageManager pm = mContext.getPackageManager(); 685 Intent queryIntent = new Intent(mConfig.serviceInterface); 686 if (!TextUtils.isEmpty(packageName)) { 687 queryIntent.setPackage(packageName); 688 } 689 List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser( 690 queryIntent, 691 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA | extraFlags, 692 userId); 693 if (DEBUG) 694 Slog.v(TAG, mConfig.serviceInterface + " services: " + installedServices); 695 if (installedServices != null) { 696 for (int i = 0, count = installedServices.size(); i < count; i++) { 697 ResolveInfo resolveInfo = installedServices.get(i); 698 ServiceInfo info = resolveInfo.serviceInfo; 699 700 ComponentName component = new ComponentName(info.packageName, info.name); 701 if (!mConfig.bindPermission.equals(info.permission)) { 702 Slog.w(TAG, "Skipping " + getCaption() + " service " 703 + info.packageName + "/" + info.name 704 + ": it does not require the permission " 705 + mConfig.bindPermission); 706 continue; 707 } 708 installed.add(component); 709 } 710 } 711 return installed; 712 } 713 714 private void trimApprovedListsAccordingToInstalledServices() { 715 int N = mApproved.size(); 716 for (int i = 0 ; i < N; i++) { 717 final int userId = mApproved.keyAt(i); 718 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i); 719 int M = approvedByType.size(); 720 for (int j = 0; j < M; j++) { 721 final ArraySet<String> approved = approvedByType.valueAt(j); 722 int P = approved.size(); 723 for (int k = P - 1; k >= 0; k--) { 724 final String approvedPackageOrComponent = approved.valueAt(k); 725 if (!isValidEntry(approvedPackageOrComponent, userId)){ 726 approved.removeAt(k); 727 Slog.v(TAG, "Removing " + approvedPackageOrComponent 728 + " from approved list; no matching services found"); 729 } else { 730 if (DEBUG) { 731 Slog.v(TAG, "Keeping " + approvedPackageOrComponent 732 + " on approved list; matching services found"); 733 } 734 } 735 } 736 } 737 } 738 } 739 740 private boolean removeUninstalledItemsFromApprovedLists(int uninstalledUserId, String pkg) { 741 boolean removed = false; 742 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(uninstalledUserId); 743 if (approvedByType != null) { 744 int M = approvedByType.size(); 745 for (int j = 0; j < M; j++) { 746 final ArraySet<String> approved = approvedByType.valueAt(j); 747 int O = approved.size(); 748 for (int k = O - 1; k >= 0; k--) { 749 final String packageOrComponent = approved.valueAt(k); 750 final String packageName = getPackageName(packageOrComponent); 751 if (TextUtils.equals(pkg, packageName)) { 752 approved.removeAt(k); 753 if (DEBUG) { 754 Slog.v(TAG, "Removing " + packageOrComponent 755 + " from approved list; uninstalled"); 756 } 757 } 758 } 759 } 760 } 761 return removed; 762 } 763 764 protected String getPackageName(String packageOrComponent) { 765 final ComponentName component = ComponentName.unflattenFromString(packageOrComponent); 766 if (component != null) { 767 return component.getPackageName(); 768 } else { 769 return packageOrComponent; 770 } 771 } 772 773 protected boolean isValidEntry(String packageOrComponent, int userId) { 774 return hasMatchingServices(packageOrComponent, userId); 775 } 776 777 private boolean hasMatchingServices(String packageOrComponent, int userId) { 778 if (!TextUtils.isEmpty(packageOrComponent)) { 779 final String packageName = getPackageName(packageOrComponent); 780 return queryPackageForServices(packageName, userId).size() > 0; 781 } 782 return false; 783 } 784 785 /** 786 * Called whenever packages change, the user switches, or the secure setting 787 * is altered. (For example in response to USER_SWITCHED in our broadcast receiver) 788 */ 789 protected void rebindServices(boolean forceRebind) { 790 if (DEBUG) Slog.d(TAG, "rebindServices"); 791 final int[] userIds = mUserProfiles.getCurrentProfileIds(); 792 final int nUserIds = userIds.length; 793 794 final SparseArray<ArraySet<ComponentName>> componentsByUser = new SparseArray<>(); 795 796 for (int i = 0; i < nUserIds; ++i) { 797 final int userId = userIds[i]; 798 final ArrayMap<Boolean, ArraySet<String>> approvedLists = mApproved.get(userIds[i]); 799 if (approvedLists != null) { 800 final int N = approvedLists.size(); 801 for (int j = 0; j < N; j++) { 802 ArraySet<ComponentName> approvedByUser = componentsByUser.get(userId); 803 if (approvedByUser == null) { 804 approvedByUser = new ArraySet<>(); 805 componentsByUser.put(userId, approvedByUser); 806 } 807 approvedByUser.addAll( 808 loadComponentNamesFromValues(approvedLists.valueAt(j), userId)); 809 } 810 } 811 } 812 813 final ArrayList<ManagedServiceInfo> removableBoundServices = new ArrayList<>(); 814 final SparseArray<Set<ComponentName>> toAdd = new SparseArray<>(); 815 816 synchronized (mMutex) { 817 // Rebind to non-system services if user switched 818 for (ManagedServiceInfo service : mServices) { 819 if (!service.isSystem && !service.isGuest(this)) { 820 removableBoundServices.add(service); 821 } 822 } 823 824 mEnabledServicesForCurrentProfiles.clear(); 825 mEnabledServicesPackageNames.clear(); 826 827 for (int i = 0; i < nUserIds; ++i) { 828 // decode the list of components 829 final ArraySet<ComponentName> userComponents = componentsByUser.get(userIds[i]); 830 if (null == userComponents) { 831 toAdd.put(userIds[i], new ArraySet<>()); 832 continue; 833 } 834 835 final Set<ComponentName> add = new HashSet<>(userComponents); 836 add.removeAll(mSnoozingForCurrentProfiles); 837 838 toAdd.put(userIds[i], add); 839 840 mEnabledServicesForCurrentProfiles.addAll(userComponents); 841 842 for (int j = 0; j < userComponents.size(); j++) { 843 final ComponentName component = userComponents.valueAt(j); 844 mEnabledServicesPackageNames.add(component.getPackageName()); 845 } 846 } 847 } 848 849 for (ManagedServiceInfo info : removableBoundServices) { 850 final ComponentName component = info.component; 851 final int oldUser = info.userid; 852 final Set<ComponentName> allowedComponents = toAdd.get(info.userid); 853 if (allowedComponents != null) { 854 if (allowedComponents.contains(component) && !forceRebind) { 855 // Already bound, don't need to bind again. 856 allowedComponents.remove(component); 857 } else { 858 // No longer allowed to be bound, or must rebind. 859 Slog.v(TAG, "disabling " + getCaption() + " for user " 860 + oldUser + ": " + component); 861 unregisterService(component, oldUser); 862 } 863 } 864 } 865 866 for (int i = 0; i < nUserIds; ++i) { 867 final Set<ComponentName> add = toAdd.get(userIds[i]); 868 for (ComponentName component : add) { 869 try { 870 ServiceInfo info = mPm.getServiceInfo(component, 871 PackageManager.MATCH_DIRECT_BOOT_AWARE 872 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userIds[i]); 873 if (info == null) { 874 Slog.w(TAG, "Not binding " + getCaption() + " service " + component 875 + ": service not found"); 876 continue; 877 } 878 if (!mConfig.bindPermission.equals(info.permission)) { 879 Slog.w(TAG, "Not binding " + getCaption() + " service " + component 880 + ": it does not require the permission " + mConfig.bindPermission); 881 continue; 882 } 883 Slog.v(TAG, 884 "enabling " + getCaption() + " for " + userIds[i] + ": " + component); 885 registerService(component, userIds[i]); 886 } catch (RemoteException e) { 887 e.rethrowFromSystemServer(); 888 } 889 } 890 } 891 892 mLastSeenProfileIds = userIds; 893 } 894 895 /** 896 * Version of registerService that takes the name of a service component to bind to. 897 */ 898 private void registerService(final ComponentName name, final int userid) { 899 synchronized (mMutex) { 900 registerServiceLocked(name, userid); 901 } 902 } 903 904 /** 905 * Inject a system service into the management list. 906 */ 907 public void registerSystemService(final ComponentName name, final int userid) { 908 synchronized (mMutex) { 909 registerServiceLocked(name, userid, true /* isSystem */); 910 } 911 } 912 913 private void registerServiceLocked(final ComponentName name, final int userid) { 914 registerServiceLocked(name, userid, false /* isSystem */); 915 } 916 917 private void registerServiceLocked(final ComponentName name, final int userid, 918 final boolean isSystem) { 919 if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid); 920 921 final String servicesBindingTag = name.toString() + "/" + userid; 922 if (mServicesBinding.contains(servicesBindingTag)) { 923 Slog.v(TAG, "Not registering " + name + " as bind is already in progress"); 924 // stop registering this thing already! we're working on it 925 return; 926 } 927 mServicesBinding.add(servicesBindingTag); 928 929 final int N = mServices.size(); 930 for (int i = N - 1; i >= 0; i--) { 931 final ManagedServiceInfo info = mServices.get(i); 932 if (name.equals(info.component) 933 && info.userid == userid) { 934 // cut old connections 935 Slog.v(TAG, " disconnecting old " + getCaption() + ": " + info.service); 936 removeServiceLocked(i); 937 if (info.connection != null) { 938 try { 939 mContext.unbindService(info.connection); 940 } catch (IllegalArgumentException e) { 941 Slog.e(TAG, "failed to unbind " + name, e); 942 } 943 } 944 } 945 } 946 947 Intent intent = new Intent(mConfig.serviceInterface); 948 intent.setComponent(name); 949 950 intent.putExtra(Intent.EXTRA_CLIENT_LABEL, mConfig.clientLabel); 951 952 final PendingIntent pendingIntent = PendingIntent.getActivity( 953 mContext, 0, new Intent(mConfig.settingsAction), 0); 954 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent); 955 956 ApplicationInfo appInfo = null; 957 try { 958 appInfo = mContext.getPackageManager().getApplicationInfo( 959 name.getPackageName(), 0); 960 } catch (NameNotFoundException e) { 961 // Ignore if the package doesn't exist we won't be able to bind to the service. 962 } 963 final int targetSdkVersion = 964 appInfo != null ? appInfo.targetSdkVersion : Build.VERSION_CODES.BASE; 965 966 try { 967 Slog.v(TAG, "binding: " + intent); 968 ServiceConnection serviceConnection = new ServiceConnection() { 969 IInterface mService; 970 971 @Override 972 public void onServiceConnected(ComponentName name, IBinder binder) { 973 boolean added = false; 974 ManagedServiceInfo info = null; 975 synchronized (mMutex) { 976 mServicesRebinding.remove(servicesBindingTag); 977 mServicesBinding.remove(servicesBindingTag); 978 try { 979 mService = asInterface(binder); 980 info = newServiceInfo(mService, name, 981 userid, isSystem, this, targetSdkVersion); 982 binder.linkToDeath(info, 0); 983 added = mServices.add(info); 984 } catch (RemoteException e) { 985 // already dead 986 } 987 } 988 if (added) { 989 onServiceAdded(info); 990 } 991 } 992 993 @Override 994 public void onServiceDisconnected(ComponentName name) { 995 mServicesBinding.remove(servicesBindingTag); 996 Slog.v(TAG, getCaption() + " connection lost: " + name); 997 } 998 999 @Override 1000 public void onBindingDied(ComponentName name) { 1001 Slog.w(TAG, getCaption() + " binding died: " + name); 1002 synchronized (mMutex) { 1003 mServicesBinding.remove(servicesBindingTag); 1004 try { 1005 mContext.unbindService(this); 1006 } catch (IllegalArgumentException e) { 1007 Slog.e(TAG, "failed to unbind " + name, e); 1008 } 1009 if (!mServicesRebinding.contains(servicesBindingTag)) { 1010 mServicesRebinding.add(servicesBindingTag); 1011 mHandler.postDelayed(new Runnable() { 1012 @Override 1013 public void run() { 1014 registerService(name, userid); 1015 } 1016 }, ON_BINDING_DIED_REBIND_DELAY_MS); 1017 } else { 1018 Slog.v(TAG, getCaption() + " not rebinding as " 1019 + "a previous rebind attempt was made: " + name); 1020 } 1021 } 1022 } 1023 }; 1024 if (!mContext.bindServiceAsUser(intent, 1025 serviceConnection, 1026 BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT, 1027 new UserHandle(userid))) { 1028 mServicesBinding.remove(servicesBindingTag); 1029 Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent); 1030 return; 1031 } 1032 } catch (SecurityException ex) { 1033 mServicesBinding.remove(servicesBindingTag); 1034 Slog.e(TAG, "Unable to bind " + getCaption() + " service: " + intent, ex); 1035 } 1036 } 1037 1038 /** 1039 * Remove a service for the given user by ComponentName 1040 */ 1041 private void unregisterService(ComponentName name, int userid) { 1042 synchronized (mMutex) { 1043 unregisterServiceLocked(name, userid); 1044 } 1045 } 1046 1047 private void unregisterServiceLocked(ComponentName name, int userid) { 1048 final int N = mServices.size(); 1049 for (int i = N - 1; i >= 0; i--) { 1050 final ManagedServiceInfo info = mServices.get(i); 1051 if (name.equals(info.component) && info.userid == userid) { 1052 removeServiceLocked(i); 1053 if (info.connection != null) { 1054 try { 1055 mContext.unbindService(info.connection); 1056 } catch (IllegalArgumentException ex) { 1057 // something happened to the service: we think we have a connection 1058 // but it's bogus. 1059 Slog.e(TAG, getCaption() + " " + name + " could not be unbound: " + ex); 1060 } 1061 } 1062 } 1063 } 1064 } 1065 1066 /** 1067 * Removes a service from the list but does not unbind 1068 * 1069 * @return the removed service. 1070 */ 1071 private ManagedServiceInfo removeServiceImpl(IInterface service, final int userid) { 1072 if (DEBUG) Slog.d(TAG, "removeServiceImpl service=" + service + " u=" + userid); 1073 ManagedServiceInfo serviceInfo = null; 1074 synchronized (mMutex) { 1075 final int N = mServices.size(); 1076 for (int i = N - 1; i >= 0; i--) { 1077 final ManagedServiceInfo info = mServices.get(i); 1078 if (info.service.asBinder() == service.asBinder() && info.userid == userid) { 1079 Slog.d(TAG, "Removing active service " + info.component); 1080 serviceInfo = removeServiceLocked(i); 1081 } 1082 } 1083 } 1084 return serviceInfo; 1085 } 1086 1087 private ManagedServiceInfo removeServiceLocked(int i) { 1088 final ManagedServiceInfo info = mServices.remove(i); 1089 onServiceRemovedLocked(info); 1090 return info; 1091 } 1092 1093 private void checkNotNull(IInterface service) { 1094 if (service == null) { 1095 throw new IllegalArgumentException(getCaption() + " must not be null"); 1096 } 1097 } 1098 1099 private ManagedServiceInfo registerServiceImpl(final IInterface service, 1100 final ComponentName component, final int userid) { 1101 ManagedServiceInfo info = newServiceInfo(service, component, userid, 1102 true /*isSystem*/, null /*connection*/, Build.VERSION_CODES.LOLLIPOP); 1103 return registerServiceImpl(info); 1104 } 1105 1106 private ManagedServiceInfo registerServiceImpl(ManagedServiceInfo info) { 1107 synchronized (mMutex) { 1108 try { 1109 info.service.asBinder().linkToDeath(info, 0); 1110 mServices.add(info); 1111 return info; 1112 } catch (RemoteException e) { 1113 // already dead 1114 } 1115 } 1116 return null; 1117 } 1118 1119 /** 1120 * Removes a service from the list and unbinds. 1121 */ 1122 private void unregisterServiceImpl(IInterface service, int userid) { 1123 ManagedServiceInfo info = removeServiceImpl(service, userid); 1124 if (info != null && info.connection != null && !info.isGuest(this)) { 1125 mContext.unbindService(info.connection); 1126 } 1127 } 1128 1129 public class ManagedServiceInfo implements IBinder.DeathRecipient { 1130 public IInterface service; 1131 public ComponentName component; 1132 public int userid; 1133 public boolean isSystem; 1134 public ServiceConnection connection; 1135 public int targetSdkVersion; 1136 1137 public ManagedServiceInfo(IInterface service, ComponentName component, 1138 int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion) { 1139 this.service = service; 1140 this.component = component; 1141 this.userid = userid; 1142 this.isSystem = isSystem; 1143 this.connection = connection; 1144 this.targetSdkVersion = targetSdkVersion; 1145 } 1146 1147 public boolean isGuest(ManagedServices host) { 1148 return ManagedServices.this != host; 1149 } 1150 1151 public ManagedServices getOwner() { 1152 return ManagedServices.this; 1153 } 1154 1155 @Override 1156 public String toString() { 1157 return new StringBuilder("ManagedServiceInfo[") 1158 .append("component=").append(component) 1159 .append(",userid=").append(userid) 1160 .append(",isSystem=").append(isSystem) 1161 .append(",targetSdkVersion=").append(targetSdkVersion) 1162 .append(",connection=").append(connection == null ? null : "<connection>") 1163 .append(",service=").append(service) 1164 .append(']').toString(); 1165 } 1166 1167 public void writeToProto(ProtoOutputStream proto, long fieldId, ManagedServices host) { 1168 final long token = proto.start(fieldId); 1169 component.writeToProto(proto, ManagedServiceInfoProto.COMPONENT); 1170 proto.write(ManagedServiceInfoProto.USER_ID, userid); 1171 proto.write(ManagedServiceInfoProto.SERVICE, service.getClass().getName()); 1172 proto.write(ManagedServiceInfoProto.IS_SYSTEM, isSystem); 1173 proto.write(ManagedServiceInfoProto.IS_GUEST, isGuest(host)); 1174 proto.end(token); 1175 } 1176 1177 public boolean enabledAndUserMatches(int nid) { 1178 if (!isEnabledForCurrentProfiles()) { 1179 return false; 1180 } 1181 if (this.userid == UserHandle.USER_ALL) return true; 1182 if (this.isSystem) return true; 1183 if (nid == UserHandle.USER_ALL || nid == this.userid) return true; 1184 return supportsProfiles() 1185 && mUserProfiles.isCurrentProfile(nid) 1186 && isPermittedForProfile(nid); 1187 } 1188 1189 public boolean supportsProfiles() { 1190 return targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP; 1191 } 1192 1193 @Override 1194 public void binderDied() { 1195 if (DEBUG) Slog.d(TAG, "binderDied"); 1196 // Remove the service, but don't unbind from the service. The system will bring the 1197 // service back up, and the onServiceConnected handler will read the service with the 1198 // new binding. If this isn't a bound service, and is just a registered 1199 // service, just removing it from the list is all we need to do anyway. 1200 removeServiceImpl(this.service, this.userid); 1201 } 1202 1203 /** convenience method for looking in mEnabledServicesForCurrentProfiles */ 1204 public boolean isEnabledForCurrentProfiles() { 1205 if (this.isSystem) return true; 1206 if (this.connection == null) return false; 1207 return mEnabledServicesForCurrentProfiles.contains(this.component); 1208 } 1209 1210 /** 1211 * Returns true if this service is allowed to receive events for the given userId. A 1212 * managed profile owner can disallow non-system services running outside of the profile 1213 * from receiving events from the profile. 1214 */ 1215 public boolean isPermittedForProfile(int userId) { 1216 if (!mUserProfiles.isManagedProfile(userId)) { 1217 return true; 1218 } 1219 DevicePolicyManager dpm = 1220 (DevicePolicyManager) mContext.getSystemService(DEVICE_POLICY_SERVICE); 1221 final long identity = Binder.clearCallingIdentity(); 1222 try { 1223 return dpm.isNotificationListenerServicePermitted( 1224 component.getPackageName(), userId); 1225 } finally { 1226 Binder.restoreCallingIdentity(identity); 1227 } 1228 } 1229 } 1230 1231 /** convenience method for looking in mEnabledServicesForCurrentProfiles */ 1232 public boolean isComponentEnabledForCurrentProfiles(ComponentName component) { 1233 return mEnabledServicesForCurrentProfiles.contains(component); 1234 } 1235 1236 public static class UserProfiles { 1237 // Profiles of the current user. 1238 private final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>(); 1239 1240 public void updateCache(@NonNull Context context) { 1241 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 1242 if (userManager != null) { 1243 int currentUserId = ActivityManager.getCurrentUser(); 1244 List<UserInfo> profiles = userManager.getProfiles(currentUserId); 1245 synchronized (mCurrentProfiles) { 1246 mCurrentProfiles.clear(); 1247 for (UserInfo user : profiles) { 1248 mCurrentProfiles.put(user.id, user); 1249 } 1250 } 1251 } 1252 } 1253 1254 public int[] getCurrentProfileIds() { 1255 synchronized (mCurrentProfiles) { 1256 int[] users = new int[mCurrentProfiles.size()]; 1257 final int N = mCurrentProfiles.size(); 1258 for (int i = 0; i < N; ++i) { 1259 users[i] = mCurrentProfiles.keyAt(i); 1260 } 1261 return users; 1262 } 1263 } 1264 1265 public boolean isCurrentProfile(int userId) { 1266 synchronized (mCurrentProfiles) { 1267 return mCurrentProfiles.get(userId) != null; 1268 } 1269 } 1270 1271 public boolean isManagedProfile(int userId) { 1272 synchronized (mCurrentProfiles) { 1273 UserInfo user = mCurrentProfiles.get(userId); 1274 return user != null && user.isManagedProfile(); 1275 } 1276 } 1277 } 1278 1279 public static class Config { 1280 public String caption; 1281 public String serviceInterface; 1282 public String secureSettingName; 1283 public String secondarySettingName; 1284 public String xmlTag; 1285 public String bindPermission; 1286 public String settingsAction; 1287 public int clientLabel; 1288 } 1289 } 1290