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