1 /* 2 * Copyright (C) 2018 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.role; 18 19 import android.Manifest; 20 import android.annotation.AnyThread; 21 import android.annotation.MainThread; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.UserIdInt; 25 import android.annotation.WorkerThread; 26 import android.app.AppOpsManager; 27 import android.app.admin.DevicePolicyManager; 28 import android.app.role.IOnRoleHoldersChangedListener; 29 import android.app.role.IRoleManager; 30 import android.app.role.RoleControllerManager; 31 import android.app.role.RoleManager; 32 import android.content.BroadcastReceiver; 33 import android.content.Context; 34 import android.content.Intent; 35 import android.content.IntentFilter; 36 import android.content.pm.PackageManager; 37 import android.database.ContentObserver; 38 import android.net.Uri; 39 import android.os.Binder; 40 import android.os.Build; 41 import android.os.Handler; 42 import android.os.ParcelFileDescriptor; 43 import android.os.RemoteCallback; 44 import android.os.RemoteCallbackList; 45 import android.os.RemoteException; 46 import android.os.UserHandle; 47 import android.os.UserManager; 48 import android.permission.flags.Flags; 49 import android.provider.Settings; 50 import android.text.TextUtils; 51 import android.util.ArraySet; 52 import android.util.IndentingPrintWriter; 53 import android.util.Log; 54 import android.util.SparseArray; 55 import android.util.proto.ProtoOutputStream; 56 57 import androidx.annotation.Keep; 58 import androidx.annotation.RequiresApi; 59 60 import com.android.internal.annotations.GuardedBy; 61 import com.android.internal.infra.AndroidFuture; 62 import com.android.internal.util.Preconditions; 63 import com.android.internal.util.dump.DualDumpOutputStream; 64 import com.android.modules.utils.build.SdkLevel; 65 import com.android.permission.compat.UserHandleCompat; 66 import com.android.permission.util.ArrayUtils; 67 import com.android.permission.util.CollectionUtils; 68 import com.android.permission.util.ForegroundThread; 69 import com.android.permission.util.PackageUtils; 70 import com.android.permission.util.ThrottledRunnable; 71 import com.android.permission.util.UserUtils; 72 import com.android.server.LocalManagerRegistry; 73 import com.android.server.SystemService; 74 import com.android.server.role.RoleServicePlatformHelper; 75 76 import java.io.FileDescriptor; 77 import java.io.FileOutputStream; 78 import java.io.PrintWriter; 79 import java.util.ArrayList; 80 import java.util.Collections; 81 import java.util.List; 82 import java.util.Map; 83 import java.util.Objects; 84 import java.util.Set; 85 import java.util.concurrent.ExecutionException; 86 import java.util.concurrent.TimeUnit; 87 import java.util.concurrent.TimeoutException; 88 89 /** 90 * Service for role management. 91 * 92 * @see RoleManager 93 */ 94 @Keep 95 @RequiresApi(Build.VERSION_CODES.S) 96 public class RoleService extends SystemService implements RoleUserState.Callback { 97 private static final String LOG_TAG = RoleService.class.getSimpleName(); 98 99 private static final boolean DEBUG = false; 100 101 private static final long GRANT_DEFAULT_ROLES_INTERVAL_MILLIS = 1000; 102 103 private static final String[] DEFAULT_APPLICATION_ROLES; 104 105 static { 106 List<String> defaultApplicationRoles = new ArrayList<>(); 107 defaultApplicationRoles.add(RoleManager.ROLE_ASSISTANT); 108 defaultApplicationRoles.add(RoleManager.ROLE_BROWSER); 109 defaultApplicationRoles.add(RoleManager.ROLE_CALL_REDIRECTION); 110 defaultApplicationRoles.add(RoleManager.ROLE_CALL_SCREENING); 111 defaultApplicationRoles.add(RoleManager.ROLE_DIALER); 112 defaultApplicationRoles.add(RoleManager.ROLE_HOME); 113 defaultApplicationRoles.add(RoleManager.ROLE_SMS); 114 if (SdkLevel.isAtLeastV()) { 115 defaultApplicationRoles.add(RoleManager.ROLE_WALLET); 116 } 117 DEFAULT_APPLICATION_ROLES = defaultApplicationRoles.toArray(new String[0]); 118 } 119 120 @NonNull 121 private final AppOpsManager mAppOpsManager; 122 123 @NonNull 124 private final Object mLock = new Object(); 125 126 @NonNull 127 private final RoleServicePlatformHelper mPlatformHelper; 128 129 /** 130 * Maps user id to its state. 131 */ 132 @GuardedBy("mLock") 133 @NonNull 134 private final SparseArray<RoleUserState> mUserStates = new SparseArray<>(); 135 136 /** 137 * Maps user id to its controller. 138 */ 139 @GuardedBy("mLock") 140 @NonNull 141 private final SparseArray<RoleController> mControllers = new SparseArray<>(); 142 143 /** 144 * Maps user id to its list of listeners. 145 */ 146 @GuardedBy("mLock") 147 @NonNull 148 private final SparseArray<RemoteCallbackList<IOnRoleHoldersChangedListener>> mListeners = 149 new SparseArray<>(); 150 151 @NonNull 152 private final Handler mListenerHandler = ForegroundThread.getHandler(); 153 154 @GuardedBy("mLock") 155 private boolean mBypassingRoleQualification; 156 157 /** 158 * Maps user id to its throttled runnable for granting default roles. 159 */ 160 @GuardedBy("mLock") 161 @NonNull 162 private final SparseArray<ThrottledRunnable> mGrantDefaultRolesThrottledRunnables = 163 new SparseArray<>(); 164 RoleService(@onNull Context context)165 public RoleService(@NonNull Context context) { 166 super(context); 167 168 mPlatformHelper = LocalManagerRegistry.getManager(RoleServicePlatformHelper.class); 169 170 RoleControllerManager.initializeRemoteServiceComponentName(context); 171 172 mAppOpsManager = context.getSystemService(AppOpsManager.class); 173 174 LocalManagerRegistry.addManager(RoleManagerLocal.class, new Local()); 175 176 registerUserRemovedReceiver(); 177 } 178 registerUserRemovedReceiver()179 private void registerUserRemovedReceiver() { 180 IntentFilter intentFilter = new IntentFilter(); 181 intentFilter.addAction(Intent.ACTION_USER_REMOVED); 182 getContext().registerReceiverForAllUsers(new BroadcastReceiver() { 183 @Override 184 public void onReceive(@NonNull Context context, @NonNull Intent intent) { 185 if (TextUtils.equals(intent.getAction(), Intent.ACTION_USER_REMOVED)) { 186 int userId = intent.<UserHandle>getParcelableExtra(Intent.EXTRA_USER) 187 .getIdentifier(); 188 onRemoveUser(userId); 189 } 190 } 191 }, intentFilter, null, null); 192 } 193 194 @Override onStart()195 public void onStart() { 196 publishBinderService(Context.ROLE_SERVICE, new Stub()); 197 198 Context context = getContext(); 199 IntentFilter packageIntentFilter = new IntentFilter(); 200 packageIntentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); 201 packageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); 202 packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); 203 packageIntentFilter.addDataScheme("package"); 204 packageIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 205 context.registerReceiverForAllUsers(new BroadcastReceiver() { 206 @Override 207 public void onReceive(Context context, Intent intent) { 208 int userId = UserHandleCompat.getUserId(intent.getIntExtra(Intent.EXTRA_UID, -1)); 209 if (DEBUG) { 210 Log.i(LOG_TAG, "Packages changed - re-running initial grants for user " 211 + userId); 212 } 213 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction()) 214 && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { 215 // Package is being upgraded - we're about to get ACTION_PACKAGE_ADDED 216 return; 217 } 218 maybeGrantDefaultRolesAsync(userId); 219 } 220 }, packageIntentFilter, null, null); 221 222 if (SdkLevel.isAtLeastV()) { 223 IntentFilter devicePolicyIntentFilter = new IntentFilter(); 224 devicePolicyIntentFilter.addAction( 225 DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED); 226 devicePolicyIntentFilter.addAction( 227 DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED); 228 devicePolicyIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 229 context.registerReceiverForAllUsers(new BroadcastReceiver() { 230 @Override 231 public void onReceive(Context context, Intent intent) { 232 int userId = getSendingUser().getIdentifier(); 233 if (DEBUG) { 234 Log.i(LOG_TAG, "Device policy changed (" + intent.getAction() 235 + ") - re-running initial grants for user " + userId); 236 } 237 maybeGrantDefaultRolesAsync(userId); 238 } 239 }, devicePolicyIntentFilter, null, null); 240 241 context.getContentResolver().registerContentObserver( 242 Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE), false, 243 new ContentObserver(ForegroundThread.getHandler()) { 244 public void onChange(boolean selfChange, Uri uri) { 245 if (DEBUG) { 246 Log.i(LOG_TAG, "Settings.Global.DEVICE_DEMO_MODE changed."); 247 } 248 UserManager userManager = 249 context.getSystemService(UserManager.class); 250 List<UserHandle> users = userManager.getUserHandles(true); 251 int usersSize = users.size(); 252 for (int i = 0; i < usersSize; i++) { 253 maybeGrantDefaultRolesAsync(users.get(i).getIdentifier()); 254 } 255 } 256 }); 257 } 258 } 259 260 @Override onUserStarting(@onNull TargetUser user)261 public void onUserStarting(@NonNull TargetUser user) { 262 if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) { 263 upgradeLegacyFallbackEnabledRolesIfNeeded(user); 264 } 265 266 maybeGrantDefaultRolesSync(user.getUserHandle().getIdentifier()); 267 } 268 upgradeLegacyFallbackEnabledRolesIfNeeded(@onNull TargetUser user)269 private void upgradeLegacyFallbackEnabledRolesIfNeeded(@NonNull TargetUser user) { 270 int userId = user.getUserHandle().getIdentifier(); 271 RoleUserState userState = getOrCreateUserState(userId); 272 if (!userState.isVersionUpgradeNeeded()) { 273 return; 274 } 275 List<String> legacyFallbackDisabledRoles = getLegacyFallbackDisabledRolesSync(userId); 276 if (legacyFallbackDisabledRoles == null) { 277 return; 278 } 279 Log.v(LOG_TAG, "Received legacy fallback disabled roles: " + legacyFallbackDisabledRoles); 280 userState.upgradeVersion(legacyFallbackDisabledRoles); 281 } 282 283 @MainThread getLegacyFallbackDisabledRolesSync(@serIdInt int userId)284 private List<String> getLegacyFallbackDisabledRolesSync(@UserIdInt int userId) { 285 AndroidFuture<List<String>> future = new AndroidFuture<>(); 286 RoleController controller = new RemoteRoleController(UserHandle.of(userId), getContext()); 287 controller.getLegacyFallbackDisabledRoles(ForegroundThread.getExecutor(), future::complete); 288 try { 289 return future.get(30, TimeUnit.SECONDS); 290 } catch (InterruptedException | ExecutionException | TimeoutException e) { 291 Log.e(LOG_TAG, "Failed to get the legacy role fallback disabled state for user " 292 + userId, e); 293 return null; 294 } 295 } 296 297 @MainThread maybeGrantDefaultRolesSync(@serIdInt int userId)298 private void maybeGrantDefaultRolesSync(@UserIdInt int userId) { 299 AndroidFuture<Void> future = maybeGrantDefaultRolesInternal(userId); 300 try { 301 future.get(30, TimeUnit.SECONDS); 302 } catch (InterruptedException | ExecutionException | TimeoutException e) { 303 Log.e(LOG_TAG, "Failed to grant default roles for user " + userId, e); 304 } 305 } 306 maybeGrantDefaultRolesAsync(@serIdInt int userId)307 private void maybeGrantDefaultRolesAsync(@UserIdInt int userId) { 308 ThrottledRunnable runnable; 309 synchronized (mLock) { 310 runnable = mGrantDefaultRolesThrottledRunnables.get(userId); 311 if (runnable == null) { 312 runnable = new ThrottledRunnable(ForegroundThread.getHandler(), 313 GRANT_DEFAULT_ROLES_INTERVAL_MILLIS, 314 () -> maybeGrantDefaultRolesInternal(userId)); 315 mGrantDefaultRolesThrottledRunnables.put(userId, runnable); 316 } 317 } 318 runnable.run(); 319 } 320 321 @AnyThread 322 @NonNull maybeGrantDefaultRolesInternal(@serIdInt int userId)323 private AndroidFuture<Void> maybeGrantDefaultRolesInternal(@UserIdInt int userId) { 324 if (!UserUtils.isUserExistent(userId, getContext())) { 325 Log.w(LOG_TAG, "User " + userId + " does not exist"); 326 return AndroidFuture.completedFuture(null); 327 } 328 329 RoleUserState userState = getOrCreateUserState(userId); 330 String oldPackagesHash = userState.getPackagesHash(); 331 String newPackagesHash = mPlatformHelper.computePackageStateHash(userId); 332 if (Objects.equals(oldPackagesHash, newPackagesHash)) { 333 if (DEBUG) { 334 Log.i(LOG_TAG, "Already granted default roles for packages hash " 335 + newPackagesHash); 336 } 337 return AndroidFuture.completedFuture(null); 338 } 339 340 // Some package state has changed, so grant default roles again. 341 Log.i(LOG_TAG, "Granting default roles..."); 342 AndroidFuture<Void> future = new AndroidFuture<>(); 343 getOrCreateController(userId).grantDefaultRoles(ForegroundThread.getExecutor(), 344 successful -> { 345 if (successful) { 346 userState.setPackagesHash(newPackagesHash); 347 future.complete(null); 348 } else { 349 future.completeExceptionally(new RuntimeException()); 350 } 351 }); 352 return future; 353 } 354 355 @NonNull getOrCreateUserState(@serIdInt int userId)356 private RoleUserState getOrCreateUserState(@UserIdInt int userId) { 357 synchronized (mLock) { 358 RoleUserState userState = mUserStates.get(userId); 359 if (userState == null) { 360 userState = new RoleUserState(userId, mPlatformHelper, this, 361 mBypassingRoleQualification); 362 mUserStates.put(userId, userState); 363 } 364 return userState; 365 } 366 } 367 368 @NonNull getOrCreateController(@serIdInt int userId)369 private RoleController getOrCreateController(@UserIdInt int userId) { 370 synchronized (mLock) { 371 RoleController controller = mControllers.get(userId); 372 if (controller == null) { 373 UserHandle user = UserHandle.of(userId); 374 Context context = getContext(); 375 if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) { 376 controller = new LocalRoleController(user, context); 377 } else { 378 controller = new RemoteRoleController(user, context); 379 } 380 mControllers.put(userId, controller); 381 } 382 return controller; 383 } 384 } 385 386 @Nullable getListeners(@serIdInt int userId)387 private RemoteCallbackList<IOnRoleHoldersChangedListener> getListeners(@UserIdInt int userId) { 388 synchronized (mLock) { 389 return mListeners.get(userId); 390 } 391 } 392 393 @NonNull getOrCreateListeners( @serIdInt int userId)394 private RemoteCallbackList<IOnRoleHoldersChangedListener> getOrCreateListeners( 395 @UserIdInt int userId) { 396 synchronized (mLock) { 397 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = mListeners.get(userId); 398 if (listeners == null) { 399 listeners = new RemoteCallbackList<>(); 400 mListeners.put(userId, listeners); 401 } 402 return listeners; 403 } 404 } 405 onRemoveUser(@serIdInt int userId)406 private void onRemoveUser(@UserIdInt int userId) { 407 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners; 408 RoleUserState userState; 409 synchronized (mLock) { 410 mGrantDefaultRolesThrottledRunnables.remove(userId); 411 listeners = mListeners.get(userId); 412 mListeners.remove(userId); 413 mControllers.remove(userId); 414 userState = mUserStates.get(userId); 415 mUserStates.remove(userId); 416 } 417 if (listeners != null) { 418 listeners.kill(); 419 } 420 if (userState != null) { 421 userState.destroy(); 422 } 423 } 424 425 @Override onRoleHoldersChanged(@onNull String roleName, @UserIdInt int userId)426 public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) { 427 mListenerHandler.post(() -> notifyRoleHoldersChanged(roleName, userId)); 428 } 429 430 @WorkerThread notifyRoleHoldersChanged(@onNull String roleName, @UserIdInt int userId)431 private void notifyRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) { 432 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId); 433 if (listeners != null) { 434 notifyRoleHoldersChangedForListeners(listeners, roleName, userId); 435 } 436 437 RemoteCallbackList<IOnRoleHoldersChangedListener> allUsersListeners = getListeners( 438 UserHandleCompat.USER_ALL); 439 if (allUsersListeners != null) { 440 notifyRoleHoldersChangedForListeners(allUsersListeners, roleName, userId); 441 } 442 } 443 444 @WorkerThread notifyRoleHoldersChangedForListeners( @onNull RemoteCallbackList<IOnRoleHoldersChangedListener> listeners, @NonNull String roleName, @UserIdInt int userId)445 private void notifyRoleHoldersChangedForListeners( 446 @NonNull RemoteCallbackList<IOnRoleHoldersChangedListener> listeners, 447 @NonNull String roleName, @UserIdInt int userId) { 448 int broadcastCount = listeners.beginBroadcast(); 449 try { 450 for (int i = 0; i < broadcastCount; i++) { 451 IOnRoleHoldersChangedListener listener = listeners.getBroadcastItem(i); 452 try { 453 listener.onRoleHoldersChanged(roleName, userId); 454 } catch (RemoteException e) { 455 Log.e(LOG_TAG, "Error calling OnRoleHoldersChangedListener", e); 456 } 457 } 458 } finally { 459 listeners.finishBroadcast(); 460 } 461 } 462 463 private class Stub extends IRoleManager.Stub { 464 465 @Override isRoleAvailableAsUser(@onNull String roleName, @UserIdInt int userId)466 public boolean isRoleAvailableAsUser(@NonNull String roleName, @UserIdInt int userId) { 467 UserUtils.enforceCrossUserPermission(userId, false, "isRoleAvailableAsUser", 468 getContext()); 469 if (!UserUtils.isUserExistent(userId, getContext())) { 470 Log.e(LOG_TAG, "user " + userId + " does not exist"); 471 return false; 472 } 473 474 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 475 476 return getOrCreateUserState(userId).isRoleAvailable(roleName); 477 } 478 479 @Override isRoleHeldAsUser(@onNull String roleName, @NonNull String packageName, @UserIdInt int userId)480 public boolean isRoleHeldAsUser(@NonNull String roleName, @NonNull String packageName, 481 @UserIdInt int userId) { 482 mAppOpsManager.checkPackage(getCallingUid(), packageName); 483 484 UserUtils.enforceCrossUserPermission(userId, false, "isRoleHeldAsUser", getContext()); 485 if (!UserUtils.isUserExistent(userId, getContext())) { 486 Log.e(LOG_TAG, "user " + userId + " does not exist"); 487 return false; 488 } 489 490 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 491 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 492 493 ArraySet<String> roleHolders = getOrCreateUserState(userId).getRoleHolders(roleName); 494 if (roleHolders == null) { 495 return false; 496 } 497 return roleHolders.contains(packageName); 498 } 499 500 @NonNull 501 @Override getRoleHoldersAsUser(@onNull String roleName, @UserIdInt int userId)502 public List<String> getRoleHoldersAsUser(@NonNull String roleName, @UserIdInt int userId) { 503 UserUtils.enforceCrossUserPermission(userId, false, "getRoleHoldersAsUser", 504 getContext()); 505 if (!UserUtils.isUserExistent(userId, getContext())) { 506 Log.e(LOG_TAG, "user " + userId + " does not exist"); 507 return Collections.emptyList(); 508 } 509 510 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, 511 "getRoleHoldersAsUser"); 512 513 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 514 515 ArraySet<String> roleHolders = getOrCreateUserState(userId).getRoleHolders(roleName); 516 if (roleHolders == null) { 517 return Collections.emptyList(); 518 } 519 return new ArrayList<>(roleHolders); 520 } 521 522 @Override addRoleHolderAsUser(@onNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback)523 public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName, 524 @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, 525 @NonNull RemoteCallback callback) { 526 UserUtils.enforceCrossUserPermission(userId, false, "addRoleHolderAsUser", 527 getContext()); 528 if (!UserUtils.isUserExistent(userId, getContext())) { 529 Log.e(LOG_TAG, "user " + userId + " does not exist"); 530 return; 531 } 532 533 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, 534 "addRoleHolderAsUser"); 535 536 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 537 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 538 Objects.requireNonNull(callback, "callback cannot be null"); 539 540 getOrCreateController(userId).onAddRoleHolder(roleName, packageName, flags, callback); 541 } 542 543 @Override removeRoleHolderAsUser(@onNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback)544 public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName, 545 @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, 546 @NonNull RemoteCallback callback) { 547 UserUtils.enforceCrossUserPermission(userId, false, "removeRoleHolderAsUser", 548 getContext()); 549 if (!UserUtils.isUserExistent(userId, getContext())) { 550 Log.e(LOG_TAG, "user " + userId + " does not exist"); 551 return; 552 } 553 554 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, 555 "removeRoleHolderAsUser"); 556 557 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 558 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 559 Objects.requireNonNull(callback, "callback cannot be null"); 560 561 getOrCreateController(userId).onRemoveRoleHolder(roleName, packageName, flags, 562 callback); 563 } 564 565 @Override clearRoleHoldersAsUser(@onNull String roleName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback)566 public void clearRoleHoldersAsUser(@NonNull String roleName, 567 @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, 568 @NonNull RemoteCallback callback) { 569 UserUtils.enforceCrossUserPermission(userId, false, "clearRoleHoldersAsUser", 570 getContext()); 571 if (!UserUtils.isUserExistent(userId, getContext())) { 572 Log.e(LOG_TAG, "user " + userId + " does not exist"); 573 return; 574 } 575 576 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, 577 "clearRoleHoldersAsUser"); 578 579 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 580 Objects.requireNonNull(callback, "callback cannot be null"); 581 582 getOrCreateController(userId).onClearRoleHolders(roleName, flags, callback); 583 } 584 585 @Override 586 @Nullable getDefaultApplicationAsUser(@onNull String roleName, @UserIdInt int userId)587 public String getDefaultApplicationAsUser(@NonNull String roleName, @UserIdInt int userId) { 588 UserUtils.enforceCrossUserPermission(userId, false, "getDefaultApplicationAsUser", 589 getContext()); 590 if (!UserUtils.isUserExistent(userId, getContext())) { 591 Log.e(LOG_TAG, "user " + userId + " does not exist"); 592 return null; 593 } 594 595 getContext().enforceCallingOrSelfPermission( 596 Manifest.permission.MANAGE_DEFAULT_APPLICATIONS, "getDefaultApplicationAsUser"); 597 598 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 599 Preconditions.checkArgumentIsSupported(DEFAULT_APPLICATION_ROLES, roleName); 600 601 ArraySet<String> roleHolders = getOrCreateUserState( 602 userId).getRoleHolders(roleName); 603 if (CollectionUtils.isEmpty(roleHolders)) { 604 return null; 605 } 606 return roleHolders.valueAt(0); 607 } 608 609 @Override setDefaultApplicationAsUser(@onNull String roleName, @Nullable String packageName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback)610 public void setDefaultApplicationAsUser(@NonNull String roleName, 611 @Nullable String packageName, @RoleManager.ManageHoldersFlags int flags, 612 @UserIdInt int userId, @NonNull RemoteCallback callback) { 613 UserUtils.enforceCrossUserPermission(userId, false, "setDefaultApplicationAsUser", 614 getContext()); 615 if (!UserUtils.isUserExistent(userId, getContext())) { 616 Log.e(LOG_TAG, "user " + userId + " does not exist"); 617 return; 618 } 619 620 getContext().enforceCallingOrSelfPermission( 621 Manifest.permission.MANAGE_DEFAULT_APPLICATIONS, "setDefaultApplicationAsUser"); 622 623 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 624 Preconditions.checkArgumentIsSupported(DEFAULT_APPLICATION_ROLES, roleName); 625 Objects.requireNonNull(callback, "callback cannot be null"); 626 627 RoleController roleController = getOrCreateController(userId); 628 if (packageName != null) { 629 roleController.onAddRoleHolder(roleName, packageName, flags, callback); 630 } else { 631 roleController.onClearRoleHolders(roleName, flags, callback); 632 } 633 } 634 635 @Override addOnRoleHoldersChangedListenerAsUser( @onNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId)636 public void addOnRoleHoldersChangedListenerAsUser( 637 @NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) { 638 UserUtils.enforceCrossUserPermission(userId, true, 639 "addOnRoleHoldersChangedListenerAsUser", getContext()); 640 if (userId != UserHandleCompat.USER_ALL && !UserUtils.isUserExistent(userId, 641 getContext())) { 642 Log.e(LOG_TAG, "user " + userId + " does not exist"); 643 return; 644 } 645 646 getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS, 647 "addOnRoleHoldersChangedListenerAsUser"); 648 649 Objects.requireNonNull(listener, "listener cannot be null"); 650 651 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getOrCreateListeners( 652 userId); 653 listeners.register(listener); 654 } 655 656 @Override removeOnRoleHoldersChangedListenerAsUser( @onNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId)657 public void removeOnRoleHoldersChangedListenerAsUser( 658 @NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) { 659 UserUtils.enforceCrossUserPermission(userId, true, 660 "removeOnRoleHoldersChangedListenerAsUser", getContext()); 661 if (userId != UserHandleCompat.USER_ALL && !UserUtils.isUserExistent(userId, 662 getContext())) { 663 Log.e(LOG_TAG, "user " + userId + " does not exist"); 664 return; 665 } 666 667 getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS, 668 "removeOnRoleHoldersChangedListenerAsUser"); 669 670 Objects.requireNonNull(listener, "listener cannot be null"); 671 672 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId); 673 if (listener == null) { 674 return; 675 } 676 listeners.unregister(listener); 677 } 678 679 @Override isBypassingRoleQualification()680 public boolean isBypassingRoleQualification() { 681 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, 682 "isBypassingRoleQualification"); 683 684 synchronized (mLock) { 685 return mBypassingRoleQualification; 686 } 687 } 688 689 @Override setBypassingRoleQualification(boolean bypassRoleQualification)690 public void setBypassingRoleQualification(boolean bypassRoleQualification) { 691 getContext().enforceCallingOrSelfPermission( 692 Manifest.permission.BYPASS_ROLE_QUALIFICATION, "setBypassingRoleQualification"); 693 694 synchronized (mLock) { 695 if (mBypassingRoleQualification == bypassRoleQualification) { 696 return; 697 } 698 mBypassingRoleQualification = bypassRoleQualification; 699 700 final int userStatesSize = mUserStates.size(); 701 for (int i = 0; i < userStatesSize; i++) { 702 final RoleUserState userState = mUserStates.valueAt(i); 703 704 userState.setBypassingRoleQualification(bypassRoleQualification); 705 } 706 } 707 } 708 709 @Override isRoleFallbackEnabledAsUser(@onNull String roleName, @UserIdInt int userId)710 public boolean isRoleFallbackEnabledAsUser(@NonNull String roleName, 711 @UserIdInt int userId) { 712 UserUtils.enforceCrossUserPermission(userId, false, "isRoleFallbackEnabledAsUser", 713 getContext()); 714 if (!UserUtils.isUserExistent(userId, getContext())) { 715 Log.e(LOG_TAG, "user " + userId + " does not exist"); 716 return false; 717 } 718 719 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, 720 "isRoleFallbackEnabledAsUser"); 721 722 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 723 724 return getOrCreateUserState(userId).isFallbackEnabled(roleName); 725 } 726 727 @Override setRoleFallbackEnabledAsUser(@onNull String roleName, boolean fallbackEnabled, @UserIdInt int userId)728 public void setRoleFallbackEnabledAsUser(@NonNull String roleName, boolean fallbackEnabled, 729 @UserIdInt int userId) { 730 UserUtils.enforceCrossUserPermission(userId, false, "setRoleFallbackEnabledAsUser", 731 getContext()); 732 if (!UserUtils.isUserExistent(userId, getContext())) { 733 Log.e(LOG_TAG, "user " + userId + " does not exist"); 734 return; 735 } 736 737 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, 738 "setRoleFallbackEnabledAsUser"); 739 740 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 741 742 getOrCreateUserState(userId).setFallbackEnabled(roleName, fallbackEnabled); 743 } 744 745 @Override setRoleNamesFromControllerAsUser(@onNull List<String> roleNames, @UserIdInt int userId)746 public void setRoleNamesFromControllerAsUser(@NonNull List<String> roleNames, 747 @UserIdInt int userId) { 748 UserUtils.enforceCrossUserPermission(userId, false, "setRoleNamesFromControllerAsUser", 749 getContext()); 750 if (!UserUtils.isUserExistent(userId, getContext())) { 751 Log.e(LOG_TAG, "user " + userId + " does not exist"); 752 return; 753 } 754 755 getContext().enforceCallingOrSelfPermission( 756 RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER, 757 "setRoleNamesFromControllerAsUser"); 758 759 Objects.requireNonNull(roleNames, "roleNames cannot be null"); 760 761 getOrCreateUserState(userId).setRoleNames(roleNames); 762 } 763 764 @Override addRoleHolderFromControllerAsUser(@onNull String roleName, @NonNull String packageName, @UserIdInt int userId)765 public boolean addRoleHolderFromControllerAsUser(@NonNull String roleName, 766 @NonNull String packageName, @UserIdInt int userId) { 767 UserUtils.enforceCrossUserPermission(userId, false, 768 "addRoleHolderFromControllerAsUser", getContext()); 769 if (!UserUtils.isUserExistent(userId, getContext())) { 770 Log.e(LOG_TAG, "user " + userId + " does not exist"); 771 return false; 772 } 773 774 getContext().enforceCallingOrSelfPermission( 775 RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER, 776 "addRoleHolderFromControllerAsUser"); 777 778 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 779 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 780 781 return getOrCreateUserState(userId).addRoleHolder(roleName, packageName); 782 } 783 784 @Override removeRoleHolderFromControllerAsUser(@onNull String roleName, @NonNull String packageName, @UserIdInt int userId)785 public boolean removeRoleHolderFromControllerAsUser(@NonNull String roleName, 786 @NonNull String packageName, @UserIdInt int userId) { 787 UserUtils.enforceCrossUserPermission(userId, false, 788 "removeRoleHolderFromControllerAsUser", getContext()); 789 if (!UserUtils.isUserExistent(userId, getContext())) { 790 Log.e(LOG_TAG, "user " + userId + " does not exist"); 791 return false; 792 } 793 794 getContext().enforceCallingOrSelfPermission( 795 RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER, 796 "removeRoleHolderFromControllerAsUser"); 797 798 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 799 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 800 801 return getOrCreateUserState(userId).removeRoleHolder(roleName, packageName); 802 } 803 804 @Override getHeldRolesFromControllerAsUser(@onNull String packageName, @UserIdInt int userId)805 public List<String> getHeldRolesFromControllerAsUser(@NonNull String packageName, 806 @UserIdInt int userId) { 807 UserUtils.enforceCrossUserPermission(userId, false, 808 "getHeldRolesFromControllerAsUser", getContext()); 809 if (!UserUtils.isUserExistent(userId, getContext())) { 810 Log.e(LOG_TAG, "user " + userId + " does not exist"); 811 return Collections.emptyList(); 812 } 813 814 getContext().enforceCallingOrSelfPermission( 815 RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER, 816 "getHeldRolesFromControllerAsUser"); 817 818 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 819 820 return getOrCreateUserState(userId).getHeldRoles(packageName); 821 } 822 823 @Override handleShellCommand(@onNull ParcelFileDescriptor in, @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, @NonNull String[] args)824 public int handleShellCommand(@NonNull ParcelFileDescriptor in, 825 @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, 826 @NonNull String[] args) { 827 return new RoleShellCommand(this).exec(this, in.getFileDescriptor(), 828 out.getFileDescriptor(), err.getFileDescriptor(), args); 829 } 830 831 @Nullable 832 @Override getBrowserRoleHolder(@serIdInt int userId)833 public String getBrowserRoleHolder(@UserIdInt int userId) { 834 final int callingUid = Binder.getCallingUid(); 835 if (UserHandleCompat.getUserId(callingUid) != userId) { 836 getContext().enforceCallingOrSelfPermission( 837 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); 838 } 839 if (isInstantApp(callingUid)) { 840 return null; 841 } 842 843 final long identity = Binder.clearCallingIdentity(); 844 try { 845 return CollectionUtils.firstOrNull(getRoleHoldersAsUser(RoleManager.ROLE_BROWSER, 846 userId)); 847 } finally { 848 Binder.restoreCallingIdentity(identity); 849 } 850 } 851 isInstantApp(int uid)852 private boolean isInstantApp(int uid) { 853 final long identity = Binder.clearCallingIdentity(); 854 try { 855 final UserHandle user = UserHandle.getUserHandleForUid(uid); 856 final Context userContext = getContext().createContextAsUser(user, 0); 857 final PackageManager userPackageManager = userContext.getPackageManager(); 858 // Instant apps can not have shared UID, so it's safe to check only the first 859 // package name here. 860 final String packageName = ArrayUtils.firstOrNull( 861 userPackageManager.getPackagesForUid(uid)); 862 if (packageName == null) { 863 return false; 864 } 865 return userPackageManager.isInstantApp(packageName); 866 } finally { 867 Binder.restoreCallingIdentity(identity); 868 } 869 } 870 871 @Override setBrowserRoleHolder(@ullable String packageName, @UserIdInt int userId)872 public boolean setBrowserRoleHolder(@Nullable String packageName, @UserIdInt int userId) { 873 final Context context = getContext(); 874 context.enforceCallingOrSelfPermission( 875 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); 876 if (UserHandleCompat.getUserId(Binder.getCallingUid()) != userId) { 877 context.enforceCallingOrSelfPermission( 878 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); 879 } 880 881 if (!UserUtils.isUserExistent(userId, context)) { 882 return false; 883 } 884 885 final AndroidFuture<Void> future = new AndroidFuture<>(); 886 final RemoteCallback callback = new RemoteCallback(result -> { 887 boolean successful = result != null; 888 if (successful) { 889 future.complete(null); 890 } else { 891 future.completeExceptionally(new RuntimeException()); 892 } 893 }); 894 final long identity = Binder.clearCallingIdentity(); 895 try { 896 if (packageName != null) { 897 addRoleHolderAsUser(RoleManager.ROLE_BROWSER, packageName, 0, userId, callback); 898 } else { 899 clearRoleHoldersAsUser(RoleManager.ROLE_BROWSER, 0, userId, callback); 900 } 901 try { 902 future.get(5, TimeUnit.SECONDS); 903 } catch (InterruptedException | ExecutionException | TimeoutException e) { 904 Log.e(LOG_TAG, "Exception while setting default browser: " + packageName, e); 905 return false; 906 } 907 } finally { 908 Binder.restoreCallingIdentity(identity); 909 } 910 911 return true; 912 } 913 914 @Override getSmsRoleHolder(int userId)915 public String getSmsRoleHolder(int userId) { 916 final Context context = getContext(); 917 UserUtils.enforceCrossUserPermission(userId, false, "getSmsRoleHolder", context); 918 if (!UserUtils.isUserExistent(userId, getContext())) { 919 Log.e(LOG_TAG, "user " + userId + " does not exist"); 920 return null; 921 } 922 923 final String packageName; 924 final long identity = Binder.clearCallingIdentity(); 925 try { 926 packageName = CollectionUtils.firstOrNull(getRoleHoldersAsUser(RoleManager.ROLE_SMS, 927 userId)); 928 } finally { 929 Binder.restoreCallingIdentity(identity); 930 } 931 if (packageName != null && !PackageUtils.canCallingOrSelfPackageQuery(packageName, 932 userId, context)) { 933 return null; 934 } 935 return packageName; 936 } 937 938 @Override getEmergencyRoleHolder(int userId)939 public String getEmergencyRoleHolder(int userId) { 940 final Context context = getContext(); 941 UserUtils.enforceCrossUserPermission(userId, false, "getEmergencyRoleHolder", context); 942 if (!UserUtils.isUserExistent(userId, getContext())) { 943 Log.e(LOG_TAG, "user " + userId + " does not exist"); 944 return null; 945 } 946 947 getContext().enforceCallingOrSelfPermission( 948 Manifest.permission.READ_PRIVILEGED_PHONE_STATE, "getEmergencyRoleHolder"); 949 950 final String packageName; 951 final long identity = Binder.clearCallingIdentity(); 952 try { 953 packageName = CollectionUtils.firstOrNull(getRoleHoldersAsUser( 954 RoleManager.ROLE_EMERGENCY, userId)); 955 } finally { 956 Binder.restoreCallingIdentity(identity); 957 } 958 if (packageName != null && !PackageUtils.canCallingOrSelfPackageQuery(packageName, 959 userId, context)) { 960 return null; 961 } 962 return packageName; 963 } 964 965 @Override isRoleVisibleAsUser(@onNull String roleName, @UserIdInt int userId)966 public boolean isRoleVisibleAsUser(@NonNull String roleName, @UserIdInt int userId) { 967 UserUtils.enforceCrossUserPermission(userId, false, "isRoleVisibleAsUser", 968 getContext()); 969 if (!UserUtils.isUserExistent(userId, getContext())) { 970 Log.e(LOG_TAG, "user " + userId + " does not exist"); 971 return false; 972 } 973 974 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, 975 "isRoleVisibleAsUser"); 976 977 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 978 979 return getOrCreateController(userId).isRoleVisible(roleName); 980 } 981 982 @Override isApplicationVisibleForRoleAsUser(@onNull String roleName, @NonNull String packageName, @UserIdInt int userId)983 public boolean isApplicationVisibleForRoleAsUser(@NonNull String roleName, 984 @NonNull String packageName, @UserIdInt int userId) { 985 UserUtils.enforceCrossUserPermission(userId, false, 986 "isApplicationVisibleForRoleAsUser", getContext()); 987 if (!UserUtils.isUserExistent(userId, getContext())) { 988 Log.e(LOG_TAG, "user " + userId + " does not exist"); 989 return false; 990 } 991 992 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, 993 "isApplicationVisibleForRoleAsUser"); 994 995 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 996 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 997 998 return getOrCreateController(userId).isApplicationVisibleForRole(roleName, packageName); 999 } 1000 1001 @Override dump(@onNull FileDescriptor fd, @NonNull PrintWriter fout, @Nullable String[] args)1002 protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout, 1003 @Nullable String[] args) { 1004 if (!checkDumpPermission("role", fout)) { 1005 return; 1006 } 1007 1008 boolean dumpAsProto = args != null && ArrayUtils.contains(args, "--proto"); 1009 DualDumpOutputStream dumpOutputStream; 1010 if (dumpAsProto) { 1011 dumpOutputStream = new DualDumpOutputStream(new ProtoOutputStream( 1012 new FileOutputStream(fd))); 1013 } else { 1014 fout.println("ROLE STATE (dumpsys role):"); 1015 dumpOutputStream = new DualDumpOutputStream(new IndentingPrintWriter(fout, " ")); 1016 } 1017 1018 synchronized (mLock) { 1019 final int userStatesSize = mUserStates.size(); 1020 for (int i = 0; i < userStatesSize; i++) { 1021 final RoleUserState userState = mUserStates.valueAt(i); 1022 1023 userState.dump(dumpOutputStream, "user_states", 1024 RoleServiceDumpProto.USER_STATES); 1025 } 1026 } 1027 1028 dumpOutputStream.flush(); 1029 } 1030 checkDumpPermission(@onNull String serviceName, @NonNull PrintWriter writer)1031 private boolean checkDumpPermission(@NonNull String serviceName, 1032 @NonNull PrintWriter writer) { 1033 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1034 != PackageManager.PERMISSION_GRANTED) { 1035 writer.println("Permission Denial: can't dump " + serviceName + " from from pid=" 1036 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 1037 + " due to missing " + android.Manifest.permission.DUMP + " permission"); 1038 return false; 1039 } else { 1040 return true; 1041 } 1042 } 1043 } 1044 1045 private class Local implements RoleManagerLocal { 1046 @NonNull 1047 @Override getRolesAndHolders(@serIdInt int userId)1048 public Map<String, Set<String>> getRolesAndHolders(@UserIdInt int userId) { 1049 // Convert ArrayMap<String, ArraySet<String>> to Map<String, Set<String>> for the API. 1050 //noinspection unchecked 1051 return (Map<String, Set<String>>) (Map<String, ?>) 1052 getOrCreateUserState(userId).getRolesAndHolders(); 1053 } 1054 } 1055 } 1056