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 android.app.role; 18 19 import android.Manifest; 20 import android.annotation.CallbackExecutor; 21 import android.annotation.FlaggedApi; 22 import android.annotation.IntDef; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.RequiresPermission; 26 import android.annotation.SuppressLint; 27 import android.annotation.SystemApi; 28 import android.annotation.SystemService; 29 import android.annotation.UserHandleAware; 30 import android.annotation.UserIdInt; 31 import android.app.compat.CompatChanges; 32 import android.compat.annotation.ChangeId; 33 import android.compat.annotation.EnabledSince; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.os.Binder; 37 import android.os.Build; 38 import android.os.Process; 39 import android.os.RemoteCallback; 40 import android.os.RemoteException; 41 import android.os.UserHandle; 42 import android.permission.flags.Flags; 43 import android.permission.internal.compat.UserHandleCompat; 44 import android.util.ArrayMap; 45 import android.util.SparseArray; 46 47 import androidx.annotation.RequiresApi; 48 49 import com.android.internal.annotations.GuardedBy; 50 import com.android.internal.util.Preconditions; 51 import com.android.modules.utils.build.SdkLevel; 52 53 import java.lang.annotation.Retention; 54 import java.lang.annotation.RetentionPolicy; 55 import java.util.List; 56 import java.util.Objects; 57 import java.util.concurrent.Executor; 58 import java.util.function.Consumer; 59 60 /** 61 * This class provides information about and manages roles. 62 * <p> 63 * A role is a unique name within the system associated with certain privileges. The list of 64 * available roles might change with a system app update, so apps should not make assumption about 65 * the availability of roles. Instead, they should always query if the role is available using 66 * {@link #isRoleAvailable(String)} before trying to do anything with it. Some predefined role names 67 * are available as constants in this class, and a list of possibly available roles can be found in 68 * the <a href="{@docRoot}reference/androidx/core/role/package-summary.html">AndroidX Role 69 * library</a>. 70 * <p> 71 * There can be multiple applications qualifying for a role, but only a subset of them can become 72 * role holders. To qualify for a role, an application must meet certain requirements, including 73 * defining certain components in its manifest. These requirements can be found in the AndroidX 74 * Libraries. Then the application will need user consent to become a role holder, which can be 75 * requested using {@link android.app.Activity#startActivityForResult(Intent, int)} with the 76 * {@code Intent} obtained from {@link #createRequestRoleIntent(String)}. 77 * <p> 78 * Upon becoming a role holder, the application may be granted certain privileges that are role 79 * specific. When the application loses its role, these privileges will also be revoked. 80 */ 81 @SystemService(Context.ROLE_SERVICE) 82 public final class RoleManager { 83 /** 84 * The name of the assistant app role. 85 * 86 * @see android.service.voice.VoiceInteractionService 87 */ 88 public static final String ROLE_ASSISTANT = "android.app.role.ASSISTANT"; 89 90 /** 91 * The name of the browser role. 92 * 93 * @see Intent#CATEGORY_APP_BROWSER 94 */ 95 public static final String ROLE_BROWSER = "android.app.role.BROWSER"; 96 97 /** 98 * The name of the dialer role. 99 * 100 * @see Intent#ACTION_DIAL 101 * @see android.telecom.InCallService 102 */ 103 public static final String ROLE_DIALER = "android.app.role.DIALER"; 104 105 /** 106 * The name of the SMS role. 107 * 108 * @see Intent#CATEGORY_APP_MESSAGING 109 */ 110 public static final String ROLE_SMS = "android.app.role.SMS"; 111 112 /** 113 * The name of the emergency role 114 */ 115 public static final String ROLE_EMERGENCY = "android.app.role.EMERGENCY"; 116 117 /** 118 * The name of the home role. 119 * 120 * @see Intent#CATEGORY_HOME 121 */ 122 public static final String ROLE_HOME = "android.app.role.HOME"; 123 124 /** 125 * The name of the call redirection role. 126 * <p> 127 * A call redirection app provides a means to re-write the phone number for an outgoing call to 128 * place the call through a call redirection service. 129 * 130 * @see android.telecom.CallRedirectionService 131 */ 132 public static final String ROLE_CALL_REDIRECTION = "android.app.role.CALL_REDIRECTION"; 133 134 /** 135 * The name of the call screening and caller id role. 136 * 137 * @see android.telecom.CallScreeningService 138 */ 139 public static final String ROLE_CALL_SCREENING = "android.app.role.CALL_SCREENING"; 140 141 /** 142 * The name of the notes role. 143 * 144 * @see Intent#ACTION_CREATE_NOTE 145 * @see Intent#EXTRA_USE_STYLUS_MODE 146 */ 147 public static final String ROLE_NOTES = "android.app.role.NOTES"; 148 149 /** 150 * The name of the Wallet role. 151 * 152 * @see android.nfc.cardemulation.CardEmulation 153 */ 154 @FlaggedApi(Flags.FLAG_WALLET_ROLE_ENABLED) 155 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 156 public static final String ROLE_WALLET = "android.app.role.WALLET"; 157 158 /** 159 * The name of the system wellbeing role. 160 * 161 * @hide 162 */ 163 @SystemApi 164 public static final String ROLE_SYSTEM_WELLBEING = "android.app.role.SYSTEM_WELLBEING"; 165 166 /** 167 * The name of the system supervision role. 168 * 169 * @hide 170 */ 171 @SystemApi 172 public static final String ROLE_SYSTEM_SUPERVISION = "android.app.role.SYSTEM_SUPERVISION"; 173 174 /** 175 * The name of the system activity recognizer role. 176 * 177 * @hide 178 */ 179 @SystemApi 180 public static final String ROLE_SYSTEM_ACTIVITY_RECOGNIZER = 181 "android.app.role.SYSTEM_ACTIVITY_RECOGNIZER"; 182 183 /** 184 * The name of the device policy management role. 185 * 186 * @hide 187 */ 188 @SystemApi 189 public static final String ROLE_DEVICE_POLICY_MANAGEMENT = 190 "android.app.role.DEVICE_POLICY_MANAGEMENT"; 191 192 /** 193 * The name of the financed device kiosk role. 194 * 195 * A financed device is a device purchased through a creditor and typically paid back under an 196 * installment plan. 197 * The creditor has the ability to lock a financed device in case of payment default. 198 * 199 * @hide 200 */ 201 @SystemApi 202 public static final String ROLE_FINANCED_DEVICE_KIOSK = 203 "android.app.role.FINANCED_DEVICE_KIOSK"; 204 205 /** 206 * The name of the system call streaming role. 207 * 208 * @hide 209 */ 210 @SystemApi 211 public static final String ROLE_SYSTEM_CALL_STREAMING = 212 "android.app.role.SYSTEM_CALL_STREAMING"; 213 214 /** 215 * The name of the role used for testing cross-user roles. 216 * 217 * @hide 218 */ 219 @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 220 @SystemApi 221 public static final String ROLE_RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY = 222 "android.app.role.RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY"; 223 224 /** 225 * @hide 226 */ 227 @IntDef(flag = true, value = { MANAGE_HOLDERS_FLAG_DONT_KILL_APP }) 228 @Retention(RetentionPolicy.SOURCE) 229 public @interface ManageHoldersFlags {} 230 231 /** 232 * Flag parameter for {@link #addRoleHolderAsUser}, {@link #removeRoleHolderAsUser} and 233 * {@link #clearRoleHoldersAsUser} to indicate that apps should not be killed when changing 234 * their role holder status. 235 * 236 * @hide 237 */ 238 @SystemApi 239 public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; 240 241 /** 242 * For apps targeting Android V and above, several methods are now user-handle-aware, which 243 * means they use the user contained within the context. For apps targeting an SDK version 244 * <em>below</em> this, the user of the calling process will be used. 245 * 246 * @hide 247 */ 248 @ChangeId 249 @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) 250 public static final long ROLE_MANAGER_USER_HANDLE_AWARE = 303742236L; 251 252 /** 253 * The action used to request user approval of a role for an application. 254 * 255 * @hide 256 */ 257 public static final String ACTION_REQUEST_ROLE = "android.app.role.action.REQUEST_ROLE"; 258 259 /** 260 * The permission required to manage records of role holders in {@link RoleManager} directly. 261 * 262 * @hide 263 */ 264 public static final String PERMISSION_MANAGE_ROLES_FROM_CONTROLLER = 265 "com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER"; 266 267 /** 268 * The name of the system dependency installer role. 269 * 270 * A dependency installer installs missing SDK or static shared library dependencies that an app 271 * requires to be installed. 272 * 273 * @hide 274 */ 275 @FlaggedApi("android.content.pm.sdk_dependency_installer") 276 @SystemApi 277 public static final String ROLE_SYSTEM_DEPENDENCY_INSTALLER = 278 "android.app.role.SYSTEM_DEPENDENCY_INSTALLER"; 279 280 @NonNull 281 private final Context mContext; 282 283 @NonNull 284 private final IRoleManager mService; 285 286 @GuardedBy("mListenersLock") 287 @NonNull 288 private final SparseArray<ArrayMap<OnRoleHoldersChangedListener, 289 OnRoleHoldersChangedListenerDelegate>> mListeners = new SparseArray<>(); 290 @NonNull 291 private final Object mListenersLock = new Object(); 292 293 @GuardedBy("mRoleControllerManagerLock") 294 @Nullable 295 private RoleControllerManager mRoleControllerManager; 296 private final Object mRoleControllerManagerLock = new Object(); 297 298 /** 299 * Create a new instance of this class. 300 * 301 * @param context the {@link Context} 302 * @param service the {@link IRoleManager} service 303 * 304 * @hide 305 */ RoleManager(@onNull Context context, @NonNull IRoleManager service)306 public RoleManager(@NonNull Context context, @NonNull IRoleManager service) { 307 mContext = context; 308 mService = service; 309 } 310 311 /** 312 * Returns an {@code Intent} suitable for passing to 313 * {@link android.app.Activity#startActivityForResult(Intent, int)} which prompts the user to 314 * grant a role to this application. 315 * <p> 316 * If the role is granted, the {@code resultCode} will be 317 * {@link android.app.Activity#RESULT_OK}, otherwise it will be 318 * {@link android.app.Activity#RESULT_CANCELED}. 319 * 320 * @param roleName the name of requested role 321 * 322 * @return the {@code Intent} to prompt user to grant the role 323 */ 324 @NonNull createRequestRoleIntent(@onNull String roleName)325 public Intent createRequestRoleIntent(@NonNull String roleName) { 326 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 327 Intent intent = new Intent(ACTION_REQUEST_ROLE); 328 intent.setPackage(mContext.getPackageManager().getPermissionControllerPackageName()); 329 intent.putExtra(Intent.EXTRA_ROLE_NAME, roleName); 330 return intent; 331 } 332 333 /** 334 * Check whether a role is available in the system. 335 * 336 * @param roleName the name of role to checking for 337 * 338 * @return whether the role is available in the system 339 */ 340 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) isRoleAvailable(@onNull String roleName)341 public boolean isRoleAvailable(@NonNull String roleName) { 342 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 343 UserHandle user = getContextUserIfAppropriate(); 344 try { 345 return mService.isRoleAvailableAsUser(roleName, user.getIdentifier()); 346 } catch (RemoteException e) { 347 throw e.rethrowFromSystemServer(); 348 } 349 } 350 351 /** 352 * Check whether the calling application is holding a particular role. 353 * 354 * @param roleName the name of the role to check for 355 * 356 * @return whether the calling application is holding the role 357 */ 358 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) isRoleHeld(@onNull String roleName)359 public boolean isRoleHeld(@NonNull String roleName) { 360 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 361 UserHandle user = getContextUserIfAppropriate(); 362 try { 363 return mService.isRoleHeldAsUser(roleName, mContext.getPackageName(), 364 user.getIdentifier()); 365 } catch (RemoteException e) { 366 throw e.rethrowFromSystemServer(); 367 } 368 } 369 370 /** 371 * Get package names of the applications holding the role. 372 * <p> 373 * <strong>Note:</strong> Using this API requires holding 374 * {@code android.permission.MANAGE_ROLE_HOLDERS}. 375 * 376 * @param roleName the name of the role to get the role holder for 377 * 378 * @return a list of package names of the role holders, or an empty list if none. 379 * 380 * @see #getRoleHoldersAsUser(String, UserHandle) 381 * 382 * @hide 383 */ 384 @NonNull 385 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 386 @SystemApi 387 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) getRoleHolders(@onNull String roleName)388 public List<String> getRoleHolders(@NonNull String roleName) { 389 return getRoleHoldersAsUser(roleName, getContextUserIfAppropriate()); 390 } 391 392 /** 393 * Get package names of the applications holding the role. 394 * <p> 395 * <strong>Note:</strong> Using this API requires holding 396 * {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user 397 * {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 398 * 399 * @param roleName the name of the role to get the role holder for 400 * @param user the user to get the role holder for 401 * 402 * @return a list of package names of the role holders, or an empty list if none. 403 * 404 * @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer) 405 * @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer) 406 * @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, Consumer) 407 * 408 * @hide 409 */ 410 @NonNull 411 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 412 @SystemApi getRoleHoldersAsUser(@onNull String roleName, @NonNull UserHandle user)413 public List<String> getRoleHoldersAsUser(@NonNull String roleName, @NonNull UserHandle user) { 414 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 415 Objects.requireNonNull(user, "user cannot be null"); 416 try { 417 return mService.getRoleHoldersAsUser(roleName, user.getIdentifier()); 418 } catch (RemoteException e) { 419 throw e.rethrowFromSystemServer(); 420 } 421 } 422 423 /** 424 * Add a specific application to the holders of a role. If the role is exclusive, the previous 425 * holder will be replaced. 426 * <p> 427 * <strong>Note:</strong> Using this API requires holding 428 * {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user 429 * {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 430 * 431 * @param roleName the name of the role to add the role holder for 432 * @param packageName the package name of the application to add to the role holders 433 * @param flags optional behavior flags 434 * @param user the user to add the role holder for 435 * @param executor the {@code Executor} to run the callback on. 436 * @param callback the callback for whether this call is successful 437 * 438 * @see #getRoleHoldersAsUser(String, UserHandle) 439 * @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer) 440 * @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, Consumer) 441 * 442 * @hide 443 */ 444 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 445 @SystemApi addRoleHolderAsUser(@onNull String roleName, @NonNull String packageName, @ManageHoldersFlags int flags, @NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback)446 public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName, 447 @ManageHoldersFlags int flags, @NonNull UserHandle user, 448 @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) { 449 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 450 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 451 Objects.requireNonNull(user, "user cannot be null"); 452 Objects.requireNonNull(executor, "executor cannot be null"); 453 Objects.requireNonNull(callback, "callback cannot be null"); 454 try { 455 mService.addRoleHolderAsUser(roleName, packageName, flags, user.getIdentifier(), 456 createRemoteCallback(executor, callback)); 457 } catch (RemoteException e) { 458 throw e.rethrowFromSystemServer(); 459 } 460 } 461 462 /** 463 * Remove a specific application from the holders of a role. 464 * <p> 465 * <strong>Note:</strong> Using this API requires holding 466 * {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user 467 * {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 468 * 469 * @param roleName the name of the role to remove the role holder for 470 * @param packageName the package name of the application to remove from the role holders 471 * @param flags optional behavior flags 472 * @param user the user to remove the role holder for 473 * @param executor the {@code Executor} to run the callback on. 474 * @param callback the callback for whether this call is successful 475 * 476 * @see #getRoleHoldersAsUser(String, UserHandle) 477 * @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer) 478 * @see #clearRoleHoldersAsUser(String, int, UserHandle, Executor, Consumer) 479 * 480 * @hide 481 */ 482 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 483 @SystemApi removeRoleHolderAsUser(@onNull String roleName, @NonNull String packageName, @ManageHoldersFlags int flags, @NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback)484 public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName, 485 @ManageHoldersFlags int flags, @NonNull UserHandle user, 486 @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback) { 487 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 488 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 489 Objects.requireNonNull(user, "user cannot be null"); 490 Objects.requireNonNull(executor, "executor cannot be null"); 491 Objects.requireNonNull(callback, "callback cannot be null"); 492 try { 493 mService.removeRoleHolderAsUser(roleName, packageName, flags, user.getIdentifier(), 494 createRemoteCallback(executor, callback)); 495 } catch (RemoteException e) { 496 throw e.rethrowFromSystemServer(); 497 } 498 } 499 500 /** 501 * Remove all holders of a role. 502 * <p> 503 * <strong>Note:</strong> Using this API requires holding 504 * {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user 505 * {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 506 * 507 * @param roleName the name of the role to remove role holders for 508 * @param flags optional behavior flags 509 * @param user the user to remove role holders for 510 * @param executor the {@code Executor} to run the callback on. 511 * @param callback the callback for whether this call is successful 512 * 513 * @see #getRoleHoldersAsUser(String, UserHandle) 514 * @see #addRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer) 515 * @see #removeRoleHolderAsUser(String, String, int, UserHandle, Executor, Consumer) 516 * 517 * @hide 518 */ 519 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 520 @SystemApi clearRoleHoldersAsUser(@onNull String roleName, @ManageHoldersFlags int flags, @NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback)521 public void clearRoleHoldersAsUser(@NonNull String roleName, @ManageHoldersFlags int flags, 522 @NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor, 523 @NonNull Consumer<Boolean> callback) { 524 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 525 Objects.requireNonNull(user, "user cannot be null"); 526 Objects.requireNonNull(executor, "executor cannot be null"); 527 Objects.requireNonNull(callback, "callback cannot be null"); 528 try { 529 mService.clearRoleHoldersAsUser(roleName, flags, user.getIdentifier(), 530 createRemoteCallback(executor, callback)); 531 } catch (RemoteException e) { 532 throw e.rethrowFromSystemServer(); 533 } 534 } 535 536 /** 537 * Get package name of the application holding the role for a default application. 538 * <p> 539 * Only roles describing default applications can be used with this method. They can have 540 * at most one holder. 541 * 542 * @param roleName the name of the default application role to get 543 * 544 * @return a package name of the role holder or {@code null} if not set. 545 * 546 * @see #setDefaultApplication(String, String, int, Executor, Consumer) 547 * 548 * @hide 549 */ 550 @Nullable 551 @RequiresPermission(Manifest.permission.MANAGE_DEFAULT_APPLICATIONS) 552 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 553 @UserHandleAware 554 @SystemApi getDefaultApplication(@onNull String roleName)555 public String getDefaultApplication(@NonNull String roleName) { 556 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 557 try { 558 return mService.getDefaultApplicationAsUser( 559 roleName, mContext.getUser().getIdentifier()); 560 } catch (RemoteException e) { 561 throw e.rethrowFromSystemServer(); 562 } 563 } 564 565 /** 566 * Set a specific application as the default application. 567 * <p> 568 * Only roles describing default applications can be used with this method. They can have 569 * at most one holder. 570 * 571 * @param roleName the name of the default application role to set the role holder for 572 * @param packageName the package name of the application to set as the default application, 573 * or {@code null} to unset. 574 * @param flags optional behavior flags 575 * @param executor the {@code Executor} to run the callback on. 576 * @param callback the callback for whether this call is successful 577 * 578 * @see #getDefaultApplication(String) 579 * 580 * @hide 581 */ 582 @RequiresPermission(Manifest.permission.MANAGE_DEFAULT_APPLICATIONS) 583 @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 584 @UserHandleAware 585 @SystemApi setDefaultApplication(@onNull String roleName, @Nullable String packageName, @ManageHoldersFlags int flags, @CallbackExecutor @NonNull Executor executor, @NonNull Consumer<Boolean> callback)586 public void setDefaultApplication(@NonNull String roleName, @Nullable String packageName, 587 @ManageHoldersFlags int flags, @CallbackExecutor @NonNull Executor executor, 588 @NonNull Consumer<Boolean> callback) { 589 // Prior to Android V some devices might require the "packageName" to be non-null. 590 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 591 Objects.requireNonNull(executor, "executor cannot be null"); 592 Objects.requireNonNull(callback, "callback cannot be null"); 593 try { 594 mService.setDefaultApplicationAsUser(roleName, packageName, flags, 595 mContext.getUser().getIdentifier(), createRemoteCallback(executor, callback)); 596 } catch (RemoteException e) { 597 throw e.rethrowFromSystemServer(); 598 } 599 } 600 601 /** 602 * Get the {@link UserHandle} of the user who that is the active user for the specified role. 603 * <p> 604 * Only profile-group exclusive roles can be used with this method, and they will 605 * have one active user within a profile group. 606 * <p> 607 * <strong>Note:</strong> Using this API requires holding 608 * {@code android.permission.INTERACT_ACROSS_USERS_FULL} and one of 609 * {@code android.permission.MANAGE_ROLE_HOLDERS} or 610 * {@code android.permission.MANAGE_DEFAULT_APPLICATIONS}. 611 * 612 * @param roleName the name of the role to get the active user for 613 * 614 * @return a {@link UserHandle} of the active user for the specified role 615 * 616 * @see #setActiveUserForRole(String, UserHandle, int) 617 * 618 * @hide 619 */ 620 @RequiresPermission(allOf = {Manifest.permission.INTERACT_ACROSS_USERS_FULL, 621 Manifest.permission.MANAGE_ROLE_HOLDERS, 622 Manifest.permission.MANAGE_DEFAULT_APPLICATIONS}, 623 conditional = true) 624 @RequiresApi(Build.VERSION_CODES.BAKLAVA) 625 @SystemApi 626 @UserHandleAware 627 @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 628 @Nullable getActiveUserForRole(@onNull String roleName)629 public UserHandle getActiveUserForRole(@NonNull String roleName) { 630 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 631 try { 632 int userId = mService.getActiveUserForRoleAsUser(roleName, 633 mContext.getUser().getIdentifier()); 634 return userId == UserHandleCompat.USER_NULL ? null : UserHandle.of(userId); 635 } catch (RemoteException e) { 636 throw e.rethrowFromSystemServer(); 637 } 638 } 639 640 /** 641 * Set a specific user as active user for a role. 642 * <p> 643 * Only profile-group exclusive roles can be used with this method, and they will have 644 * one active user within a profile group. 645 * <p> 646 * <strong>Note:</strong> Using this API requires holding 647 * {@code android.permission.INTERACT_ACROSS_USERS_FULL} and one of 648 * {@code android.permission.MANAGE_ROLE_HOLDERS} or 649 * {@code android.permission.MANAGE_DEFAULT_APPLICATIONS}. 650 * 651 * @param roleName the name of the role to set the active user for 652 * @param user the user to set as active user for specified role 653 * @param flags optional behavior flags 654 * 655 * @see #getActiveUserForRole(String) 656 * 657 * @hide 658 */ 659 @RequiresPermission(allOf = {Manifest.permission.INTERACT_ACROSS_USERS_FULL, 660 Manifest.permission.MANAGE_ROLE_HOLDERS, 661 Manifest.permission.MANAGE_DEFAULT_APPLICATIONS}, 662 conditional = true) 663 @RequiresApi(Build.VERSION_CODES.BAKLAVA) 664 @SystemApi 665 @UserHandleAware 666 @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 667 // The user handle parameter is a value to be set by this method, while the context user of the 668 // operation is indeed read from the context 669 @SuppressLint("UserHandle") setActiveUserForRole( @onNull String roleName, @NonNull UserHandle user, @ManageHoldersFlags int flags)670 public void setActiveUserForRole( 671 @NonNull String roleName, @NonNull UserHandle user, @ManageHoldersFlags int flags) { 672 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 673 Objects.requireNonNull(user, "user cannot be null"); 674 try { 675 mService.setActiveUserForRoleAsUser(roleName, user.getIdentifier(), flags, 676 mContext.getUser().getIdentifier()); 677 } catch (RemoteException e) { 678 throw e.rethrowFromSystemServer(); 679 } 680 } 681 682 @NonNull createRemoteCallback(@onNull Executor executor, @NonNull Consumer<Boolean> callback)683 private static RemoteCallback createRemoteCallback(@NonNull Executor executor, 684 @NonNull Consumer<Boolean> callback) { 685 return new RemoteCallback(result -> executor.execute(() -> { 686 boolean successful = result != null; 687 final long token = Binder.clearCallingIdentity(); 688 try { 689 callback.accept(successful); 690 } finally { 691 Binder.restoreCallingIdentity(token); 692 } 693 })); 694 } 695 696 /** 697 * Add a listener to observe role holder changes 698 * <p> 699 * <strong>Note:</strong> Using this API requires holding 700 * {@code android.permission.OBSERVE_ROLE_HOLDERS} and if the user id is not the current user 701 * {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 702 * 703 * @param executor the {@code Executor} to call the listener on. 704 * @param listener the listener to be added 705 * @param user the user to add the listener for 706 * 707 * @see #removeOnRoleHoldersChangedListenerAsUser(OnRoleHoldersChangedListener, UserHandle) 708 * 709 * @hide 710 */ 711 @RequiresPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS) 712 @SuppressLint("SamShouldBeLast") // TODO(b/190240500): remove this 713 @SystemApi addOnRoleHoldersChangedListenerAsUser(@allbackExecutor @onNull Executor executor, @NonNull OnRoleHoldersChangedListener listener, @NonNull UserHandle user)714 public void addOnRoleHoldersChangedListenerAsUser(@CallbackExecutor @NonNull Executor executor, 715 @NonNull OnRoleHoldersChangedListener listener, @NonNull UserHandle user) { 716 Objects.requireNonNull(executor, "executor cannot be null"); 717 Objects.requireNonNull(listener, "listener cannot be null"); 718 Objects.requireNonNull(user, "user cannot be null"); 719 int userId = user.getIdentifier(); 720 synchronized (mListenersLock) { 721 ArrayMap<OnRoleHoldersChangedListener, OnRoleHoldersChangedListenerDelegate> listeners = 722 mListeners.get(userId); 723 if (listeners == null) { 724 listeners = new ArrayMap<>(); 725 mListeners.put(userId, listeners); 726 } else { 727 if (listeners.containsKey(listener)) { 728 return; 729 } 730 } 731 OnRoleHoldersChangedListenerDelegate listenerDelegate = 732 new OnRoleHoldersChangedListenerDelegate(executor, listener); 733 try { 734 mService.addOnRoleHoldersChangedListenerAsUser(listenerDelegate, userId); 735 } catch (RemoteException e) { 736 throw e.rethrowFromSystemServer(); 737 } 738 listeners.put(listener, listenerDelegate); 739 } 740 } 741 742 /** 743 * Remove a listener observing role holder changes 744 * <p> 745 * <strong>Note:</strong> Using this API requires holding 746 * {@code android.permission.OBSERVE_ROLE_HOLDERS} and if the user id is not the current user 747 * {@code android.permission.INTERACT_ACROSS_USERS_FULL}. 748 * 749 * @param listener the listener to be removed 750 * @param user the user to remove the listener for 751 * 752 * @see #addOnRoleHoldersChangedListenerAsUser(Executor, OnRoleHoldersChangedListener, 753 * UserHandle) 754 * 755 * @hide 756 */ 757 @RequiresPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS) 758 @SuppressLint("SamShouldBeLast") // TODO(b/190240500): remove this 759 @SystemApi removeOnRoleHoldersChangedListenerAsUser( @onNull OnRoleHoldersChangedListener listener, @NonNull UserHandle user)760 public void removeOnRoleHoldersChangedListenerAsUser( 761 @NonNull OnRoleHoldersChangedListener listener, @NonNull UserHandle user) { 762 Objects.requireNonNull(listener, "listener cannot be null"); 763 Objects.requireNonNull(user, "user cannot be null"); 764 int userId = user.getIdentifier(); 765 synchronized (mListenersLock) { 766 ArrayMap<OnRoleHoldersChangedListener, OnRoleHoldersChangedListenerDelegate> listeners = 767 mListeners.get(userId); 768 if (listeners == null) { 769 return; 770 } 771 OnRoleHoldersChangedListenerDelegate listenerDelegate = listeners.get(listener); 772 if (listenerDelegate == null) { 773 return; 774 } 775 try { 776 mService.removeOnRoleHoldersChangedListenerAsUser(listenerDelegate, 777 user.getIdentifier()); 778 } catch (RemoteException e) { 779 throw e.rethrowFromSystemServer(); 780 } 781 listeners.remove(listener); 782 if (listeners.isEmpty()) { 783 mListeners.remove(userId); 784 } 785 } 786 } 787 788 /** 789 * Check whether role qualifications should be bypassed. 790 * <p> 791 * Only the shell is allowed to do this, the qualification for the shell role itself cannot be 792 * bypassed, and each role needs to explicitly allow bypassing qualification in its definition. 793 * The bypass state will not be persisted across reboot. 794 * 795 * @return whether role qualification should be bypassed 796 * 797 * @hide 798 */ 799 @RequiresApi(Build.VERSION_CODES.S) 800 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 801 @SystemApi isBypassingRoleQualification()802 public boolean isBypassingRoleQualification() { 803 try { 804 return mService.isBypassingRoleQualification(); 805 } catch (RemoteException e) { 806 throw e.rethrowFromSystemServer(); 807 } 808 } 809 810 /** 811 * Set whether role qualifications should be bypassed. 812 * <p> 813 * Only the shell is allowed to do this, the qualification for the shell role itself cannot be 814 * bypassed, and each role needs to explicitly allow bypassing qualification in its definition. 815 * The bypass state will not be persisted across reboot. 816 * 817 * @param bypassRoleQualification whether role qualification should be bypassed 818 * 819 * @hide 820 */ 821 @RequiresApi(Build.VERSION_CODES.S) 822 @RequiresPermission(Manifest.permission.BYPASS_ROLE_QUALIFICATION) 823 @SystemApi setBypassingRoleQualification(boolean bypassRoleQualification)824 public void setBypassingRoleQualification(boolean bypassRoleQualification) { 825 try { 826 mService.setBypassingRoleQualification(bypassRoleQualification); 827 } catch (RemoteException e) { 828 throw e.rethrowFromSystemServer(); 829 } 830 } 831 832 /** 833 * Check whether role currently enables fallback to default holder. 834 * <p> 835 * This is based on the "None" holder being actively selected, in which case don't fallback. 836 * 837 * @param roleName the name of the role being queried 838 * 839 * @return whether fallback is enabled for the provided role 840 * 841 * @hide 842 */ 843 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 844 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 845 @FlaggedApi(Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED) 846 @UserHandleAware 847 @SystemApi isRoleFallbackEnabled(@onNull String roleName)848 public boolean isRoleFallbackEnabled(@NonNull String roleName) { 849 try { 850 return mService.isRoleFallbackEnabledAsUser(roleName, 851 mContext.getUser().getIdentifier()); 852 } catch (RemoteException e) { 853 throw e.rethrowFromSystemServer(); 854 } 855 } 856 857 /** 858 * Set whether role should fallback to a default role holder. 859 * 860 * @param roleName the name of the role being queried. 861 * @param fallbackEnabled whether to enable fallback holders for this role. 862 * 863 * @hide 864 */ 865 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 866 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 867 @FlaggedApi(Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED) 868 @UserHandleAware 869 @SystemApi setRoleFallbackEnabled(@onNull String roleName, boolean fallbackEnabled)870 public void setRoleFallbackEnabled(@NonNull String roleName, boolean fallbackEnabled) { 871 try { 872 mService.setRoleFallbackEnabledAsUser(roleName, fallbackEnabled, 873 mContext.getUser().getIdentifier()); 874 } catch (RemoteException e) { 875 throw e.rethrowFromSystemServer(); 876 } 877 } 878 879 /** 880 * Set the names of all the available roles. Should only be called from 881 * {@link android.app.role.RoleControllerService}. 882 * <p> 883 * <strong>Note:</strong> Using this API requires holding 884 * {@link #PERMISSION_MANAGE_ROLES_FROM_CONTROLLER}. 885 * 886 * @param roleNames the names of all the available roles 887 * 888 * @deprecated This is only usable by the role controller service, which is an internal 889 * implementation detail inside role. 890 * 891 * @hide 892 */ 893 @Deprecated 894 @RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER) 895 @SystemApi 896 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) setRoleNamesFromController(@onNull List<String> roleNames)897 public void setRoleNamesFromController(@NonNull List<String> roleNames) { 898 Objects.requireNonNull(roleNames, "roleNames cannot be null"); 899 UserHandle user = getContextUserIfAppropriate(); 900 try { 901 mService.setRoleNamesFromControllerAsUser(roleNames, user.getIdentifier()); 902 } catch (RemoteException e) { 903 throw e.rethrowFromSystemServer(); 904 } 905 } 906 907 /** 908 * Add a specific application to the holders of a role, only modifying records inside 909 * {@link RoleManager}. Should only be called from 910 * {@link android.app.role.RoleControllerService}. 911 * <p> 912 * <strong>Note:</strong> Using this API requires holding 913 * {@link #PERMISSION_MANAGE_ROLES_FROM_CONTROLLER}. 914 * 915 * @param roleName the name of the role to add the role holder for 916 * @param packageName the package name of the application to add to the role holders 917 * 918 * @return whether the operation was successful, and will also be {@code true} if a matching 919 * role holder is already found. 920 * 921 * @see #getRoleHolders(String) 922 * @see #removeRoleHolderFromController(String, String) 923 * 924 * @deprecated This is only usable by the role controller service, which is an internal 925 * implementation detail inside role. 926 * 927 * @hide 928 */ 929 @Deprecated 930 @RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER) 931 @SystemApi 932 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) addRoleHolderFromController(@onNull String roleName, @NonNull String packageName)933 public boolean addRoleHolderFromController(@NonNull String roleName, 934 @NonNull String packageName) { 935 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 936 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 937 UserHandle user = getContextUserIfAppropriate(); 938 try { 939 return mService.addRoleHolderFromControllerAsUser(roleName, packageName, 940 user.getIdentifier()); 941 } catch (RemoteException e) { 942 throw e.rethrowFromSystemServer(); 943 } 944 } 945 946 /** 947 * Remove a specific application from the holders of a role, only modifying records inside 948 * {@link RoleManager}. Should only be called from 949 * {@link android.app.role.RoleControllerService}. 950 * <p> 951 * <strong>Note:</strong> Using this API requires holding 952 * {@link #PERMISSION_MANAGE_ROLES_FROM_CONTROLLER}. 953 * 954 * @param roleName the name of the role to remove the role holder for 955 * @param packageName the package name of the application to remove from the role holders 956 * 957 * @return whether the operation was successful, and will also be {@code true} if no matching 958 * role holder was found to remove. 959 * 960 * @see #getRoleHolders(String) 961 * @see #addRoleHolderFromController(String, String) 962 * 963 * @deprecated This is only usable by the role controller service, which is an internal 964 * implementation detail inside role. 965 * 966 * @hide 967 */ 968 @Deprecated 969 @RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER) 970 @SystemApi 971 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) removeRoleHolderFromController(@onNull String roleName, @NonNull String packageName)972 public boolean removeRoleHolderFromController(@NonNull String roleName, 973 @NonNull String packageName) { 974 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 975 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 976 UserHandle user = getContextUserIfAppropriate(); 977 try { 978 return mService.removeRoleHolderFromControllerAsUser(roleName, packageName, 979 user.getIdentifier()); 980 } catch (RemoteException e) { 981 throw e.rethrowFromSystemServer(); 982 } 983 } 984 985 /** 986 * Returns the list of all roles that the given package is currently holding 987 * 988 * @param packageName the package name 989 * @return the list of role names 990 * 991 * @deprecated This is only usable by the role controller service, which is an internal 992 * implementation detail inside role. 993 * 994 * @hide 995 */ 996 @Deprecated 997 @NonNull 998 @RequiresPermission(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER) 999 @SystemApi 1000 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) getHeldRolesFromController(@onNull String packageName)1001 public List<String> getHeldRolesFromController(@NonNull String packageName) { 1002 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); 1003 UserHandle user = getContextUserIfAppropriate(); 1004 try { 1005 return mService.getHeldRolesFromControllerAsUser(packageName, user.getIdentifier()); 1006 } catch (RemoteException e) { 1007 throw e.rethrowFromSystemServer(); 1008 } 1009 } 1010 getContextUserIfAppropriate()1011 private UserHandle getContextUserIfAppropriate() { 1012 return CompatChanges.isChangeEnabled(ROLE_MANAGER_USER_HANDLE_AWARE) ? mContext.getUser() 1013 : Process.myUserHandle(); 1014 } 1015 1016 /** 1017 * Get the role holder of {@link #ROLE_BROWSER} without requiring 1018 * {@link Manifest.permission#OBSERVE_ROLE_HOLDERS}, as in 1019 * {@link android.content.pm.PackageManager#getDefaultBrowserPackageNameAsUser(int)} 1020 * 1021 * @param userId the user ID 1022 * @return the package name of the default browser, or {@code null} if none 1023 * 1024 * @hide 1025 */ 1026 @RequiresApi(Build.VERSION_CODES.S) 1027 @Nullable 1028 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) getBrowserRoleHolder(@serIdInt int userId)1029 public String getBrowserRoleHolder(@UserIdInt int userId) { 1030 try { 1031 return mService.getBrowserRoleHolder(userId); 1032 } catch (RemoteException e) { 1033 throw e.rethrowFromSystemServer(); 1034 } 1035 } 1036 1037 /** 1038 * Set the role holder of {@link #ROLE_BROWSER} requiring 1039 * {@link Manifest.permission.SET_PREFERRED_APPLICATIONS} instead of 1040 * {@link Manifest.permission#MANAGE_ROLE_HOLDERS}, as in 1041 * {@link android.content.pm.PackageManager#setDefaultBrowserPackageNameAsUser(String, int)} 1042 * 1043 * @param packageName the package name of the default browser, or {@code null} if none 1044 * @param userId the user ID 1045 * @return whether the default browser was set successfully 1046 * 1047 * @hide 1048 */ 1049 @RequiresApi(Build.VERSION_CODES.S) 1050 @Nullable 1051 @RequiresPermission(Manifest.permission.SET_PREFERRED_APPLICATIONS) 1052 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) setBrowserRoleHolder(@ullable String packageName, @UserIdInt int userId)1053 public boolean setBrowserRoleHolder(@Nullable String packageName, @UserIdInt int userId) { 1054 try { 1055 return mService.setBrowserRoleHolder(packageName, userId); 1056 } catch (RemoteException e) { 1057 throw e.rethrowFromSystemServer(); 1058 } 1059 } 1060 1061 /** 1062 * Allows getting the role holder for {@link #ROLE_SMS} without requiring 1063 * {@link Manifest.permission#OBSERVE_ROLE_HOLDERS}, as in 1064 * {@link android.provider.Telephony.Sms#getDefaultSmsPackage(Context)}. 1065 * 1066 * @param userId the user ID to get the default SMS package for 1067 * @return the package name of the default SMS app, or {@code null} if none 1068 * 1069 * @hide 1070 */ 1071 @RequiresApi(Build.VERSION_CODES.S) 1072 @Nullable 1073 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) getSmsRoleHolder(@serIdInt int userId)1074 public String getSmsRoleHolder(@UserIdInt int userId) { 1075 try { 1076 return mService.getSmsRoleHolder(userId); 1077 } catch (RemoteException e) { 1078 throw e.rethrowFromSystemServer(); 1079 } 1080 } 1081 1082 /** 1083 * Allows getting the role holder for {@link #ROLE_EMERGENCY} without requiring 1084 * {@link Manifest.permission#OBSERVE_ROLE_HOLDERS}. 1085 * 1086 * @param userId the user ID to get the default emergency package for 1087 * @return the package name of the default emergency app, or {@code null} if none 1088 * 1089 * @hide 1090 */ 1091 @FlaggedApi(Flags.FLAG_GET_EMERGENCY_ROLE_HOLDER_API_ENABLED) 1092 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) 1093 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) 1094 @Nullable 1095 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) getEmergencyRoleHolder(@serIdInt int userId)1096 public String getEmergencyRoleHolder(@UserIdInt int userId) { 1097 try { 1098 return mService.getEmergencyRoleHolder(userId); 1099 } catch (RemoteException e) { 1100 throw e.rethrowFromSystemServer(); 1101 } 1102 } 1103 1104 /** 1105 * Check whether a role should be visible to user. 1106 * 1107 * @param roleName name of the role to check for 1108 * @param executor the executor to execute callback on 1109 * @param callback the callback to receive whether the role should be visible to user 1110 * 1111 * @hide 1112 */ 1113 @RequiresApi(Build.VERSION_CODES.S) 1114 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 1115 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) 1116 @SystemApi isRoleVisible(@onNull String roleName, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback)1117 public void isRoleVisible(@NonNull String roleName, 1118 @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { 1119 if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) { 1120 int userId = getContextUserIfAppropriate().getIdentifier(); 1121 boolean visible; 1122 try { 1123 visible = mService.isRoleVisibleAsUser(roleName, userId); 1124 } catch (RemoteException e) { 1125 throw e.rethrowFromSystemServer(); 1126 } 1127 executor.execute(() -> { 1128 final long token = Binder.clearCallingIdentity(); 1129 try { 1130 callback.accept(visible); 1131 } finally { 1132 Binder.restoreCallingIdentity(token); 1133 } 1134 }); 1135 } else { 1136 getRoleControllerManager().isRoleVisible(roleName, executor, callback); 1137 } 1138 } 1139 1140 /** 1141 * Check whether an application is visible for a role. 1142 * 1143 * While an application can be qualified for a role, it can still stay hidden from user (thus 1144 * not visible). If an application is visible for a role, we may show things related to the role 1145 * for it, e.g. showing an entry pointing to the role settings in its application info page. 1146 * 1147 * @param roleName the name of the role to check for 1148 * @param packageName the package name of the application to check for 1149 * @param executor the executor to execute callback on 1150 * @param callback the callback to receive whether the application is visible for the role 1151 * 1152 * @hide 1153 */ 1154 @RequiresApi(Build.VERSION_CODES.S) 1155 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 1156 @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) 1157 @SystemApi isApplicationVisibleForRole(@onNull String roleName, @NonNull String packageName, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback)1158 public void isApplicationVisibleForRole(@NonNull String roleName, @NonNull String packageName, 1159 @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { 1160 if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) { 1161 int userId = getContextUserIfAppropriate().getIdentifier(); 1162 boolean visible; 1163 try { 1164 visible = mService.isApplicationVisibleForRoleAsUser(roleName, packageName, userId); 1165 } catch (RemoteException e) { 1166 throw e.rethrowFromSystemServer(); 1167 } 1168 executor.execute(() -> { 1169 final long token = Binder.clearCallingIdentity(); 1170 try { 1171 callback.accept(visible); 1172 } finally { 1173 Binder.restoreCallingIdentity(token); 1174 } 1175 }); 1176 } else { 1177 getRoleControllerManager().isApplicationVisibleForRole(roleName, packageName, executor, 1178 callback); 1179 } 1180 } 1181 1182 /** 1183 * Get the default holders of this role, which will be added when the role is added for the 1184 * first time. 1185 * <p> 1186 * <strong>Note:</strong> Use of this API should be limited to tests. The values returned are 1187 * not persisted. 1188 * <p> 1189 * Throws {@link IllegalArgumentException} if role is not a test role 1190 * 1191 * @param roleName the name of the role to get test default holders for 1192 * @return the list of package names of the default holders 1193 * 1194 * @hide 1195 */ 1196 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 1197 @RequiresApi(Build.VERSION_CODES.BAKLAVA) 1198 @SystemApi 1199 @UserHandleAware 1200 @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 1201 @NonNull getDefaultHoldersForTest(@onNull String roleName)1202 public List<String> getDefaultHoldersForTest(@NonNull String roleName) { 1203 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 1204 try { 1205 return mService.getDefaultHoldersForTestAsUser(roleName, 1206 mContext.getUser().getIdentifier()); 1207 } catch (RemoteException e) { 1208 throw e.rethrowFromSystemServer(); 1209 } 1210 } 1211 1212 /** 1213 * Set the default holders of this role, which will be added when the role is added for the 1214 * first time. 1215 * <p> 1216 * <strong>Note:</strong> Use of this API should be limited to tests. The values used are 1217 * not persisted. 1218 * <p> 1219 * Throws {@link IllegalArgumentException} if role is not a test role 1220 * Throws {@link NullPointerException} if packageNames is {@code null} 1221 * 1222 * @param roleName the name of the role to set test default holders for 1223 * @param packageNames a list of package names of the default holders, or an empty list to unset 1224 * 1225 * @hide 1226 */ 1227 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 1228 @RequiresApi(Build.VERSION_CODES.BAKLAVA) 1229 @SystemApi 1230 @UserHandleAware 1231 @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) setDefaultHoldersForTest( @onNull String roleName, @NonNull List<String> packageNames)1232 public void setDefaultHoldersForTest( 1233 @NonNull String roleName, @NonNull List<String> packageNames) { 1234 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 1235 Objects.requireNonNull(packageNames, "packageNames cannot be null"); 1236 try { 1237 mService.setDefaultHoldersForTestAsUser(roleName, packageNames, 1238 mContext.getUser().getIdentifier()); 1239 } catch (RemoteException e) { 1240 throw e.rethrowFromSystemServer(); 1241 } 1242 } 1243 1244 /** 1245 * Get whether a role should be visible for testing. 1246 * <p> 1247 * <strong>Note:</strong> Use of this API should be limited to tests. The values returned are 1248 * not persisted. 1249 * <p> 1250 * Throws {@link IllegalArgumentException} if role is not a test role 1251 * 1252 * @param roleName the name of the role to get test visibility for 1253 * @return {@code true} if role is visible, {@code false} otherwise 1254 * 1255 * @hide 1256 */ 1257 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 1258 @RequiresApi(Build.VERSION_CODES.BAKLAVA) 1259 @SystemApi 1260 @UserHandleAware 1261 @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) isRoleVisibleForTest(@onNull String roleName)1262 public boolean isRoleVisibleForTest(@NonNull String roleName) { 1263 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 1264 try { 1265 return mService.isRoleVisibleForTestAsUser(roleName, 1266 mContext.getUser().getIdentifier()); 1267 } catch (RemoteException e) { 1268 throw e.rethrowFromSystemServer(); 1269 } 1270 } 1271 1272 /** 1273 * Set whether a role should be visible for testing. 1274 * <p> 1275 * <strong>Note:</strong> Use of this API should be limited to tests. The values used are 1276 * not persisted. 1277 * <p> 1278 * Throws {@link IllegalArgumentException} if role is not a test role 1279 * 1280 * @param roleName the name of the role to set test visibility for 1281 * @param visible {@code true} to set role as visible, {@code false} otherwise 1282 * 1283 * @hide 1284 */ 1285 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) 1286 @RequiresApi(Build.VERSION_CODES.BAKLAVA) 1287 @SystemApi 1288 @UserHandleAware 1289 @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) setRoleVisibleForTest(@onNull String roleName, boolean visible)1290 public void setRoleVisibleForTest(@NonNull String roleName, boolean visible) { 1291 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 1292 try { 1293 mService.setRoleVisibleForTestAsUser(roleName, visible, 1294 mContext.getUser().getIdentifier()); 1295 } catch (RemoteException e) { 1296 throw e.rethrowFromSystemServer(); 1297 } 1298 } 1299 1300 @NonNull getRoleControllerManager()1301 private RoleControllerManager getRoleControllerManager() { 1302 synchronized (mRoleControllerManagerLock) { 1303 if (mRoleControllerManager == null) { 1304 mRoleControllerManager = new RoleControllerManager(mContext); 1305 } 1306 return mRoleControllerManager; 1307 } 1308 } 1309 1310 private static class OnRoleHoldersChangedListenerDelegate 1311 extends IOnRoleHoldersChangedListener.Stub { 1312 1313 @NonNull 1314 private final Executor mExecutor; 1315 @NonNull 1316 private final OnRoleHoldersChangedListener mListener; 1317 OnRoleHoldersChangedListenerDelegate(@onNull Executor executor, @NonNull OnRoleHoldersChangedListener listener)1318 OnRoleHoldersChangedListenerDelegate(@NonNull Executor executor, 1319 @NonNull OnRoleHoldersChangedListener listener) { 1320 mExecutor = executor; 1321 mListener = listener; 1322 } 1323 1324 @Override onRoleHoldersChanged(@onNull String roleName, @UserIdInt int userId)1325 public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) { 1326 final long token = Binder.clearCallingIdentity(); 1327 try { 1328 mExecutor.execute(() -> 1329 mListener.onRoleHoldersChanged(roleName, UserHandle.of(userId))); 1330 } finally { 1331 Binder.restoreCallingIdentity(token); 1332 } 1333 } 1334 } 1335 } 1336