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.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR; 20 import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT; 21 import static android.content.Context.BIND_AUTO_CREATE; 22 import static android.content.Context.BIND_FOREGROUND_SERVICE; 23 import static android.content.Context.DEVICE_POLICY_SERVICE; 24 import static android.os.UserHandle.USER_ALL; 25 import static android.os.UserHandle.USER_SYSTEM; 26 import static android.service.notification.NotificationListenerService.META_DATA_DEFAULT_AUTOBIND; 27 28 import static com.android.server.notification.Flags.FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER; 29 import static com.android.server.notification.Flags.managedServicesConcurrentMultiuser; 30 import static com.android.server.notification.NotificationManagerService.privateSpaceFlagsEnabled; 31 32 import android.annotation.FlaggedApi; 33 import android.annotation.NonNull; 34 import android.app.ActivityManager; 35 import android.app.ActivityOptions; 36 import android.app.PendingIntent; 37 import android.app.admin.DevicePolicyManager; 38 import android.content.ComponentName; 39 import android.content.ContentResolver; 40 import android.content.Context; 41 import android.content.Intent; 42 import android.content.ServiceConnection; 43 import android.content.pm.ApplicationInfo; 44 import android.content.pm.IPackageManager; 45 import android.content.pm.PackageManager; 46 import android.content.pm.PackageManager.NameNotFoundException; 47 import android.content.pm.ResolveInfo; 48 import android.content.pm.ServiceInfo; 49 import android.content.pm.UserInfo; 50 import android.os.Binder; 51 import android.os.Build; 52 import android.os.Handler; 53 import android.os.IBinder; 54 import android.os.IInterface; 55 import android.os.Looper; 56 import android.os.RemoteException; 57 import android.os.UserHandle; 58 import android.os.UserManager; 59 import android.provider.Settings; 60 import android.service.notification.ManagedServiceInfoProto; 61 import android.service.notification.ManagedServicesProto; 62 import android.service.notification.ManagedServicesProto.ServiceProto; 63 import android.text.TextUtils; 64 import android.util.ArrayMap; 65 import android.util.ArraySet; 66 import android.util.IntArray; 67 import android.util.Log; 68 import android.util.Pair; 69 import android.util.Slog; 70 import android.util.SparseArray; 71 import android.util.SparseSetArray; 72 import android.util.proto.ProtoOutputStream; 73 74 import com.android.internal.annotations.GuardedBy; 75 import com.android.internal.annotations.VisibleForTesting; 76 import com.android.internal.util.XmlUtils; 77 import com.android.internal.util.function.TriPredicate; 78 import com.android.modules.utils.TypedXmlPullParser; 79 import com.android.modules.utils.TypedXmlSerializer; 80 import com.android.server.LocalServices; 81 import com.android.server.notification.NotificationManagerService.DumpFilter; 82 import com.android.server.pm.UserManagerInternal; 83 import com.android.server.utils.TimingsTraceAndSlog; 84 85 import org.xmlpull.v1.XmlPullParser; 86 import org.xmlpull.v1.XmlPullParserException; 87 88 import java.io.IOException; 89 import java.io.PrintWriter; 90 import java.util.ArrayList; 91 import java.util.Arrays; 92 import java.util.HashSet; 93 import java.util.List; 94 import java.util.Objects; 95 import java.util.Set; 96 97 /** 98 * Manages the lifecycle of application-provided services bound by system server. 99 * 100 * Services managed by this helper must have: 101 * - An associated system settings value with a list of enabled component names. 102 * - A well-known action for services to use in their intent-filter. 103 * - A system permission for services to require in order to ensure system has exclusive binding. 104 * - A settings page for user configuration of enabled services, and associated intent action. 105 * - A remote interface definition (aidl) provided by the service used for communication. 106 */ 107 abstract public class ManagedServices { 108 protected final String TAG = getClass().getSimpleName().replace('$', '.'); 109 protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 110 111 private static final int ON_BINDING_DIED_REBIND_DELAY_MS = 10000; 112 protected static final String ENABLED_SERVICES_SEPARATOR = ":"; 113 private static final String DB_VERSION_1 = "1"; 114 private static final String DB_VERSION_2 = "2"; 115 private static final String DB_VERSION_3 = "3"; 116 117 118 /** 119 * List of components and apps that can have running {@link ManagedServices}. 120 */ 121 static final String TAG_MANAGED_SERVICES = "service_listing"; 122 static final String ATT_APPROVED_LIST = "approved"; 123 static final String ATT_USER_ID = "user"; 124 static final String ATT_IS_PRIMARY = "primary"; 125 static final String ATT_VERSION = "version"; 126 static final String ATT_DEFAULTS = "defaults"; 127 static final String ATT_USER_SET = "user_set_services"; 128 static final String ATT_USER_SET_OLD = "user_set"; 129 static final String ATT_USER_CHANGED = "user_changed"; 130 131 static final String DB_VERSION = "4"; 132 133 static final int APPROVAL_BY_PACKAGE = 0; 134 static final int APPROVAL_BY_COMPONENT = 1; 135 136 protected final Context mContext; 137 protected final Object mMutex; 138 private final UserProfiles mUserProfiles; 139 protected final IPackageManager mPm; 140 protected final UserManager mUm; 141 protected final UserManagerInternal mUmInternal; 142 private final Config mConfig; 143 private final Handler mHandler = new Handler(Looper.getMainLooper()); 144 145 // contains connections to all connected services, including app services 146 // and system services 147 @GuardedBy("mMutex") 148 private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<>(); 149 /** 150 * The services that have been bound by us. If the service is also connected, it will also 151 * be in {@link #mServices}. 152 */ 153 @GuardedBy("mMutex") 154 private final ArrayList<Pair<ComponentName, Integer>> mServicesBound = new ArrayList<>(); 155 @GuardedBy("mMutex") 156 private final ArraySet<Pair<ComponentName, Integer>> mServicesRebinding = new ArraySet<>(); 157 // we need these packages to be protected because classes that inherit from it need to see it 158 protected final Object mDefaultsLock = new Object(); 159 @GuardedBy("mDefaultsLock") 160 protected final ArraySet<ComponentName> mDefaultComponents = new ArraySet<>(); 161 @GuardedBy("mDefaultsLock") 162 protected final ArraySet<String> mDefaultPackages = new ArraySet<>(); 163 164 // lists the component names of all enabled (and therefore potentially connected) 165 // app services for each user. This is intended to support a concurrent multi-user environment. 166 // key value is the resolved userId. 167 @GuardedBy("mMutex") 168 private final SparseArray<ArraySet<ComponentName>> mEnabledServicesByUser = 169 new SparseArray<>(); 170 // Just the packages from mEnabledServicesByUser 171 // This is intended to support a concurrent multi-user environment. 172 // key value is the resolved userId. 173 @GuardedBy("mMutex") 174 private final SparseArray<ArraySet<String>> mEnabledServicesPackageNamesByUser = 175 new SparseArray<>(); 176 // Per user id, list of enabled packages that have nevertheless asked not to be run 177 @GuardedBy("mSnoozing") 178 private final SparseSetArray<ComponentName> mSnoozing = new SparseSetArray<>(); 179 180 // List of approved packages or components (by user, then by primary/secondary) that are 181 // allowed to be bound as managed services. A package or component appearing in this list does 182 // not mean that we are currently bound to said package/component. 183 @GuardedBy("mApproved") 184 protected final ArrayMap<Integer, ArrayMap<Boolean, ArraySet<String>>> mApproved = 185 new ArrayMap<>(); 186 // List of packages or components (by user) that are configured to be enabled/disabled 187 // explicitly by the user 188 @GuardedBy("mApproved") 189 protected ArrayMap<Integer, ArraySet<String>> mUserSetServices = new ArrayMap<>(); 190 @GuardedBy("mApproved") 191 protected ArrayMap<Integer, Boolean> mIsUserChanged = new ArrayMap<>(); 192 193 // True if approved services are stored in xml, not settings. 194 private boolean mUseXml; 195 196 // Whether managed services are approved individually or package wide 197 protected int mApprovalLevel; 198 ManagedServices(Context context, Object mutex, UserProfiles userProfiles, IPackageManager pm)199 public ManagedServices(Context context, Object mutex, UserProfiles userProfiles, 200 IPackageManager pm) { 201 mContext = context; 202 mMutex = mutex; 203 mUserProfiles = userProfiles; 204 mPm = pm; 205 mConfig = getConfig(); 206 mApprovalLevel = APPROVAL_BY_COMPONENT; 207 mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 208 mUmInternal = LocalServices.getService(UserManagerInternal.class); 209 // Initialize for the current user. 210 mEnabledServicesByUser.put(UserHandle.USER_CURRENT, new ArraySet<>()); 211 mEnabledServicesPackageNamesByUser.put(UserHandle.USER_CURRENT, new ArraySet<>()); 212 } 213 getConfig()214 abstract protected Config getConfig(); 215 getCaption()216 private String getCaption() { 217 return mConfig.caption; 218 } 219 asInterface(IBinder binder)220 abstract protected IInterface asInterface(IBinder binder); 221 checkType(IInterface service)222 abstract protected boolean checkType(IInterface service); 223 onServiceAdded(ManagedServiceInfo info)224 abstract protected void onServiceAdded(ManagedServiceInfo info); 225 ensureFilters(ServiceInfo si, int userId)226 abstract protected void ensureFilters(ServiceInfo si, int userId); 227 getServices()228 protected List<ManagedServiceInfo> getServices() { 229 synchronized (mMutex) { 230 List<ManagedServiceInfo> services = new ArrayList<>(mServices); 231 return services; 232 } 233 } 234 addDefaultComponentOrPackage(String packageOrComponent)235 protected void addDefaultComponentOrPackage(String packageOrComponent) { 236 if (!TextUtils.isEmpty(packageOrComponent)) { 237 synchronized (mDefaultsLock) { 238 if (mApprovalLevel == APPROVAL_BY_PACKAGE) { 239 mDefaultPackages.add(packageOrComponent); 240 return; 241 } 242 ComponentName cn = ComponentName.unflattenFromString(packageOrComponent); 243 if (cn != null && mApprovalLevel == APPROVAL_BY_COMPONENT) { 244 mDefaultPackages.add(cn.getPackageName()); 245 mDefaultComponents.add(cn); 246 return; 247 } 248 } 249 } 250 } 251 loadDefaultsFromConfig()252 protected abstract void loadDefaultsFromConfig(); 253 isDefaultComponentOrPackage(String packageOrComponent)254 boolean isDefaultComponentOrPackage(String packageOrComponent) { 255 synchronized (mDefaultsLock) { 256 ComponentName cn = ComponentName.unflattenFromString(packageOrComponent); 257 if (cn == null) { 258 return mDefaultPackages.contains(packageOrComponent); 259 } else { 260 return mDefaultComponents.contains(cn); 261 } 262 } 263 } 264 getDefaultComponents()265 ArraySet<ComponentName> getDefaultComponents() { 266 synchronized (mDefaultsLock) { 267 return new ArraySet<>(mDefaultComponents); 268 } 269 } 270 getDefaultPackages()271 ArraySet<String> getDefaultPackages() { 272 synchronized (mDefaultsLock) { 273 return new ArraySet<>(mDefaultPackages); 274 } 275 } 276 277 /** 278 * When resetting a package, we need to enable default components that belong to that packages 279 * we also need to disable components that are not default to return the managed service state 280 * to when a new android device is first turned on for that package. 281 * 282 * @param packageName package to reset. 283 * @param userId the android user id 284 * @return a list of components that were permitted 285 */ 286 @NonNull resetComponents(String packageName, int userId)287 ArrayMap<Boolean, ArrayList<ComponentName>> resetComponents(String packageName, int userId) { 288 // components that we want to enable 289 ArrayList<ComponentName> componentsToEnable; 290 // components that were removed 291 ArrayList<ComponentName> disabledComponents; 292 // all components that are enabled now 293 ArraySet<ComponentName> enabledComponents = new ArraySet<>(getAllowedComponents(userId)); 294 295 boolean changed = false; 296 297 synchronized (mDefaultsLock) { 298 componentsToEnable = new ArrayList<>(mDefaultComponents.size()); 299 disabledComponents = new ArrayList<>(mDefaultComponents.size()); 300 301 // record all components that are enabled but should not be by default 302 for (int i = 0; i < mDefaultComponents.size() && enabledComponents.size() > 0; i++) { 303 ComponentName currentDefault = mDefaultComponents.valueAt(i); 304 if (packageName.equals(currentDefault.getPackageName()) 305 && !enabledComponents.contains(currentDefault)) { 306 componentsToEnable.add(currentDefault); 307 } 308 } 309 synchronized (mApproved) { 310 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get( 311 userId); 312 if (approvedByType != null) { 313 final int M = approvedByType.size(); 314 for (int j = 0; j < M; j++) { 315 final ArraySet<String> approved = approvedByType.valueAt(j); 316 for (int i = 0; i < enabledComponents.size(); i++) { 317 ComponentName currentComponent = enabledComponents.valueAt(i); 318 if (packageName.equals(currentComponent.getPackageName()) 319 && !mDefaultComponents.contains(currentComponent)) { 320 if (approved.remove(currentComponent.flattenToString())) { 321 disabledComponents.add(currentComponent); 322 clearUserSetFlagLocked(currentComponent, userId); 323 changed = true; 324 } 325 } 326 } 327 for (int i = 0; i < componentsToEnable.size(); i++) { 328 ComponentName candidate = componentsToEnable.get(i); 329 changed |= approved.add(candidate.flattenToString()); 330 } 331 } 332 333 } 334 } 335 } 336 if (changed) rebindServices(false, USER_ALL); 337 338 ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>(); 339 changes.put(true, componentsToEnable); 340 changes.put(false, disabledComponents); 341 342 return changes; 343 } 344 345 @GuardedBy("mApproved") clearUserSetFlagLocked(ComponentName component, int userId)346 private boolean clearUserSetFlagLocked(ComponentName component, int userId) { 347 String approvedValue = getApprovedValue(component.flattenToString()); 348 ArraySet<String> userSet = mUserSetServices.get(userId); 349 return userSet != null && userSet.remove(approvedValue); 350 } 351 getBindFlags()352 protected int getBindFlags() { 353 return BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_ALLOW_WHITELIST_MANAGEMENT; 354 } 355 onServiceRemovedLocked(ManagedServiceInfo removed)356 protected void onServiceRemovedLocked(ManagedServiceInfo removed) { } 357 newServiceInfo(IInterface service, ComponentName component, int userId, boolean isSystem, ServiceConnection connection, int targetSdkVersion, int uid)358 private ManagedServiceInfo newServiceInfo(IInterface service, 359 ComponentName component, int userId, boolean isSystem, ServiceConnection connection, 360 int targetSdkVersion, int uid) { 361 return new ManagedServiceInfo(service, component, userId, isSystem, connection, 362 targetSdkVersion, uid); 363 } 364 onBootPhaseAppsCanStart()365 public void onBootPhaseAppsCanStart() {} 366 dump(PrintWriter pw, DumpFilter filter)367 public void dump(PrintWriter pw, DumpFilter filter) { 368 pw.println(" Allowed " + getCaption() + "s:"); 369 synchronized (mApproved) { 370 final int N = mApproved.size(); 371 for (int i = 0; i < N; i++) { 372 final int userId = mApproved.keyAt(i); 373 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i); 374 final Boolean userChanged = mIsUserChanged.get(userId); 375 if (approvedByType != null) { 376 final int M = approvedByType.size(); 377 for (int j = 0; j < M; j++) { 378 final boolean isPrimary = approvedByType.keyAt(j); 379 final ArraySet<String> approved = approvedByType.valueAt(j); 380 if (approvedByType != null && approvedByType.size() > 0) { 381 pw.println(" " + String.join(ENABLED_SERVICES_SEPARATOR, approved) 382 + " (user: " + userId + " isPrimary: " + isPrimary 383 + (userChanged == null ? "" : " isUserChanged: " 384 + userChanged) + ")"); 385 } 386 } 387 } 388 } 389 pw.println(" Has user set:"); 390 Set<Integer> userIds = mUserSetServices.keySet(); 391 for (int userId : userIds) { 392 if (mIsUserChanged.get(userId) == null) { 393 pw.println(" userId=" + userId + " value=" 394 + (mUserSetServices.get(userId))); 395 } 396 } 397 } 398 399 synchronized (mMutex) { 400 if (managedServicesConcurrentMultiuser()) { 401 for (int i = 0; i < mEnabledServicesByUser.size(); i++) { 402 final int userId = mEnabledServicesByUser.keyAt(i); 403 final ArraySet<ComponentName> componentNames = 404 mEnabledServicesByUser.get(userId); 405 String userString = userId == UserHandle.USER_CURRENT 406 ? "current profiles" : "user " + Integer.toString(userId); 407 pw.println(" All " + getCaption() + "s (" + componentNames.size() 408 + ") enabled for " + userString + ":"); 409 for (ComponentName cmpt : componentNames) { 410 if (filter != null && !filter.matches(cmpt)) continue; 411 pw.println(" " + cmpt); 412 } 413 } 414 } else { 415 final ArraySet<ComponentName> enabledServicesForCurrentProfiles = 416 mEnabledServicesByUser.get(UserHandle.USER_CURRENT); 417 pw.println(" All " + getCaption() + "s (" 418 + enabledServicesForCurrentProfiles.size() 419 + ") enabled for current profiles:"); 420 for (ComponentName cmpt : enabledServicesForCurrentProfiles) { 421 if (filter != null && !filter.matches(cmpt)) continue; 422 pw.println(" " + cmpt); 423 } 424 } 425 426 pw.println(" Live " + getCaption() + "s (" + mServices.size() + "):"); 427 for (ManagedServiceInfo info : mServices) { 428 if (filter != null && !filter.matches(info.component)) continue; 429 pw.println(" " + info.component 430 + " (user " + info.userid + "): " + info.service 431 + (info.isSystem ? " SYSTEM" : "") 432 + (info.isGuest(this) ? " GUEST" : "")); 433 } 434 } 435 436 final SparseSetArray<ComponentName> snoozingComponents; 437 synchronized (mSnoozing) { 438 snoozingComponents = new SparseSetArray<>(mSnoozing); 439 } 440 pw.println(" Snoozed " + getCaption() + "s (" 441 + snoozingComponents.size() + "):"); 442 for (int i = 0; i < snoozingComponents.size(); i++) { 443 pw.println(" User: " + snoozingComponents.keyAt(i)); 444 for (ComponentName name : snoozingComponents.valuesAt(i)) { 445 final ServiceInfo info = getServiceInfo(name, snoozingComponents.keyAt(i)); 446 pw.println(" " + name.flattenToShortString() + (isAutobindAllowed(info) ? "" 447 : " (META_DATA_DEFAULT_AUTOBIND=false)")); 448 } 449 } 450 } 451 dump(ProtoOutputStream proto, DumpFilter filter)452 public void dump(ProtoOutputStream proto, DumpFilter filter) { 453 proto.write(ManagedServicesProto.CAPTION, getCaption()); 454 synchronized (mApproved) { 455 final int N = mApproved.size(); 456 for (int i = 0; i < N; i++) { 457 final int userId = mApproved.keyAt(i); 458 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i); 459 if (approvedByType != null) { 460 final int M = approvedByType.size(); 461 for (int j = 0; j < M; j++) { 462 final boolean isPrimary = approvedByType.keyAt(j); 463 final ArraySet<String> approved = approvedByType.valueAt(j); 464 if (approvedByType != null && approvedByType.size() > 0) { 465 final long sToken = proto.start(ManagedServicesProto.APPROVED); 466 for (String s : approved) { 467 proto.write(ServiceProto.NAME, s); 468 } 469 proto.write(ServiceProto.USER_ID, userId); 470 proto.write(ServiceProto.IS_PRIMARY, isPrimary); 471 proto.end(sToken); 472 } 473 } 474 } 475 } 476 } 477 478 synchronized (mMutex) { 479 if (managedServicesConcurrentMultiuser()) { 480 for (int i = 0; i < mEnabledServicesByUser.size(); i++) { 481 final int userId = mEnabledServicesByUser.keyAt(i); 482 final ArraySet<ComponentName> componentNames = 483 mEnabledServicesByUser.get(userId); 484 for (ComponentName cmpt : componentNames) { 485 if (filter != null && !filter.matches(cmpt)) continue; 486 cmpt.dumpDebug(proto, ManagedServicesProto.ENABLED); 487 } 488 } 489 } else { 490 final ArraySet<ComponentName> enabledServicesForCurrentProfiles = 491 mEnabledServicesByUser.get(UserHandle.USER_CURRENT); 492 for (ComponentName cmpt : enabledServicesForCurrentProfiles) { 493 if (filter != null && !filter.matches(cmpt)) continue; 494 cmpt.dumpDebug(proto, ManagedServicesProto.ENABLED); 495 } 496 } 497 for (ManagedServiceInfo info : mServices) { 498 if (filter != null && !filter.matches(info.component)) continue; 499 info.dumpDebug(proto, ManagedServicesProto.LIVE_SERVICES, this); 500 } 501 } 502 503 synchronized (mSnoozing) { 504 for (int i = 0; i < mSnoozing.size(); i++) { 505 long token = proto.start(ManagedServicesProto.SNOOZED); 506 proto.write(ManagedServicesProto.SnoozedServices.USER_ID, 507 mSnoozing.keyAt(i)); 508 for (ComponentName name : mSnoozing.valuesAt(i)) { 509 name.dumpDebug(proto, ManagedServicesProto.SnoozedServices.SNOOZED); 510 } 511 proto.end(token); 512 } 513 } 514 } 515 onSettingRestored(String element, String value, int backupSdkInt, int userId)516 protected void onSettingRestored(String element, String value, int backupSdkInt, int userId) { 517 if (!mUseXml) { 518 Slog.d(TAG, "Restored managed service setting: " + element); 519 if (mConfig.secureSettingName.equals(element) || 520 (mConfig.secondarySettingName != null 521 && mConfig.secondarySettingName.equals(element))) { 522 if (backupSdkInt < Build.VERSION_CODES.O) { 523 // automatic system grants were added in O, so append the approved apps 524 // rather than wiping out the setting 525 String currentSetting = 526 getApproved(userId, mConfig.secureSettingName.equals(element)); 527 if (!TextUtils.isEmpty(currentSetting)) { 528 if (!TextUtils.isEmpty(value)) { 529 value = value + ENABLED_SERVICES_SEPARATOR + currentSetting; 530 } else { 531 value = currentSetting; 532 } 533 } 534 } 535 if (shouldReflectToSettings()) { 536 Settings.Secure.putStringForUser( 537 mContext.getContentResolver(), element, value, userId); 538 } 539 540 for (UserInfo user : mUm.getUsers()) { 541 addApprovedList(value, user.id, mConfig.secureSettingName.equals(element)); 542 } 543 Slog.d(TAG, "Done loading approved values from settings"); 544 rebindServices(false, userId); 545 } 546 } 547 } 548 writeDefaults(TypedXmlSerializer out)549 void writeDefaults(TypedXmlSerializer out) throws IOException { 550 synchronized (mDefaultsLock) { 551 List<String> componentStrings = new ArrayList<>(mDefaultComponents.size()); 552 for (int i = 0; i < mDefaultComponents.size(); i++) { 553 componentStrings.add(mDefaultComponents.valueAt(i).flattenToString()); 554 } 555 String defaults = String.join(ENABLED_SERVICES_SEPARATOR, componentStrings); 556 out.attribute(null, ATT_DEFAULTS, defaults); 557 } 558 } 559 writeXml(TypedXmlSerializer out, boolean forBackup, int userId)560 public void writeXml(TypedXmlSerializer out, boolean forBackup, int userId) throws IOException { 561 out.startTag(null, getConfig().xmlTag); 562 563 out.attributeInt(null, ATT_VERSION, Integer.parseInt(DB_VERSION)); 564 565 writeDefaults(out); 566 567 if (forBackup) { 568 trimApprovedListsAccordingToInstalledServices(userId); 569 } 570 571 synchronized (mApproved) { 572 final int N = mApproved.size(); 573 for (int i = 0; i < N; i++) { 574 final int approvedUserId = mApproved.keyAt(i); 575 if (forBackup && approvedUserId != userId) { 576 continue; 577 } 578 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i); 579 final Boolean isUserChanged = mIsUserChanged.get(approvedUserId); 580 if (approvedByType != null) { 581 final int M = approvedByType.size(); 582 for (int j = 0; j < M; j++) { 583 final boolean isPrimary = approvedByType.keyAt(j); 584 final Set<String> approved = approvedByType.valueAt(j); 585 final Set<String> userSet = mUserSetServices.get(approvedUserId); 586 if (approved != null || userSet != null || isUserChanged != null) { 587 String allowedItems = approved == null 588 ? "" 589 : String.join(ENABLED_SERVICES_SEPARATOR, approved); 590 out.startTag(null, TAG_MANAGED_SERVICES); 591 out.attribute(null, ATT_APPROVED_LIST, allowedItems); 592 out.attributeInt(null, ATT_USER_ID, approvedUserId); 593 out.attributeBoolean(null, ATT_IS_PRIMARY, isPrimary); 594 if (isUserChanged != null) { 595 out.attributeBoolean(null, ATT_USER_CHANGED, isUserChanged); 596 } else if (userSet != null) { 597 String userSetItems = 598 String.join(ENABLED_SERVICES_SEPARATOR, userSet); 599 out.attribute(null, ATT_USER_SET, userSetItems); 600 } 601 writeExtraAttributes(out, approvedUserId); 602 out.endTag(null, TAG_MANAGED_SERVICES); 603 604 if (!forBackup && isPrimary) { 605 if (shouldReflectToSettings()) { 606 // Also write values to settings, for observers who haven't 607 // migrated yet 608 Settings.Secure.putStringForUser(mContext.getContentResolver(), 609 getConfig().secureSettingName, allowedItems, 610 approvedUserId); 611 } 612 } 613 614 } 615 } 616 } 617 } 618 } 619 620 writeExtraXmlTags(out); 621 622 out.endTag(null, getConfig().xmlTag); 623 } 624 625 /** 626 * Returns whether the approved list of services should also be written to the Settings db 627 */ shouldReflectToSettings()628 protected boolean shouldReflectToSettings() { 629 return false; 630 } 631 632 /** 633 * Writes extra xml attributes to {@link #TAG_MANAGED_SERVICES} tag. 634 */ writeExtraAttributes(TypedXmlSerializer out, int userId)635 protected void writeExtraAttributes(TypedXmlSerializer out, int userId) throws IOException {} 636 637 /** 638 * Writes extra xml tags within the parent tag specified in {@link Config#xmlTag}. 639 */ writeExtraXmlTags(TypedXmlSerializer out)640 protected void writeExtraXmlTags(TypedXmlSerializer out) throws IOException {} 641 642 /** 643 * This is called to process tags other than {@link #TAG_MANAGED_SERVICES}. 644 */ readExtraTag(String tag, TypedXmlPullParser parser)645 protected void readExtraTag(String tag, TypedXmlPullParser parser) 646 throws IOException, XmlPullParserException {} 647 migrateToXml()648 protected final void migrateToXml() { 649 for (UserInfo user : mUm.getUsers()) { 650 final ContentResolver cr = mContext.getContentResolver(); 651 if (!TextUtils.isEmpty(getConfig().secureSettingName)) { 652 addApprovedList(Settings.Secure.getStringForUser( 653 cr, 654 getConfig().secureSettingName, 655 user.id), user.id, true); 656 } 657 if (!TextUtils.isEmpty(getConfig().secondarySettingName)) { 658 addApprovedList(Settings.Secure.getStringForUser( 659 cr, 660 getConfig().secondarySettingName, 661 user.id), user.id, false); 662 } 663 } 664 } 665 readDefaults(TypedXmlPullParser parser)666 void readDefaults(TypedXmlPullParser parser) { 667 String defaultComponents = XmlUtils.readStringAttribute(parser, ATT_DEFAULTS); 668 669 if (!TextUtils.isEmpty(defaultComponents)) { 670 String[] components = defaultComponents.split(ENABLED_SERVICES_SEPARATOR); 671 synchronized (mDefaultsLock) { 672 for (int i = 0; i < components.length; i++) { 673 if (!TextUtils.isEmpty(components[i])) { 674 ComponentName cn = ComponentName.unflattenFromString(components[i]); 675 if (cn != null) { 676 mDefaultPackages.add(cn.getPackageName()); 677 mDefaultComponents.add(cn); 678 } else { 679 mDefaultPackages.add(components[i]); 680 } 681 } 682 } 683 } 684 } 685 } 686 readXml( TypedXmlPullParser parser, TriPredicate<String, Integer, String> allowedManagedServicePackages, boolean forRestore, int userId)687 public void readXml( 688 TypedXmlPullParser parser, 689 TriPredicate<String, Integer, String> allowedManagedServicePackages, 690 boolean forRestore, 691 int userId) 692 throws XmlPullParserException, IOException { 693 // read grants 694 int type; 695 String version = XmlUtils.readStringAttribute(parser, ATT_VERSION); 696 boolean needUpgradeUserset = false; 697 readDefaults(parser); 698 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 699 String tag = parser.getName(); 700 if (type == XmlPullParser.END_TAG 701 && getConfig().xmlTag.equals(tag)) { 702 break; 703 } 704 if (type == XmlPullParser.START_TAG) { 705 if (TAG_MANAGED_SERVICES.equals(tag)) { 706 Slog.i(TAG, "Read " + mConfig.caption + " permissions from xml"); 707 708 final String approved = XmlUtils.readStringAttribute(parser, ATT_APPROVED_LIST); 709 // Ignore parser's user id for restore. 710 final int resolvedUserId = forRestore 711 ? userId : parser.getAttributeInt(null, ATT_USER_ID, 0); 712 final boolean isPrimary = 713 parser.getAttributeBoolean(null, ATT_IS_PRIMARY, true); 714 715 // Load three different userSet attributes from xml 716 // user_changed, not null if version == 4 and is NAS setting 717 final String isUserChanged = XmlUtils.readStringAttribute(parser, 718 ATT_USER_CHANGED); 719 // user_set, not null if version <= 3 720 final String isUserChanged_Old = XmlUtils.readStringAttribute(parser, 721 ATT_USER_SET_OLD); 722 // user_set_services, not null if version >= 3 and is non-NAS setting 723 String userSetComponent = XmlUtils.readStringAttribute(parser, ATT_USER_SET); 724 725 // since the same xml version may have different userSet attributes, 726 // we need to check both xml version and userSet values to know how to set 727 // the userSetComponent/mIsUserChanged to the correct value 728 if (DB_VERSION.equals(version)) { 729 // version 4, NAS contains user_changed and 730 // NLS/others contain user_set_services 731 if (isUserChanged == null) { //NLS 732 userSetComponent = TextUtils.emptyIfNull(userSetComponent); 733 } else { //NAS 734 synchronized (mApproved) { 735 mIsUserChanged.put(resolvedUserId, Boolean.valueOf(isUserChanged)); 736 } 737 userSetComponent = Boolean.valueOf(isUserChanged) ? approved : ""; 738 } 739 } else { 740 // version 3 may contain user_set (R) or user_set_services (S) 741 // version 2 or older contain user_set or nothing 742 needUpgradeUserset = true; 743 if (userSetComponent == null) { //contains user_set 744 if (isUserChanged_Old != null && Boolean.valueOf(isUserChanged_Old)) { 745 //user_set = true 746 userSetComponent = approved; 747 synchronized (mApproved) { 748 mIsUserChanged.put(resolvedUserId, true); 749 } 750 needUpgradeUserset = false; 751 } else { 752 userSetComponent = ""; 753 } 754 } 755 } 756 readExtraAttributes(tag, parser, resolvedUserId); 757 if (isUserChanged != null && approved.isEmpty()) { 758 // NAS 759 denyPregrantedAppUserSet(resolvedUserId, isPrimary); 760 mUseXml = true; 761 } else { 762 if (allowedManagedServicePackages == null 763 || allowedManagedServicePackages.test( 764 getPackageName(approved), resolvedUserId, getRequiredPermission()) 765 || approved.isEmpty()) { 766 if (mUm.getUserInfo(resolvedUserId) != null) { 767 addApprovedList(approved, resolvedUserId, isPrimary, 768 userSetComponent); 769 } 770 mUseXml = true; 771 } 772 } 773 } else { 774 readExtraTag(tag, parser); 775 } 776 } 777 } 778 boolean isOldVersion = TextUtils.isEmpty(version) 779 || DB_VERSION_1.equals(version) 780 || DB_VERSION_2.equals(version) 781 || DB_VERSION_3.equals(version); 782 if (isOldVersion) { 783 upgradeDefaultsXmlVersion(); 784 } 785 if (needUpgradeUserset) { 786 upgradeUserSet(); 787 } 788 789 rebindServices(false, USER_ALL); 790 } 791 upgradeDefaultsXmlVersion()792 void upgradeDefaultsXmlVersion() { 793 int defaultsSize; 794 synchronized (mDefaultsLock) { 795 // check if any defaults are loaded 796 defaultsSize = mDefaultComponents.size() + mDefaultPackages.size(); 797 } 798 if (defaultsSize == 0) { 799 // load defaults from current allowed 800 if (this.mApprovalLevel == APPROVAL_BY_COMPONENT) { 801 List<ComponentName> approvedComponents = getAllowedComponents(USER_SYSTEM); 802 for (int i = 0; i < approvedComponents.size(); i++) { 803 addDefaultComponentOrPackage(approvedComponents.get(i).flattenToString()); 804 } 805 } 806 if (this.mApprovalLevel == APPROVAL_BY_PACKAGE) { 807 List<String> approvedPkgs = getAllowedPackages(USER_SYSTEM); 808 for (int i = 0; i < approvedPkgs.size(); i++) { 809 addDefaultComponentOrPackage(approvedPkgs.get(i)); 810 } 811 } 812 } 813 synchronized (mDefaultsLock) { 814 defaultsSize = mDefaultComponents.size() + mDefaultPackages.size(); 815 } 816 // if no defaults are loaded, then load from config 817 if (defaultsSize == 0) { 818 loadDefaultsFromConfig(); 819 } 820 } 821 upgradeUserSet()822 protected void upgradeUserSet() {}; 823 824 /** 825 * Read extra attributes in the {@link #TAG_MANAGED_SERVICES} tag. 826 */ readExtraAttributes(String tag, TypedXmlPullParser parser, int userId)827 protected void readExtraAttributes(String tag, TypedXmlPullParser parser, int userId) 828 throws IOException {} 829 getRequiredPermission()830 protected abstract String getRequiredPermission(); 831 addApprovedList(String approved, int userId, boolean isPrimary)832 protected void addApprovedList(String approved, int userId, boolean isPrimary) { 833 addApprovedList(approved, userId, isPrimary, approved); 834 } 835 addApprovedList(String approved, int userId, boolean isPrimary, String userSet)836 protected void addApprovedList(String approved, int userId, boolean isPrimary, String userSet) { 837 if (TextUtils.isEmpty(approved)) { 838 approved = ""; 839 } 840 if (userSet == null) { 841 userSet = approved; 842 } 843 synchronized (mApproved) { 844 ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId); 845 if (approvedByType == null) { 846 approvedByType = new ArrayMap<>(); 847 mApproved.put(userId, approvedByType); 848 } 849 850 ArraySet<String> approvedList = approvedByType.get(isPrimary); 851 if (approvedList == null) { 852 approvedList = new ArraySet<>(); 853 approvedByType.put(isPrimary, approvedList); 854 } 855 856 String[] approvedArray = approved.split(ENABLED_SERVICES_SEPARATOR); 857 for (String pkgOrComponent : approvedArray) { 858 String approvedItem = getApprovedValue(pkgOrComponent); 859 if (approvedItem != null) { 860 approvedList.add(approvedItem); 861 } 862 } 863 864 ArraySet<String> userSetList = mUserSetServices.get(userId); 865 if (userSetList == null) { 866 userSetList = new ArraySet<>(); 867 mUserSetServices.put(userId, userSetList); 868 } 869 String[] userSetArray = userSet.split(ENABLED_SERVICES_SEPARATOR); 870 for (String pkgOrComponent : userSetArray) { 871 String approvedItem = getApprovedValue(pkgOrComponent); 872 if (approvedItem != null) { 873 userSetList.add(approvedItem); 874 } 875 } 876 } 877 } 878 denyPregrantedAppUserSet(int userId, boolean isPrimary)879 protected void denyPregrantedAppUserSet(int userId, boolean isPrimary) { 880 synchronized (mApproved) { 881 ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId); 882 if (approvedByType == null) { 883 approvedByType = new ArrayMap<>(); 884 mApproved.put(userId, approvedByType); 885 } 886 approvedByType.put(isPrimary, new ArraySet<>()); 887 } 888 } 889 890 /** convenience method for looking in mEnabledServicesPackageNamesByUser 891 * for UserHandle.USER_CURRENT. 892 * This is a legacy API. When FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER becomes 893 * trunk stable, this API should be deprecated. Additionally, when this method 894 * is deprecated, the unit tests written using this method should also be revised. 895 * 896 * @param pkg target package name 897 * @return boolean value that indicates whether it is enabled for the current profiles 898 */ isComponentEnabledForPackage(String pkg)899 protected boolean isComponentEnabledForPackage(String pkg) { 900 return isComponentEnabledForPackage(pkg, UserHandle.USER_CURRENT); 901 } 902 903 /** convenience method for looking in mEnabledServicesPackageNamesByUser 904 * 905 * @param pkg target package name 906 * @param userId the id of the target user 907 * @return boolean value that indicates whether it is enabled for the target user 908 */ 909 @FlaggedApi(FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER) isComponentEnabledForPackage(String pkg, int userId)910 protected boolean isComponentEnabledForPackage(String pkg, int userId) { 911 synchronized (mMutex) { 912 ArraySet<String> enabledServicesPackageNames = 913 mEnabledServicesPackageNamesByUser.get(resolveUserId(userId)); 914 return enabledServicesPackageNames != null && enabledServicesPackageNames.contains(pkg); 915 } 916 } 917 setPackageOrComponentEnabled(String pkgOrComponent, int userId, boolean isPrimary, boolean enabled)918 protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId, 919 boolean isPrimary, boolean enabled) { 920 setPackageOrComponentEnabled(pkgOrComponent, userId, isPrimary, enabled, true); 921 } 922 setPackageOrComponentEnabled(String pkgOrComponent, int userId, boolean isPrimary, boolean enabled, boolean userSet)923 protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId, 924 boolean isPrimary, boolean enabled, boolean userSet) { 925 Slog.i(TAG, 926 (enabled ? " Allowing " : "Disallowing ") + mConfig.caption + " " 927 + pkgOrComponent + " (userSet: " + userSet + ")"); 928 synchronized (mApproved) { 929 ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.get(userId); 930 if (allowedByType == null) { 931 allowedByType = new ArrayMap<>(); 932 mApproved.put(userId, allowedByType); 933 } 934 ArraySet<String> approved = allowedByType.get(isPrimary); 935 if (approved == null) { 936 approved = new ArraySet<>(); 937 allowedByType.put(isPrimary, approved); 938 } 939 String approvedItem = getApprovedValue(pkgOrComponent); 940 941 if (approvedItem != null) { 942 if (enabled) { 943 approved.add(approvedItem); 944 } else { 945 approved.remove(approvedItem); 946 } 947 } 948 ArraySet<String> userSetServices = mUserSetServices.get(userId); 949 if (userSetServices == null) { 950 userSetServices = new ArraySet<>(); 951 mUserSetServices.put(userId, userSetServices); 952 } 953 if (userSet) { 954 userSetServices.add(pkgOrComponent); 955 } else { 956 userSetServices.remove(pkgOrComponent); 957 } 958 } 959 960 rebindServices(false, userId); 961 } 962 getApprovedValue(String pkgOrComponent)963 private String getApprovedValue(String pkgOrComponent) { 964 if (mApprovalLevel == APPROVAL_BY_COMPONENT) { 965 if(ComponentName.unflattenFromString(pkgOrComponent) != null) { 966 return pkgOrComponent; 967 } 968 return null; 969 } else { 970 return getPackageName(pkgOrComponent); 971 } 972 } 973 getApproved(int userId, boolean primary)974 protected String getApproved(int userId, boolean primary) { 975 synchronized (mApproved) { 976 final ArrayMap<Boolean, ArraySet<String>> allowedByType = 977 mApproved.getOrDefault(userId, new ArrayMap<>()); 978 ArraySet<String> approved = allowedByType.getOrDefault(primary, new ArraySet<>()); 979 return String.join(ENABLED_SERVICES_SEPARATOR, approved); 980 } 981 } 982 getAllowedComponents(int userId)983 protected List<ComponentName> getAllowedComponents(int userId) { 984 final List<ComponentName> allowedComponents = new ArrayList<>(); 985 synchronized (mApproved) { 986 final ArrayMap<Boolean, ArraySet<String>> allowedByType = 987 mApproved.getOrDefault(userId, new ArrayMap<>()); 988 for (int i = 0; i < allowedByType.size(); i++) { 989 final ArraySet<String> allowed = allowedByType.valueAt(i); 990 for (int j = 0; j < allowed.size(); j++) { 991 ComponentName cn = ComponentName.unflattenFromString(allowed.valueAt(j)); 992 if (cn != null) { 993 allowedComponents.add(cn); 994 } 995 } 996 } 997 } 998 return allowedComponents; 999 } 1000 1001 @NonNull getAllowedPackages(int userId)1002 protected List<String> getAllowedPackages(int userId) { 1003 final List<String> allowedPackages = new ArrayList<>(); 1004 synchronized (mApproved) { 1005 final ArrayMap<Boolean, ArraySet<String>> allowedByType = 1006 mApproved.getOrDefault(userId, new ArrayMap<>()); 1007 for (int i = 0; i < allowedByType.size(); i++) { 1008 final ArraySet<String> allowed = allowedByType.valueAt(i); 1009 for (int j = 0; j < allowed.size(); j++) { 1010 String pkgName = getPackageName(allowed.valueAt(j)); 1011 if (!TextUtils.isEmpty(pkgName)) { 1012 allowedPackages.add(pkgName); 1013 } 1014 } 1015 } 1016 } 1017 return allowedPackages; 1018 } 1019 isPackageOrComponentAllowed(String pkgOrComponent, int userId)1020 protected boolean isPackageOrComponentAllowed(String pkgOrComponent, int userId) { 1021 synchronized (mApproved) { 1022 ArrayMap<Boolean, ArraySet<String>> allowedByType = 1023 mApproved.getOrDefault(userId, new ArrayMap<>()); 1024 for (int i = 0; i < allowedByType.size(); i++) { 1025 ArraySet<String> allowed = allowedByType.valueAt(i); 1026 if (allowed.contains(pkgOrComponent)) { 1027 return true; 1028 } 1029 } 1030 } 1031 return false; 1032 } 1033 isPackageOrComponentAllowedWithPermission(ComponentName component, int userId)1034 protected boolean isPackageOrComponentAllowedWithPermission(ComponentName component, 1035 int userId) { 1036 if (!(isPackageOrComponentAllowed(component.flattenToString(), userId) 1037 || isPackageOrComponentAllowed(component.getPackageName(), userId))) { 1038 return false; 1039 } 1040 return componentHasBindPermission(component, userId); 1041 } 1042 componentHasBindPermission(ComponentName component, int userId)1043 private boolean componentHasBindPermission(ComponentName component, int userId) { 1044 ServiceInfo info = getServiceInfo(component, userId); 1045 if (info == null) { 1046 return false; 1047 } 1048 return mConfig.bindPermission.equals(info.permission); 1049 } 1050 isPackageOrComponentUserSet(String pkgOrComponent, int userId)1051 boolean isPackageOrComponentUserSet(String pkgOrComponent, int userId) { 1052 synchronized (mApproved) { 1053 ArraySet<String> services = mUserSetServices.get(userId); 1054 return services != null && services.contains(pkgOrComponent); 1055 } 1056 } 1057 isPackageAllowed(String pkg, int userId)1058 protected boolean isPackageAllowed(String pkg, int userId) { 1059 if (pkg == null) { 1060 return false; 1061 } 1062 synchronized (mApproved) { 1063 ArrayMap<Boolean, ArraySet<String>> allowedByType = 1064 mApproved.getOrDefault(userId, new ArrayMap<>()); 1065 for (int i = 0; i < allowedByType.size(); i++) { 1066 ArraySet<String> allowed = allowedByType.valueAt(i); 1067 for (String allowedEntry : allowed) { 1068 ComponentName component = ComponentName.unflattenFromString(allowedEntry); 1069 if (component != null) { 1070 if (pkg.equals(component.getPackageName())) { 1071 return true; 1072 } 1073 } else { 1074 if (pkg.equals(allowedEntry)) { 1075 return true; 1076 } 1077 } 1078 } 1079 } 1080 } 1081 return false; 1082 } 1083 onPackagesChanged(boolean removingPackage, String[] pkgList, int[] uidList)1084 public void onPackagesChanged(boolean removingPackage, String[] pkgList, int[] uidList) { 1085 if (DEBUG) { 1086 synchronized (mMutex) { 1087 int resolvedUserId = (managedServicesConcurrentMultiuser() 1088 && (uidList != null && uidList.length > 0)) 1089 ? resolveUserId(UserHandle.getUserId(uidList[0])) 1090 : UserHandle.USER_CURRENT; 1091 Slog.d(TAG, "onPackagesChanged removingPackage=" + removingPackage 1092 + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList)) 1093 + " mEnabledServicesPackageNames=" 1094 + mEnabledServicesPackageNamesByUser.get(resolvedUserId)); 1095 } 1096 } 1097 1098 if (pkgList != null && (pkgList.length > 0)) { 1099 boolean anyServicesInvolved = false; 1100 // Remove notification settings for uninstalled package 1101 if (removingPackage && uidList != null) { 1102 int size = Math.min(pkgList.length, uidList.length); 1103 for (int i = 0; i < size; i++) { 1104 final String pkg = pkgList[i]; 1105 final int userId = UserHandle.getUserId(uidList[i]); 1106 anyServicesInvolved = removeUninstalledItemsFromApprovedLists(userId, pkg); 1107 } 1108 } 1109 for (String pkgName : pkgList) { 1110 if (!managedServicesConcurrentMultiuser()) { 1111 if (isComponentEnabledForPackage(pkgName)) { 1112 anyServicesInvolved = true; 1113 } 1114 } 1115 if (uidList != null && uidList.length > 0) { 1116 for (int uid : uidList) { 1117 if (managedServicesConcurrentMultiuser()) { 1118 if (isComponentEnabledForPackage(pkgName, UserHandle.getUserId(uid))) { 1119 anyServicesInvolved = true; 1120 } 1121 } 1122 if (isPackageAllowed(pkgName, UserHandle.getUserId(uid))) { 1123 anyServicesInvolved = true; 1124 trimApprovedListsForInvalidServices(pkgName, UserHandle.getUserId(uid)); 1125 } 1126 } 1127 } 1128 } 1129 1130 if (anyServicesInvolved) { 1131 // make sure we're still bound to any of our services who may have just upgraded 1132 rebindServices(false, USER_ALL); 1133 } 1134 } 1135 } 1136 onUserRemoved(int user)1137 public void onUserRemoved(int user) { 1138 Slog.i(TAG, "Removing approved services for removed user " + user); 1139 synchronized (mApproved) { 1140 mApproved.remove(user); 1141 } 1142 synchronized (mSnoozing) { 1143 mSnoozing.remove(user); 1144 } 1145 unbindUserServices(user); 1146 } 1147 1148 /** 1149 * Call this method when a user is stopped 1150 * 1151 * @param user the id of the stopped user 1152 */ onUserStopped(int user)1153 public void onUserStopped(int user) { 1154 if (!managedServicesConcurrentMultiuser()) { 1155 return; 1156 } 1157 boolean hasAny = false; 1158 synchronized (mMutex) { 1159 if (mEnabledServicesByUser.contains(user) 1160 && mEnabledServicesPackageNamesByUser.contains(user)) { 1161 // Through the ManagedServices.resolveUserId, 1162 // we resolve UserHandle.USER_CURRENT as the key for users 1163 // other than the visible background user. 1164 // Therefore, the user IDs that exist as keys for each member variable 1165 // correspond to the visible background user. 1166 // We need to unbind services of the stopped visible background user. 1167 mEnabledServicesByUser.remove(user); 1168 mEnabledServicesPackageNamesByUser.remove(user); 1169 hasAny = true; 1170 } 1171 } 1172 if (hasAny) { 1173 Slog.i(TAG, "Removing approved services for stopped user " + user); 1174 unbindUserServices(user); 1175 } 1176 } 1177 onUserSwitched(int user)1178 public void onUserSwitched(int user) { 1179 if (DEBUG) Slog.d(TAG, "onUserSwitched u=" + user); 1180 unbindOtherUserServices(user); 1181 rebindServices(true, user); 1182 } 1183 onUserUnlocked(int user)1184 public void onUserUnlocked(int user) { 1185 if (DEBUG) Slog.d(TAG, "onUserUnlocked u=" + user); 1186 rebindServices(false, user); 1187 } 1188 getServiceFromTokenLocked(IInterface service)1189 private ManagedServiceInfo getServiceFromTokenLocked(IInterface service) { 1190 if (service == null) { 1191 return null; 1192 } 1193 final IBinder token = service.asBinder(); 1194 synchronized (mMutex) { 1195 final int nServices = mServices.size(); 1196 for (int i = 0; i < nServices; i++) { 1197 final ManagedServiceInfo info = mServices.get(i); 1198 if (info.service.asBinder() == token) return info; 1199 } 1200 } 1201 return null; 1202 } 1203 isServiceTokenValidLocked(IInterface service)1204 protected boolean isServiceTokenValidLocked(IInterface service) { 1205 if (service == null) { 1206 return false; 1207 } 1208 ManagedServiceInfo info = getServiceFromTokenLocked(service); 1209 if (info != null) { 1210 return true; 1211 } 1212 return false; 1213 } 1214 checkServiceTokenLocked(IInterface service)1215 protected ManagedServiceInfo checkServiceTokenLocked(IInterface service) { 1216 checkNotNull(service); 1217 ManagedServiceInfo info = getServiceFromTokenLocked(service); 1218 if (info != null) { 1219 return info; 1220 } 1221 throw new SecurityException("Disallowed call from unknown " + getCaption() + ": " 1222 + service.asBinder() + " " + service.getClass()); 1223 } 1224 isSameUser(IInterface service, int userId)1225 public boolean isSameUser(IInterface service, int userId) { 1226 checkNotNull(service); 1227 synchronized (mMutex) { 1228 ManagedServiceInfo info = getServiceFromTokenLocked(service); 1229 if (info != null) { 1230 return info.isSameUser(userId); 1231 } 1232 return false; 1233 } 1234 } 1235 unregisterService(IInterface service, int userid)1236 public void unregisterService(IInterface service, int userid) { 1237 checkNotNull(service); 1238 // no need to check permissions; if your service binder is in the list, 1239 // that's proof that you had permission to add it in the first place 1240 unregisterServiceImpl(service, userid); 1241 } 1242 registerSystemService(IInterface service, ComponentName component, int userid, int uid)1243 public void registerSystemService(IInterface service, ComponentName component, int userid, 1244 int uid) { 1245 checkNotNull(service); 1246 ManagedServiceInfo info = registerServiceImpl( 1247 service, component, userid, Build.VERSION_CODES.CUR_DEVELOPMENT, uid); 1248 if (info != null) { 1249 onServiceAdded(info); 1250 } 1251 } 1252 1253 /** 1254 * Add a service to our callbacks. The lifecycle of this service is managed externally, 1255 * but unlike a system service, it should not be considered privileged. 1256 * */ registerGuestService(ManagedServiceInfo guest)1257 protected void registerGuestService(ManagedServiceInfo guest) { 1258 checkNotNull(guest.service); 1259 if (!checkType(guest.service)) { 1260 throw new IllegalArgumentException(); 1261 } 1262 if (registerServiceImpl(guest) != null) { 1263 onServiceAdded(guest); 1264 } 1265 } 1266 setComponentState(ComponentName component, int userId, boolean enabled)1267 protected void setComponentState(ComponentName component, int userId, boolean enabled) { 1268 synchronized (mSnoozing) { 1269 boolean previous = !mSnoozing.contains(userId, component); 1270 if (previous == enabled) { 1271 return; 1272 } 1273 1274 if (enabled) { 1275 mSnoozing.remove(userId, component); 1276 } else { 1277 mSnoozing.add(userId, component); 1278 } 1279 } 1280 1281 // State changed 1282 Slog.d(TAG, ((enabled) ? "Enabling " : "Disabling ") + "component " + 1283 component.flattenToShortString()); 1284 1285 synchronized (mMutex) { 1286 if (enabled) { 1287 if (isPackageOrComponentAllowedWithPermission(component, userId)) { 1288 registerServiceLocked(component, userId); 1289 } else { 1290 Slog.d(TAG, component + " no longer has permission to be bound"); 1291 } 1292 } else { 1293 unregisterServiceLocked(component, userId); 1294 } 1295 } 1296 } 1297 loadComponentNamesFromValues( ArraySet<String> approved, int userId)1298 private @NonNull ArraySet<ComponentName> loadComponentNamesFromValues( 1299 ArraySet<String> approved, int userId) { 1300 if (approved == null || approved.size() == 0) 1301 return new ArraySet<>(); 1302 ArraySet<ComponentName> result = new ArraySet<>(approved.size()); 1303 for (int i = 0; i < approved.size(); i++) { 1304 final String packageOrComponent = approved.valueAt(i); 1305 if (!TextUtils.isEmpty(packageOrComponent)) { 1306 ComponentName component = ComponentName.unflattenFromString(packageOrComponent); 1307 if (component != null) { 1308 result.add(component); 1309 } else { 1310 result.addAll(queryPackageForServices(packageOrComponent, userId)); 1311 } 1312 } 1313 } 1314 return result; 1315 } 1316 queryPackageForServices(String packageName, int userId)1317 protected Set<ComponentName> queryPackageForServices(String packageName, int userId) { 1318 return queryPackageForServices(packageName, 0, userId); 1319 } 1320 queryPackageForServices(String packageName, int extraFlags, int userId)1321 protected ArraySet<ComponentName> queryPackageForServices(String packageName, int extraFlags, 1322 int userId) { 1323 ArraySet<ComponentName> installed = new ArraySet<>(); 1324 final PackageManager pm = mContext.getPackageManager(); 1325 Intent queryIntent = new Intent(mConfig.serviceInterface); 1326 if (!TextUtils.isEmpty(packageName)) { 1327 queryIntent.setPackage(packageName); 1328 } 1329 List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser( 1330 queryIntent, 1331 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA | extraFlags, 1332 userId); 1333 if (DEBUG) 1334 Slog.v(TAG, mConfig.serviceInterface + " services: " + installedServices); 1335 if (installedServices != null) { 1336 for (int i = 0, count = installedServices.size(); i < count; i++) { 1337 ResolveInfo resolveInfo = installedServices.get(i); 1338 ServiceInfo info = resolveInfo.serviceInfo; 1339 1340 ComponentName component = new ComponentName(info.packageName, info.name); 1341 if (!mConfig.bindPermission.equals(info.permission)) { 1342 Slog.w(TAG, "Skipping " + getCaption() + " service " 1343 + info.packageName + "/" + info.name 1344 + ": it does not require the permission " 1345 + mConfig.bindPermission); 1346 continue; 1347 } 1348 installed.add(component); 1349 } 1350 } 1351 return installed; 1352 } 1353 trimApprovedListsAccordingToInstalledServices(int userId)1354 private void trimApprovedListsAccordingToInstalledServices(int userId) { 1355 synchronized (mApproved) { 1356 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId); 1357 if (approvedByType == null) { 1358 return; 1359 } 1360 for (int i = 0; i < approvedByType.size(); i++) { 1361 final ArraySet<String> approved = approvedByType.valueAt(i); 1362 for (int j = approved.size() - 1; j >= 0; j--) { 1363 final String approvedPackageOrComponent = approved.valueAt(j); 1364 if (!isValidEntry(approvedPackageOrComponent, userId)) { 1365 approved.removeAt(j); 1366 Slog.v(TAG, "Removing " + approvedPackageOrComponent 1367 + " from approved list; no matching services found"); 1368 } else { 1369 if (DEBUG) { 1370 Slog.v(TAG, "Keeping " + approvedPackageOrComponent 1371 + " on approved list; matching services found"); 1372 } 1373 } 1374 } 1375 } 1376 } 1377 } 1378 removeUninstalledItemsFromApprovedLists(int uninstalledUserId, String pkg)1379 private boolean removeUninstalledItemsFromApprovedLists(int uninstalledUserId, String pkg) { 1380 boolean removed = false; 1381 synchronized (mApproved) { 1382 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get( 1383 uninstalledUserId); 1384 if (approvedByType != null) { 1385 int M = approvedByType.size(); 1386 for (int j = 0; j < M; j++) { 1387 final ArraySet<String> approved = approvedByType.valueAt(j); 1388 int O = approved.size(); 1389 for (int k = O - 1; k >= 0; k--) { 1390 final String packageOrComponent = approved.valueAt(k); 1391 final String packageName = getPackageName(packageOrComponent); 1392 if (TextUtils.equals(pkg, packageName)) { 1393 approved.removeAt(k); 1394 if (DEBUG) { 1395 Slog.v(TAG, "Removing " + packageOrComponent 1396 + " from approved list; uninstalled"); 1397 } 1398 } 1399 } 1400 } 1401 } 1402 // Remove uninstalled components from user-set list 1403 final ArraySet<String> userSet = mUserSetServices.get(uninstalledUserId); 1404 if (userSet != null) { 1405 int numServices = userSet.size(); 1406 for (int i = numServices - 1; i >= 0; i--) { 1407 String pkgOrComponent = userSet.valueAt(i); 1408 if (TextUtils.equals(pkg, getPackageName(pkgOrComponent))) { 1409 userSet.removeAt(i); 1410 if (DEBUG) { 1411 Slog.v(TAG, "Removing " + pkgOrComponent 1412 + " from user-set list; uninstalled"); 1413 } 1414 } 1415 } 1416 } 1417 } 1418 return removed; 1419 } 1420 trimApprovedListsForInvalidServices(String packageName, int userId)1421 private void trimApprovedListsForInvalidServices(String packageName, int userId) { 1422 synchronized (mApproved) { 1423 final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId); 1424 if (approvedByType == null) { 1425 return; 1426 } 1427 for (int i = 0; i < approvedByType.size(); i++) { 1428 final ArraySet<String> approved = approvedByType.valueAt(i); 1429 for (int j = approved.size() - 1; j >= 0; j--) { 1430 final String approvedPackageOrComponent = approved.valueAt(j); 1431 if (TextUtils.equals(getPackageName(approvedPackageOrComponent), packageName)) { 1432 final ComponentName component = ComponentName.unflattenFromString( 1433 approvedPackageOrComponent); 1434 if (component != null && !componentHasBindPermission(component, userId)) { 1435 approved.removeAt(j); 1436 if (DEBUG) { 1437 Slog.v(TAG, "Removing " + approvedPackageOrComponent 1438 + " from approved list; no bind permission found " 1439 + mConfig.bindPermission); 1440 } 1441 } 1442 } 1443 } 1444 } 1445 } 1446 } 1447 getPackageName(String packageOrComponent)1448 protected String getPackageName(String packageOrComponent) { 1449 final ComponentName component = ComponentName.unflattenFromString(packageOrComponent); 1450 if (component != null) { 1451 return component.getPackageName(); 1452 } else { 1453 return packageOrComponent; 1454 } 1455 } 1456 isValidEntry(String packageOrComponent, int userId)1457 protected boolean isValidEntry(String packageOrComponent, int userId) { 1458 return hasMatchingServices(packageOrComponent, userId); 1459 } 1460 hasMatchingServices(String packageOrComponent, int userId)1461 private boolean hasMatchingServices(String packageOrComponent, int userId) { 1462 if (!TextUtils.isEmpty(packageOrComponent)) { 1463 final String packageName = getPackageName(packageOrComponent); 1464 return queryPackageForServices(packageName, userId).size() > 0; 1465 } 1466 return false; 1467 } 1468 1469 @VisibleForTesting getAllowedComponents(IntArray userIds)1470 protected SparseArray<ArraySet<ComponentName>> getAllowedComponents(IntArray userIds) { 1471 final int nUserIds = userIds.size(); 1472 final SparseArray<ArraySet<ComponentName>> componentsByUser = new SparseArray<>(); 1473 1474 for (int i = 0; i < nUserIds; ++i) { 1475 final int userId = userIds.get(i); 1476 synchronized (mApproved) { 1477 final ArrayMap<Boolean, ArraySet<String>> approvedLists = mApproved.get(userId); 1478 if (approvedLists != null) { 1479 final int N = approvedLists.size(); 1480 for (int j = 0; j < N; j++) { 1481 ArraySet<ComponentName> approvedByUser = componentsByUser.get(userId); 1482 if (approvedByUser == null) { 1483 approvedByUser = new ArraySet<>(); 1484 componentsByUser.put(userId, approvedByUser); 1485 } 1486 approvedByUser.addAll( 1487 loadComponentNamesFromValues(approvedLists.valueAt(j), userId)); 1488 } 1489 } 1490 } 1491 } 1492 return componentsByUser; 1493 } 1494 1495 @GuardedBy("mMutex") populateComponentsToBind(SparseArray<Set<ComponentName>> componentsToBind, final IntArray activeUsers, SparseArray<ArraySet<ComponentName>> approvedComponentsByUser)1496 protected void populateComponentsToBind(SparseArray<Set<ComponentName>> componentsToBind, 1497 final IntArray activeUsers, 1498 SparseArray<ArraySet<ComponentName>> approvedComponentsByUser) { 1499 final int nUserIds = activeUsers.size(); 1500 if (managedServicesConcurrentMultiuser()) { 1501 for (int i = 0; i < nUserIds; ++i) { 1502 final int resolvedUserId = resolveUserId(activeUsers.get(i)); 1503 if (mEnabledServicesByUser.get(resolvedUserId) != null) { 1504 mEnabledServicesByUser.get(resolvedUserId).clear(); 1505 } 1506 if (mEnabledServicesPackageNamesByUser.get(resolvedUserId) != null) { 1507 mEnabledServicesPackageNamesByUser.get(resolvedUserId).clear(); 1508 } 1509 } 1510 } else { 1511 mEnabledServicesByUser.get(UserHandle.USER_CURRENT).clear(); 1512 mEnabledServicesPackageNamesByUser.get(UserHandle.USER_CURRENT).clear(); 1513 } 1514 for (int i = 0; i < nUserIds; ++i) { 1515 final int userId = activeUsers.get(i); 1516 // decode the list of components 1517 final ArraySet<ComponentName> userComponents = approvedComponentsByUser.get(userId); 1518 if (null == userComponents) { 1519 componentsToBind.put(userId, new ArraySet<>()); 1520 continue; 1521 } 1522 1523 final int resolvedUserId = managedServicesConcurrentMultiuser() 1524 ? resolveUserId(userId) 1525 : UserHandle.USER_CURRENT; 1526 ArraySet<ComponentName> enabledServices = 1527 mEnabledServicesByUser.contains(resolvedUserId) 1528 ? mEnabledServicesByUser.get(resolvedUserId) 1529 : new ArraySet<>(); 1530 ArraySet<String> enabledServicesPackageName = 1531 mEnabledServicesPackageNamesByUser.contains(resolvedUserId) 1532 ? mEnabledServicesPackageNamesByUser.get(resolvedUserId) 1533 : new ArraySet<>(); 1534 1535 final Set<ComponentName> add = new HashSet<>(userComponents); 1536 synchronized (mSnoozing) { 1537 ArraySet<ComponentName> snoozed = mSnoozing.get(userId); 1538 if (snoozed != null) { 1539 add.removeAll(snoozed); 1540 } 1541 } 1542 1543 componentsToBind.put(userId, add); 1544 1545 enabledServices.addAll(userComponents); 1546 for (int j = 0; j < userComponents.size(); j++) { 1547 enabledServicesPackageName.add(userComponents.valueAt(j).getPackageName()); 1548 } 1549 mEnabledServicesByUser.put(resolvedUserId, enabledServices); 1550 mEnabledServicesPackageNamesByUser.put(resolvedUserId, enabledServicesPackageName); 1551 } 1552 } 1553 1554 @GuardedBy("mMutex") getRemovableConnectedServices()1555 protected Set<ManagedServiceInfo> getRemovableConnectedServices() { 1556 final Set<ManagedServiceInfo> removableBoundServices = new ArraySet<>(); 1557 for (ManagedServiceInfo service : mServices) { 1558 if (!service.isSystem && !service.isGuest(this)) { 1559 removableBoundServices.add(service); 1560 } 1561 } 1562 return removableBoundServices; 1563 } 1564 populateComponentsToUnbind( boolean forceRebind, Set<ManagedServiceInfo> removableBoundServices, SparseArray<Set<ComponentName>> allowedComponentsToBind, SparseArray<Set<ComponentName>> componentsToUnbind)1565 protected void populateComponentsToUnbind( 1566 boolean forceRebind, 1567 Set<ManagedServiceInfo> removableBoundServices, 1568 SparseArray<Set<ComponentName>> allowedComponentsToBind, 1569 SparseArray<Set<ComponentName>> componentsToUnbind) { 1570 for (ManagedServiceInfo info : removableBoundServices) { 1571 final Set<ComponentName> allowedComponents = allowedComponentsToBind.get(info.userid); 1572 if (allowedComponents != null) { 1573 if (forceRebind || !allowedComponents.contains(info.component)) { 1574 Set<ComponentName> toUnbind = 1575 componentsToUnbind.get(info.userid, new ArraySet<>()); 1576 toUnbind.add(info.component); 1577 componentsToUnbind.put(info.userid, toUnbind); 1578 } 1579 } 1580 } 1581 } 1582 1583 /** 1584 * Called whenever packages change, the user switches, or the secure setting 1585 * is altered. (For example in response to USER_SWITCHED in our broadcast receiver) 1586 */ rebindServices(boolean forceRebind, int userToRebind)1587 protected void rebindServices(boolean forceRebind, int userToRebind) { 1588 if (DEBUG) Slog.d(TAG, "rebindServices " + forceRebind + " " + userToRebind); 1589 boolean rebindAllCurrentUsers = mUserProfiles.isProfileUser(userToRebind, mContext) 1590 && allowRebindForParentUser(); 1591 IntArray userIds = getUserIdsForRebindServices(userToRebind, rebindAllCurrentUsers); 1592 1593 final SparseArray<Set<ComponentName>> componentsToBind = new SparseArray<>(); 1594 final SparseArray<Set<ComponentName>> componentsToUnbind = new SparseArray<>(); 1595 1596 synchronized (mMutex) { 1597 final SparseArray<ArraySet<ComponentName>> approvedComponentsByUser = 1598 getAllowedComponents(userIds); 1599 final Set<ManagedServiceInfo> removableBoundServices = getRemovableConnectedServices(); 1600 1601 // Filter approvedComponentsByUser to collect all of the components that are allowed 1602 // for the currently active user(s). 1603 populateComponentsToBind(componentsToBind, userIds, approvedComponentsByUser); 1604 1605 // For every current non-system connection, disconnect services that are no longer 1606 // approved, or ALL services if we are force rebinding 1607 populateComponentsToUnbind( 1608 forceRebind, removableBoundServices, componentsToBind, componentsToUnbind); 1609 } 1610 1611 unbindFromServices(componentsToUnbind); 1612 bindToServices(componentsToBind); 1613 } 1614 getUserIdsForRebindServices(int userToRebind, boolean rebindAllCurrentUsers)1615 private IntArray getUserIdsForRebindServices(int userToRebind, boolean rebindAllCurrentUsers) { 1616 IntArray userIds = mUserProfiles.getCurrentProfileIds(); 1617 if (userToRebind != USER_ALL && !rebindAllCurrentUsers) { 1618 userIds = new IntArray(1); 1619 userIds.add(userToRebind); 1620 } else if (managedServicesConcurrentMultiuser() 1621 && userToRebind == USER_ALL) { 1622 for (UserInfo user : mUm.getUsers()) { 1623 if (mUmInternal.isVisibleBackgroundFullUser(user.id) 1624 && !userIds.contains(user.id)) { 1625 userIds.add(user.id); 1626 } 1627 } 1628 } 1629 return userIds; 1630 } 1631 1632 /** 1633 * Called when user switched to unbind all services from other users. 1634 */ 1635 @VisibleForTesting unbindOtherUserServices(int currentUser)1636 void unbindOtherUserServices(int currentUser) { 1637 TimingsTraceAndSlog t = new TimingsTraceAndSlog(); 1638 t.traceBegin("ManagedServices.unbindOtherUserServices_current" + currentUser); 1639 unbindServicesImpl(currentUser, true /* allExceptUser */); 1640 t.traceEnd(); 1641 } 1642 unbindUserServices(int user)1643 void unbindUserServices(int user) { 1644 TimingsTraceAndSlog t = new TimingsTraceAndSlog(); 1645 t.traceBegin("ManagedServices.unbindUserServices" + user); 1646 unbindServicesImpl(user, false /* allExceptUser */); 1647 t.traceEnd(); 1648 } 1649 unbindServicesImpl(int user, boolean allExceptUser)1650 void unbindServicesImpl(int user, boolean allExceptUser) { 1651 final SparseArray<Set<ComponentName>> componentsToUnbind = new SparseArray<>(); 1652 synchronized (mMutex) { 1653 final Set<ManagedServiceInfo> removableBoundServices = getRemovableConnectedServices(); 1654 for (ManagedServiceInfo info : removableBoundServices) { 1655 // User switching is the event for the forground user. 1656 // It should not affect the service of the visible background user. 1657 if ((allExceptUser && (info.userid != user) 1658 && !(managedServicesConcurrentMultiuser() 1659 && info.isVisibleBackgroundUserService)) 1660 || (!allExceptUser && (info.userid == user))) { 1661 Set<ComponentName> toUnbind = 1662 componentsToUnbind.get(info.userid, new ArraySet<>()); 1663 toUnbind.add(info.component); 1664 componentsToUnbind.put(info.userid, toUnbind); 1665 } 1666 } 1667 } 1668 unbindFromServices(componentsToUnbind); 1669 } 1670 unbindFromServices(SparseArray<Set<ComponentName>> componentsToUnbind)1671 protected void unbindFromServices(SparseArray<Set<ComponentName>> componentsToUnbind) { 1672 for (int i = 0; i < componentsToUnbind.size(); i++) { 1673 final int userId = componentsToUnbind.keyAt(i); 1674 final Set<ComponentName> removableComponents = componentsToUnbind.get(userId); 1675 for (ComponentName cn : removableComponents) { 1676 // No longer allowed to be bound, or must rebind. 1677 Slog.v(TAG, "disabling " + getCaption() + " for user " + userId + ": " + cn); 1678 unregisterService(cn, userId); 1679 } 1680 } 1681 } 1682 1683 // Attempt to bind to services, skipping those that cannot be found or lack the permission. bindToServices(SparseArray<Set<ComponentName>> componentsToBind)1684 private void bindToServices(SparseArray<Set<ComponentName>> componentsToBind) { 1685 for (int i = 0; i < componentsToBind.size(); i++) { 1686 final int userId = componentsToBind.keyAt(i); 1687 final Set<ComponentName> add = componentsToBind.get(userId); 1688 for (ComponentName component : add) { 1689 ServiceInfo info = getServiceInfo(component, userId); 1690 if (info == null) { 1691 Slog.w(TAG, "Not binding " + getCaption() + " service " + component 1692 + ": service not found"); 1693 continue; 1694 } 1695 if (!mConfig.bindPermission.equals(info.permission)) { 1696 Slog.w(TAG, "Not binding " + getCaption() + " service " + component 1697 + ": it does not require the permission " + mConfig.bindPermission); 1698 continue; 1699 } 1700 // Do not (auto)bind if service has meta-data to explicitly disallow it 1701 if (!isAutobindAllowed(info) && !isBoundOrRebinding(component, userId)) { 1702 synchronized (mSnoozing) { 1703 Slog.d(TAG, "Not binding " + getCaption() + " service " + component 1704 + ": has META_DATA_DEFAULT_AUTOBIND = false"); 1705 mSnoozing.add(userId, component); 1706 } 1707 continue; 1708 } 1709 1710 Slog.v(TAG, 1711 "enabling " + getCaption() + " for " + userId + ": " + component); 1712 registerService(info, userId); 1713 } 1714 } 1715 } 1716 1717 /** 1718 * Version of registerService that takes the name of a service component to bind to. 1719 */ 1720 @VisibleForTesting registerService(final ServiceInfo si, final int userId)1721 void registerService(final ServiceInfo si, final int userId) { 1722 ensureFilters(si, userId); 1723 registerService(si.getComponentName(), userId); 1724 } 1725 1726 @VisibleForTesting registerService(final ComponentName cn, final int userId)1727 void registerService(final ComponentName cn, final int userId) { 1728 synchronized (mMutex) { 1729 registerServiceLocked(cn, userId); 1730 } 1731 } 1732 1733 @VisibleForTesting reregisterService(final ComponentName cn, final int userId)1734 void reregisterService(final ComponentName cn, final int userId) { 1735 // If rebinding a package that died, ensure it still has permission 1736 // after the rebind delay 1737 if (isPackageOrComponentAllowedWithPermission(cn, userId)) { 1738 registerService(cn, userId); 1739 } else { 1740 if (DEBUG) Slog.v(TAG, "skipped reregisterService cn=" + cn + " u=" + userId 1741 + " because of isPackageOrComponentAllowedWithPermission check"); 1742 } 1743 } 1744 1745 /** 1746 * Inject a system service into the management list. 1747 */ registerSystemService(final ComponentName name, final int userid)1748 public void registerSystemService(final ComponentName name, final int userid) { 1749 synchronized (mMutex) { 1750 registerServiceLocked(name, userid, true /* isSystem */); 1751 } 1752 } 1753 1754 @GuardedBy("mMutex") registerServiceLocked(final ComponentName name, final int userid)1755 private void registerServiceLocked(final ComponentName name, final int userid) { 1756 registerServiceLocked(name, userid, false /* isSystem */); 1757 } 1758 1759 @GuardedBy("mMutex") registerServiceLocked(final ComponentName name, final int userid, final boolean isSystem)1760 private void registerServiceLocked(final ComponentName name, final int userid, 1761 final boolean isSystem) { 1762 if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid); 1763 1764 final Pair<ComponentName, Integer> servicesBindingTag = Pair.create(name, userid); 1765 if (mServicesBound.contains(servicesBindingTag)) { 1766 Slog.v(TAG, "Not registering " + name + " is already bound"); 1767 // stop registering this thing already! we're working on it 1768 return; 1769 } 1770 mServicesBound.add(servicesBindingTag); 1771 1772 final int N = mServices.size(); 1773 for (int i = N - 1; i >= 0; i--) { 1774 final ManagedServiceInfo info = mServices.get(i); 1775 if (name.equals(info.component) 1776 && info.userid == userid) { 1777 // cut old connections 1778 Slog.v(TAG, " disconnecting old " + getCaption() + ": " + info.service); 1779 removeServiceLocked(i); 1780 if (info.connection != null) { 1781 unbindService(info.connection, info.component, info.userid); 1782 } 1783 } 1784 } 1785 1786 Intent intent = new Intent(mConfig.serviceInterface); 1787 intent.setComponent(name); 1788 1789 intent.putExtra(Intent.EXTRA_CLIENT_LABEL, mConfig.clientLabel); 1790 1791 final ActivityOptions activityOptions = ActivityOptions.makeBasic(); 1792 activityOptions.setPendingIntentCreatorBackgroundActivityStartMode( 1793 ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED); 1794 final PendingIntent pendingIntent = PendingIntent.getActivity( 1795 mContext, 0, new Intent(mConfig.settingsAction), PendingIntent.FLAG_IMMUTABLE, 1796 activityOptions.toBundle()); 1797 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent); 1798 1799 ApplicationInfo appInfo = null; 1800 try { 1801 appInfo = mContext.getPackageManager().getApplicationInfoAsUser( 1802 name.getPackageName(), 0, userid); 1803 } catch (NameNotFoundException e) { 1804 // Ignore if the package doesn't exist we won't be able to bind to the service. 1805 } 1806 final int targetSdkVersion = 1807 appInfo != null ? appInfo.targetSdkVersion : Build.VERSION_CODES.BASE; 1808 final int uid = appInfo != null ? appInfo.uid : -1; 1809 1810 try { 1811 Slog.v(TAG, "binding: " + intent); 1812 ServiceConnection serviceConnection = new ServiceConnection() { 1813 IInterface mService; 1814 1815 @Override 1816 public void onServiceConnected(ComponentName name, IBinder binder) { 1817 Slog.v(TAG, userid + " " + getCaption() + " service connected: " + name); 1818 boolean added = false; 1819 ManagedServiceInfo info = null; 1820 synchronized (mMutex) { 1821 mServicesRebinding.remove(servicesBindingTag); 1822 try { 1823 mService = asInterface(binder); 1824 info = newServiceInfo(mService, name, 1825 userid, isSystem, this, targetSdkVersion, uid); 1826 binder.linkToDeath(info, 0); 1827 added = mServices.add(info); 1828 } catch (RemoteException e) { 1829 Slog.e(TAG, "Failed to linkToDeath, already dead", e); 1830 } 1831 } 1832 if (added) { 1833 onServiceAdded(info); 1834 } 1835 } 1836 1837 @Override 1838 public void onServiceDisconnected(ComponentName name) { 1839 Slog.v(TAG, userid + " " + getCaption() + " connection lost: " + name); 1840 } 1841 1842 @Override 1843 public void onBindingDied(ComponentName name) { 1844 Slog.w(TAG, userid + " " + getCaption() + " binding died: " + name); 1845 synchronized (mMutex) { 1846 unbindService(this, name, userid); 1847 if (!mServicesRebinding.contains(servicesBindingTag)) { 1848 mServicesRebinding.add(servicesBindingTag); 1849 mHandler.postDelayed(() -> 1850 reregisterService(name, userid), 1851 ON_BINDING_DIED_REBIND_DELAY_MS); 1852 } else { 1853 Slog.v(TAG, getCaption() + " not rebinding in user " + userid 1854 + " as a previous rebind attempt was made: " + name); 1855 } 1856 } 1857 } 1858 1859 @Override 1860 public void onNullBinding(ComponentName name) { 1861 Slog.v(TAG, "onNullBinding() called with: name = [" + name + "]"); 1862 mContext.unbindService(this); 1863 } 1864 }; 1865 if (!mContext.bindServiceAsUser(intent, 1866 serviceConnection, 1867 getBindFlags(), 1868 new UserHandle(userid))) { 1869 mServicesBound.remove(servicesBindingTag); 1870 Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent 1871 + " in user " + userid); 1872 return; 1873 } 1874 } catch (SecurityException ex) { 1875 mServicesBound.remove(servicesBindingTag); 1876 Slog.e(TAG, "Unable to bind " + getCaption() + " service: " + intent, ex); 1877 } 1878 } 1879 1880 @VisibleForTesting isBound(ComponentName cn, int userId)1881 boolean isBound(ComponentName cn, int userId) { 1882 final Pair<ComponentName, Integer> servicesBindingTag = Pair.create(cn, userId); 1883 synchronized (mMutex) { 1884 return mServicesBound.contains(servicesBindingTag); 1885 } 1886 } 1887 isBoundOrRebinding(final ComponentName cn, final int userId)1888 protected boolean isBoundOrRebinding(final ComponentName cn, final int userId) { 1889 synchronized (mMutex) { 1890 return isBound(cn, userId) || mServicesRebinding.contains(Pair.create(cn, userId)); 1891 } 1892 } 1893 1894 /** 1895 * Remove a service for the given user by ComponentName 1896 */ unregisterService(ComponentName name, int userid)1897 private void unregisterService(ComponentName name, int userid) { 1898 synchronized (mMutex) { 1899 unregisterServiceLocked(name, userid); 1900 } 1901 } 1902 1903 @GuardedBy("mMutex") unregisterServiceLocked(ComponentName name, int userid)1904 private void unregisterServiceLocked(ComponentName name, int userid) { 1905 final int N = mServices.size(); 1906 for (int i = N - 1; i >= 0; i--) { 1907 final ManagedServiceInfo info = mServices.get(i); 1908 if (name.equals(info.component) && info.userid == userid) { 1909 removeServiceLocked(i); 1910 if (info.connection != null) { 1911 unbindService(info.connection, info.component, info.userid); 1912 } 1913 } 1914 } 1915 } 1916 1917 /** 1918 * Removes a service from the list but does not unbind 1919 * 1920 * @return the removed service. 1921 */ removeServiceImpl(IInterface service, final int userid)1922 private ManagedServiceInfo removeServiceImpl(IInterface service, final int userid) { 1923 if (DEBUG) Slog.d(TAG, "removeServiceImpl service=" + service + " u=" + userid); 1924 ManagedServiceInfo serviceInfo = null; 1925 synchronized (mMutex) { 1926 final int N = mServices.size(); 1927 for (int i = N - 1; i >= 0; i--) { 1928 final ManagedServiceInfo info = mServices.get(i); 1929 if (info.service.asBinder() == service.asBinder() && info.userid == userid) { 1930 Slog.d(TAG, "Removing active service " + info.component); 1931 serviceInfo = removeServiceLocked(i); 1932 } 1933 } 1934 } 1935 return serviceInfo; 1936 } 1937 1938 @GuardedBy("mMutex") removeServiceLocked(int i)1939 private ManagedServiceInfo removeServiceLocked(int i) { 1940 final ManagedServiceInfo info = mServices.remove(i); 1941 onServiceRemovedLocked(info); 1942 return info; 1943 } 1944 checkNotNull(IInterface service)1945 private void checkNotNull(IInterface service) { 1946 if (service == null) { 1947 throw new IllegalArgumentException(getCaption() + " must not be null"); 1948 } 1949 } 1950 registerServiceImpl(final IInterface service, final ComponentName component, final int userid, int targetSdk, int uid)1951 private ManagedServiceInfo registerServiceImpl(final IInterface service, 1952 final ComponentName component, final int userid, int targetSdk, int uid) { 1953 ManagedServiceInfo info = newServiceInfo(service, component, userid, 1954 true /*isSystem*/, null /*connection*/, targetSdk, uid); 1955 return registerServiceImpl(info); 1956 } 1957 registerServiceImpl(ManagedServiceInfo info)1958 private ManagedServiceInfo registerServiceImpl(ManagedServiceInfo info) { 1959 synchronized (mMutex) { 1960 try { 1961 info.service.asBinder().linkToDeath(info, 0); 1962 mServices.add(info); 1963 return info; 1964 } catch (RemoteException e) { 1965 // already dead 1966 } 1967 } 1968 return null; 1969 } 1970 1971 /** 1972 * Removes a service from the list and unbinds. 1973 */ unregisterServiceImpl(IInterface service, int userid)1974 private void unregisterServiceImpl(IInterface service, int userid) { 1975 ManagedServiceInfo info = removeServiceImpl(service, userid); 1976 if (info != null && info.connection != null && !info.isGuest(this)) { 1977 unbindService(info.connection, info.component, info.userid); 1978 } 1979 } 1980 unbindService(ServiceConnection connection, ComponentName component, int userId)1981 private void unbindService(ServiceConnection connection, ComponentName component, int userId) { 1982 try { 1983 mContext.unbindService(connection); 1984 } catch (IllegalArgumentException e) { 1985 Slog.e(TAG, getCaption() + " " + component + " could not be unbound", e); 1986 } 1987 synchronized (mMutex) { 1988 mServicesBound.remove(Pair.create(component, userId)); 1989 } 1990 } 1991 getServiceInfo(ComponentName component, int userId)1992 private ServiceInfo getServiceInfo(ComponentName component, int userId) { 1993 try { 1994 return mPm.getServiceInfo(component, 1995 PackageManager.GET_META_DATA 1996 | PackageManager.MATCH_DIRECT_BOOT_AWARE 1997 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 1998 userId); 1999 } catch (RemoteException e) { 2000 e.rethrowFromSystemServer(); 2001 } 2002 return null; 2003 } 2004 isAutobindAllowed(ServiceInfo serviceInfo)2005 private boolean isAutobindAllowed(ServiceInfo serviceInfo) { 2006 if (serviceInfo != null && serviceInfo.metaData != null && serviceInfo.metaData.containsKey( 2007 META_DATA_DEFAULT_AUTOBIND)) { 2008 return serviceInfo.metaData.getBoolean(META_DATA_DEFAULT_AUTOBIND, true); 2009 } 2010 return true; 2011 } 2012 2013 /** 2014 * This method returns the mapped id for the incoming user id 2015 * If the incoming id was not the id of the visible background user, it returns USER_CURRENT. 2016 * In the other cases, it returns the same value as the input. 2017 * 2018 * @param userId the id of the user 2019 * @return the user id if it is a visible background user, otherwise 2020 * {@link UserHandle#USER_CURRENT} 2021 */ 2022 @FlaggedApi(FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER) 2023 @VisibleForTesting resolveUserId(int userId)2024 public int resolveUserId(int userId) { 2025 if (managedServicesConcurrentMultiuser()) { 2026 if (mUmInternal.isVisibleBackgroundFullUser(userId)) { 2027 // The dataset of the visible background user should be managed independently. 2028 return userId; 2029 } 2030 } 2031 // The data of current user and its profile users need to be managed 2032 // in a dataset as before. 2033 return UserHandle.USER_CURRENT; 2034 } 2035 2036 /** 2037 * Returns true if services in the parent user should be rebound 2038 * when rebindServices is called with a profile userId. 2039 * Must be false for NotificationAssistants. 2040 */ allowRebindForParentUser()2041 protected abstract boolean allowRebindForParentUser(); 2042 2043 public class ManagedServiceInfo implements IBinder.DeathRecipient { 2044 public IInterface service; 2045 public ComponentName component; 2046 public int userid; 2047 public boolean isSystem; 2048 @FlaggedApi(FLAG_LIFETIME_EXTENSION_REFACTOR) 2049 public boolean isSystemUi; 2050 public ServiceConnection connection; 2051 public int targetSdkVersion; 2052 public Pair<ComponentName, Integer> mKey; 2053 public int uid; 2054 @FlaggedApi(FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER) 2055 public boolean isVisibleBackgroundUserService; 2056 ManagedServiceInfo(IInterface service, ComponentName component, int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion, int uid)2057 public ManagedServiceInfo(IInterface service, ComponentName component, 2058 int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion, 2059 int uid) { 2060 this.service = service; 2061 this.component = component; 2062 this.userid = userid; 2063 this.isSystem = isSystem; 2064 this.connection = connection; 2065 this.targetSdkVersion = targetSdkVersion; 2066 this.uid = uid; 2067 if (managedServicesConcurrentMultiuser()) { 2068 this.isVisibleBackgroundUserService = LocalServices 2069 .getService(UserManagerInternal.class).isVisibleBackgroundFullUser(userid); 2070 } 2071 mKey = Pair.create(component, userid); 2072 } 2073 isGuest(ManagedServices host)2074 public boolean isGuest(ManagedServices host) { 2075 return ManagedServices.this != host; 2076 } 2077 getOwner()2078 public ManagedServices getOwner() { 2079 return ManagedServices.this; 2080 } 2081 getService()2082 public IInterface getService() { 2083 return service; 2084 } 2085 isSystem()2086 public boolean isSystem() { 2087 return isSystem; 2088 } 2089 2090 @FlaggedApi(FLAG_LIFETIME_EXTENSION_REFACTOR) isSystemUi()2091 public boolean isSystemUi() { 2092 return isSystemUi; 2093 } 2094 2095 @Override toString()2096 public String toString() { 2097 return new StringBuilder("ManagedServiceInfo[") 2098 .append("component=").append(component) 2099 .append(",userid=").append(userid) 2100 .append(",isSystem=").append(isSystem) 2101 .append(",targetSdkVersion=").append(targetSdkVersion) 2102 .append(",connection=").append(connection == null ? null : "<connection>") 2103 .append(",service=").append(service) 2104 .append(",serviceAsBinder=").append(service != null ? service.asBinder() : null) 2105 .append(']').toString(); 2106 } 2107 dumpDebug(ProtoOutputStream proto, long fieldId, ManagedServices host)2108 public void dumpDebug(ProtoOutputStream proto, long fieldId, ManagedServices host) { 2109 final long token = proto.start(fieldId); 2110 component.dumpDebug(proto, ManagedServiceInfoProto.COMPONENT); 2111 proto.write(ManagedServiceInfoProto.USER_ID, userid); 2112 proto.write(ManagedServiceInfoProto.SERVICE, service.getClass().getName()); 2113 proto.write(ManagedServiceInfoProto.IS_SYSTEM, isSystem); 2114 proto.write(ManagedServiceInfoProto.IS_GUEST, isGuest(host)); 2115 proto.end(token); 2116 } 2117 isSameUser(int userId)2118 public boolean isSameUser(int userId) { 2119 if (!isEnabledForUser()) { 2120 return false; 2121 } 2122 return userId == USER_ALL || userId == this.userid; 2123 } 2124 enabledAndUserMatches(int nid)2125 public boolean enabledAndUserMatches(int nid) { 2126 if (!isEnabledForUser()) { 2127 return false; 2128 } 2129 if (this.userid == USER_ALL) return true; 2130 if (this.isSystem) return true; 2131 if (nid == USER_ALL || nid == this.userid) return true; 2132 if (managedServicesConcurrentMultiuser() 2133 && mUmInternal.getProfileParentId(nid) 2134 != mUmInternal.getProfileParentId(this.userid)) { 2135 // If the profile parent IDs do not match each other, 2136 // it is determined that the users do not match. 2137 // This situation may occur when comparing the current user's ID 2138 // with the visible background user's ID. 2139 return false; 2140 } 2141 return supportsProfiles() 2142 && mUserProfiles.isCurrentProfile(nid) 2143 && isPermittedForProfile(nid); 2144 } 2145 supportsProfiles()2146 public boolean supportsProfiles() { 2147 return targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP; 2148 } 2149 2150 @Override binderDied()2151 public void binderDied() { 2152 if (DEBUG) Slog.d(TAG, "binderDied " + this); 2153 // Remove the service, but don't unbind from the service. The system will bring the 2154 // service back up, and the onServiceConnected handler will read the service with the 2155 // new binding. If this isn't a bound service, and is just a registered 2156 // service, just removing it from the list is all we need to do anyway. 2157 removeServiceImpl(this.service, this.userid); 2158 } 2159 2160 /** 2161 * convenience method for looking in mEnabledServicesByUser. 2162 * If FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER is disabled, this manages the data using 2163 * only UserHandle.USER_CURRENT as the key, in order to behave the same as the legacy logic. 2164 */ isEnabledForUser()2165 public boolean isEnabledForUser() { 2166 if (this.isSystem) return true; 2167 if (this.connection == null) return false; 2168 synchronized (mMutex) { 2169 int resolvedUserId = managedServicesConcurrentMultiuser() 2170 ? resolveUserId(this.userid) 2171 : UserHandle.USER_CURRENT; 2172 ArraySet<ComponentName> enabledServices = 2173 mEnabledServicesByUser.get(resolvedUserId); 2174 return enabledServices != null && enabledServices.contains(this.component); 2175 } 2176 } 2177 2178 /** 2179 * Returns true if this service is allowed to receive events for the given userId. A 2180 * managed profile owner can disallow non-system services running outside of the profile 2181 * from receiving events from the profile. 2182 */ isPermittedForProfile(int userId)2183 public boolean isPermittedForProfile(int userId) { 2184 if (!mUserProfiles.isProfileUser(userId, mContext)) { 2185 return true; 2186 } 2187 DevicePolicyManager dpm = 2188 (DevicePolicyManager) mContext.getSystemService(DEVICE_POLICY_SERVICE); 2189 final long identity = Binder.clearCallingIdentity(); 2190 try { 2191 return dpm.isNotificationListenerServicePermitted( 2192 component.getPackageName(), userId); 2193 } finally { 2194 Binder.restoreCallingIdentity(identity); 2195 } 2196 } 2197 2198 @Override equals(Object o)2199 public boolean equals(Object o) { 2200 if (this == o) return true; 2201 if (o == null || getClass() != o.getClass()) return false; 2202 ManagedServiceInfo that = (ManagedServiceInfo) o; 2203 return userid == that.userid 2204 && isSystem == that.isSystem 2205 && targetSdkVersion == that.targetSdkVersion 2206 && Objects.equals(service, that.service) 2207 && Objects.equals(component, that.component) 2208 && Objects.equals(connection, that.connection); 2209 } 2210 2211 @Override hashCode()2212 public int hashCode() { 2213 return Objects.hash(service, component, userid, isSystem, connection, targetSdkVersion); 2214 } 2215 } 2216 2217 /** convenience method for looking in mEnabledServicesByUser for UserHandle.USER_CURRENT. 2218 * This is a legacy API. When FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER becomes 2219 * trunk stable, this API should be deprecated. Additionally, when this method 2220 * is deprecated, the unit tests written using this method should also be revised. 2221 * 2222 * @param component target component name 2223 * @return boolean value that indicates whether it is enabled for the current profiles 2224 */ isComponentEnabledForCurrentProfiles(ComponentName component)2225 public boolean isComponentEnabledForCurrentProfiles(ComponentName component) { 2226 return isComponentEnabledForUser(component, UserHandle.USER_CURRENT); 2227 } 2228 2229 /** convenience method for looking in mEnabledServicesForUser 2230 * 2231 * @param component target component name 2232 * @param userId the id of the target user 2233 * @return boolean value that indicates whether it is enabled for the target user 2234 */ 2235 @FlaggedApi(FLAG_MANAGED_SERVICES_CONCURRENT_MULTIUSER) isComponentEnabledForUser(ComponentName component, int userId)2236 public boolean isComponentEnabledForUser(ComponentName component, int userId) { 2237 synchronized (mMutex) { 2238 ArraySet<ComponentName> enabledServicesForUser = 2239 mEnabledServicesByUser.get(resolveUserId(userId)); 2240 return enabledServicesForUser != null && enabledServicesForUser.contains(component); 2241 } 2242 } 2243 2244 public static class UserProfiles { 2245 // Profiles of the current user. 2246 private final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<>(); 2247 updateCache(@onNull Context context)2248 public void updateCache(@NonNull Context context) { 2249 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 2250 if (userManager != null) { 2251 int currentUserId = ActivityManager.getCurrentUser(); 2252 List<UserInfo> profiles = userManager.getProfiles(currentUserId); 2253 synchronized (mCurrentProfiles) { 2254 mCurrentProfiles.clear(); 2255 for (UserInfo user : profiles) { 2256 mCurrentProfiles.put(user.id, user); 2257 } 2258 } 2259 } 2260 } 2261 2262 /** 2263 * Returns the currently active users (generally one user and its work profile). 2264 */ getCurrentProfileIds()2265 public IntArray getCurrentProfileIds() { 2266 synchronized (mCurrentProfiles) { 2267 IntArray users = new IntArray(mCurrentProfiles.size()); 2268 final int N = mCurrentProfiles.size(); 2269 for (int i = 0; i < N; ++i) { 2270 users.add(mCurrentProfiles.keyAt(i)); 2271 } 2272 return users; 2273 } 2274 } 2275 isCurrentProfile(int userId)2276 public boolean isCurrentProfile(int userId) { 2277 synchronized (mCurrentProfiles) { 2278 return mCurrentProfiles.get(userId) != null; 2279 } 2280 } 2281 isProfileUser(int userId, Context context)2282 public boolean isProfileUser(int userId, Context context) { 2283 synchronized (mCurrentProfiles) { 2284 UserInfo user = mCurrentProfiles.get(userId); 2285 if (user == null) { 2286 return false; 2287 } 2288 if (privateSpaceFlagsEnabled()) { 2289 return user.isProfile() && hasParent(user, context); 2290 } 2291 return user.isManagedProfile() || user.isCloneProfile(); 2292 } 2293 } 2294 hasParent(UserInfo profile, Context context)2295 boolean hasParent(UserInfo profile, Context context) { 2296 final long identity = Binder.clearCallingIdentity(); 2297 try { 2298 UserManager um = context.getSystemService(UserManager.class); 2299 return um.getProfileParent(profile.id) != null; 2300 } finally { 2301 Binder.restoreCallingIdentity(identity); 2302 } 2303 } 2304 } 2305 2306 public static class Config { 2307 public String caption; 2308 public String serviceInterface; 2309 public String secureSettingName; 2310 public String secondarySettingName; 2311 public String xmlTag; 2312 public String bindPermission; 2313 public String settingsAction; 2314 public int clientLabel; 2315 } 2316 } 2317