• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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