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