Loading api/system-current.txt +4 −1 Original line number Diff line number Diff line Loading @@ -810,9 +810,12 @@ package android.app.role { public final class RoleManager { method public void addRoleHolderAsUser(java.lang.String, java.lang.String, android.os.UserHandle, java.util.concurrent.Executor, android.app.role.RoleManagerCallback); method public boolean addRoleHolderFromController(java.lang.String, java.lang.String); method public void clearRoleHoldersAsUser(java.lang.String, android.os.UserHandle, java.util.concurrent.Executor, android.app.role.RoleManagerCallback); method public java.util.Set<java.lang.String> getRoleHoldersAsUser(java.lang.String, android.os.UserHandle); method public java.util.List<java.lang.String> getRoleHolders(java.lang.String); method public java.util.List<java.lang.String> getRoleHoldersAsUser(java.lang.String, android.os.UserHandle); method public void removeRoleHolderAsUser(java.lang.String, java.lang.String, android.os.UserHandle, java.util.concurrent.Executor, android.app.role.RoleManagerCallback); method public boolean removeRoleHolderFromController(java.lang.String, java.lang.String); field public static final java.lang.String EXTRA_REQUEST_ROLE_NAME = "android.app.role.extra.REQUEST_ROLE_NAME"; } Loading core/java/android/app/role/IRoleManager.aidl +4 −0 Original line number Diff line number Diff line Loading @@ -36,4 +36,8 @@ interface IRoleManager { in IRoleManagerCallback callback); void clearRoleHoldersAsUser(in String roleName, int userId, in IRoleManagerCallback callback); boolean addRoleHolderFromController(in String roleName, in String packageName); boolean removeRoleHolderFromController(in String roleName, in String packageName); } core/java/android/app/role/RoleManager.java +114 −18 Original line number Diff line number Diff line Loading @@ -22,19 +22,16 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.util.ArraySet; import com.android.internal.util.Preconditions; import java.util.List; import java.util.Set; import java.util.concurrent.Executor; /** Loading @@ -51,8 +48,8 @@ import java.util.concurrent.Executor; * role holders. To qualify for a role, an application must meet certain requirements, including * defining certain components in its manifest. These requirements can be found in the AndroidX * Libraries. Then the application will need user consent to become a role holder, which can be * requested using {@link Activity#startActivityForResult(Intent, int)} with the {@code Intent} * obtained from {@link #createRequestRoleIntent(String)}. * requested using {@link android.app.Activity#startActivityForResult(Intent, int)} with the * {@code Intent} obtained from {@link #createRequestRoleIntent(String)}. * <p> * Upon becoming a role holder, the application may be granted certain privileges that are role * specific. When the application loses its role, these privileges will also be revoked. Loading Loading @@ -89,6 +86,14 @@ public final class RoleManager { @SystemApi public static final String EXTRA_REQUEST_ROLE_NAME = "android.app.role.extra.REQUEST_ROLE_NAME"; /** * The permission required to manage records of role holders in {@link RoleManager} directly. * * @hide */ public static final String PERMISSION_MANAGE_ROLE_HOLDERS_FROM_CONTROLLER = "com.android.permissioncontroller.permission.MANAGE_ROLE_HOLDERS_FROM_CONTROLLER"; @NonNull private final Context mContext; Loading @@ -105,11 +110,13 @@ public final class RoleManager { } /** * Returns an {@code Intent} suitable for passing to {@link Activity#startActivityForResult( * Intent, int)} which prompts the user to grant a role to this application. * Returns an {@code Intent} suitable for passing to * {@link android.app.Activity#startActivityForResult(Intent, int)} which prompts the user to * grant a role to this application. * <p> * If the role is granted, the {@code resultCode} will be {@link Activity#RESULT_OK}, otherwise * it will be {@link Activity#RESULT_CANCELED}. * If the role is granted, the {@code resultCode} will be * {@link android.app.Activity#RESULT_OK}, otherwise it will be * {@link android.app.Activity#RESULT_CANCELED}. * * @param roleName the name of requested role * Loading Loading @@ -162,6 +169,29 @@ public final class RoleManager { } } /** * Get package names of the applications holding the role. * <p> * <strong>Note:</strong> Using this API requires holding * {@code android.permission.MANAGE_ROLE_HOLDERS}. * * @param roleName the name of the role to get the role holder for * * @return a list of package names of the role holders, or an empty list if none. * * @throws IllegalArgumentException if the role name is {@code null} or empty. * * @see #getRoleHoldersAsUser(String, UserHandle) * * @hide */ @NonNull @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) @SystemApi public List<String> getRoleHolders(@NonNull String roleName) { return getRoleHoldersAsUser(roleName, UserHandle.of(UserHandle.getCallingUserId())); } /** * Get package names of the applications holding the role. * <p> Loading @@ -172,7 +202,7 @@ public final class RoleManager { * @param roleName the name of the role to get the role holder for * @param user the user to get the role holder for * * @return the package name of the role holder, or {@code null} if none. * @return a list of package names of the role holders, or an empty list if none. * * @throws IllegalArgumentException if the role name is {@code null} or empty. * Loading @@ -185,16 +215,14 @@ public final class RoleManager { @NonNull @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) @SystemApi public Set<String> getRoleHoldersAsUser(@NonNull String roleName, @NonNull UserHandle user) { public List<String> getRoleHoldersAsUser(@NonNull String roleName, @NonNull UserHandle user) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkNotNull(user, "user cannot be null"); List<String> roleHolders; try { roleHolders = mService.getRoleHoldersAsUser(roleName, user.getIdentifier()); return mService.getRoleHoldersAsUser(roleName, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } return new ArraySet<>(roleHolders); } /** Loading Loading @@ -312,6 +340,74 @@ public final class RoleManager { } } /** * Add a specific application to the holders of a role, only modifying records inside * {@link RoleManager}. Should only be called from * {@link android.rolecontrollerservice.RoleControllerService}. * <p> * <strong>Note:</strong> Using this API requires holding * {@link #PERMISSION_MANAGE_ROLE_HOLDERS_FROM_CONTROLLER}. * * @param roleName the name of the role to add the role holder for * @param packageName the package name of the application to add to the role holders * * @return whether the operation was successful, and will also be {@code true} if a matching * role holder is already found. * * @throws IllegalArgumentException if the role name or package name is {@code null} or empty. * * @see #getRoleHolders(String) * @see #removeRoleHolderFromController(String, String) * * @hide */ @RequiresPermission(PERMISSION_MANAGE_ROLE_HOLDERS_FROM_CONTROLLER) @SystemApi public boolean addRoleHolderFromController(@NonNull String roleName, @NonNull String packageName) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); try { return mService.addRoleHolderFromController(roleName, packageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Remove a specific application from the holders of a role, only modifying records inside * {@link RoleManager}. Should only be called from * {@link android.rolecontrollerservice.RoleControllerService}. * <p> * <strong>Note:</strong> Using this API requires holding * {@link #PERMISSION_MANAGE_ROLE_HOLDERS_FROM_CONTROLLER}. * * @param roleName the name of the role to remove the role holder for * @param packageName the package name of the application to remove from the role holders * * @return whether the operation was successful, and will also be {@code true} if no matching * role holder was found to remove. * * @throws IllegalArgumentException if the role name or package name is {@code null} or empty. * * @see #getRoleHolders(String) * @see #addRoleHolderFromController(String, String) * * @hide */ @RequiresPermission(PERMISSION_MANAGE_ROLE_HOLDERS_FROM_CONTROLLER) @SystemApi public boolean removeRoleHolderFromController(@NonNull String roleName, @NonNull String packageName) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); try { return mService.removeRoleHolderFromController(roleName, packageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } private static class RoleManagerCallbackDelegate extends IRoleManagerCallback.Stub { @NonNull Loading services/core/java/com/android/server/role/RemoteRoleControllerService.java +7 −5 Original line number Diff line number Diff line Loading @@ -105,6 +105,9 @@ public class RemoteRoleControllerService { @NonNull private final Queue<Call> mPendingCalls = new ArrayDeque<>(); @NonNull private final Handler mMainHandler = Handler.getMain(); @NonNull private final Runnable mUnbindRunnable = this::unbind; Loading Loading @@ -142,7 +145,7 @@ public class RemoteRoleControllerService { } public void enqueueCall(@NonNull Call call) { Handler.getMain().post(PooledLambda.obtainRunnable(this::executeCall, call)); mMainHandler.post(PooledLambda.obtainRunnable(this::executeCall, call)); } @MainThread Loading @@ -158,7 +161,7 @@ public class RemoteRoleControllerService { @MainThread private void ensureBound() { Handler.getMain().removeCallbacks(mUnbindRunnable); mMainHandler.removeCallbacks(mUnbindRunnable); if (!mBound) { Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE); intent.setPackage(mContext.getPackageManager() Loading @@ -169,9 +172,8 @@ public class RemoteRoleControllerService { } private void scheduleUnbind() { Handler mainHandler = Handler.getMain(); mainHandler.removeCallbacks(mUnbindRunnable); mainHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS); mMainHandler.removeCallbacks(mUnbindRunnable); mMainHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS); } @MainThread Loading services/core/java/com/android/server/role/RoleManagerService.java +33 −0 Original line number Diff line number Diff line Loading @@ -249,9 +249,42 @@ public class RoleManagerService extends SystemService { userId = handleIncomingUser(userId, "clearRoleHoldersAsUser"); getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, "clearRoleHoldersAsUser"); getControllerService(userId).onClearRoleHolders(roleName, callback); } @Override public boolean addRoleHolderFromController(@NonNull String roleName, @NonNull String packageName) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); getContext().enforceCallingOrSelfPermission( RoleManager.PERMISSION_MANAGE_ROLE_HOLDERS_FROM_CONTROLLER, "addRoleHolderFromController"); int userId = UserHandle.getCallingUserId(); synchronized (mLock) { RoleUserState userState = getUserStateLocked(userId); return userState.addRoleHolderLocked(roleName, packageName); } } @Override public boolean removeRoleHolderFromController(@NonNull String roleName, @NonNull String packageName) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); getContext().enforceCallingOrSelfPermission( RoleManager.PERMISSION_MANAGE_ROLE_HOLDERS_FROM_CONTROLLER, "removeRoleHolderFromController"); int userId = UserHandle.getCallingUserId(); synchronized (mLock) { RoleUserState userState = getUserStateLocked(userId); return userState.removeRoleHolderLocked(roleName, packageName); } } @CheckResult private int handleIncomingUser(@UserIdInt int userId, @NonNull String name) { return ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId, Loading Loading
api/system-current.txt +4 −1 Original line number Diff line number Diff line Loading @@ -810,9 +810,12 @@ package android.app.role { public final class RoleManager { method public void addRoleHolderAsUser(java.lang.String, java.lang.String, android.os.UserHandle, java.util.concurrent.Executor, android.app.role.RoleManagerCallback); method public boolean addRoleHolderFromController(java.lang.String, java.lang.String); method public void clearRoleHoldersAsUser(java.lang.String, android.os.UserHandle, java.util.concurrent.Executor, android.app.role.RoleManagerCallback); method public java.util.Set<java.lang.String> getRoleHoldersAsUser(java.lang.String, android.os.UserHandle); method public java.util.List<java.lang.String> getRoleHolders(java.lang.String); method public java.util.List<java.lang.String> getRoleHoldersAsUser(java.lang.String, android.os.UserHandle); method public void removeRoleHolderAsUser(java.lang.String, java.lang.String, android.os.UserHandle, java.util.concurrent.Executor, android.app.role.RoleManagerCallback); method public boolean removeRoleHolderFromController(java.lang.String, java.lang.String); field public static final java.lang.String EXTRA_REQUEST_ROLE_NAME = "android.app.role.extra.REQUEST_ROLE_NAME"; } Loading
core/java/android/app/role/IRoleManager.aidl +4 −0 Original line number Diff line number Diff line Loading @@ -36,4 +36,8 @@ interface IRoleManager { in IRoleManagerCallback callback); void clearRoleHoldersAsUser(in String roleName, int userId, in IRoleManagerCallback callback); boolean addRoleHolderFromController(in String roleName, in String packageName); boolean removeRoleHolderFromController(in String roleName, in String packageName); }
core/java/android/app/role/RoleManager.java +114 −18 Original line number Diff line number Diff line Loading @@ -22,19 +22,16 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.util.ArraySet; import com.android.internal.util.Preconditions; import java.util.List; import java.util.Set; import java.util.concurrent.Executor; /** Loading @@ -51,8 +48,8 @@ import java.util.concurrent.Executor; * role holders. To qualify for a role, an application must meet certain requirements, including * defining certain components in its manifest. These requirements can be found in the AndroidX * Libraries. Then the application will need user consent to become a role holder, which can be * requested using {@link Activity#startActivityForResult(Intent, int)} with the {@code Intent} * obtained from {@link #createRequestRoleIntent(String)}. * requested using {@link android.app.Activity#startActivityForResult(Intent, int)} with the * {@code Intent} obtained from {@link #createRequestRoleIntent(String)}. * <p> * Upon becoming a role holder, the application may be granted certain privileges that are role * specific. When the application loses its role, these privileges will also be revoked. Loading Loading @@ -89,6 +86,14 @@ public final class RoleManager { @SystemApi public static final String EXTRA_REQUEST_ROLE_NAME = "android.app.role.extra.REQUEST_ROLE_NAME"; /** * The permission required to manage records of role holders in {@link RoleManager} directly. * * @hide */ public static final String PERMISSION_MANAGE_ROLE_HOLDERS_FROM_CONTROLLER = "com.android.permissioncontroller.permission.MANAGE_ROLE_HOLDERS_FROM_CONTROLLER"; @NonNull private final Context mContext; Loading @@ -105,11 +110,13 @@ public final class RoleManager { } /** * Returns an {@code Intent} suitable for passing to {@link Activity#startActivityForResult( * Intent, int)} which prompts the user to grant a role to this application. * Returns an {@code Intent} suitable for passing to * {@link android.app.Activity#startActivityForResult(Intent, int)} which prompts the user to * grant a role to this application. * <p> * If the role is granted, the {@code resultCode} will be {@link Activity#RESULT_OK}, otherwise * it will be {@link Activity#RESULT_CANCELED}. * If the role is granted, the {@code resultCode} will be * {@link android.app.Activity#RESULT_OK}, otherwise it will be * {@link android.app.Activity#RESULT_CANCELED}. * * @param roleName the name of requested role * Loading Loading @@ -162,6 +169,29 @@ public final class RoleManager { } } /** * Get package names of the applications holding the role. * <p> * <strong>Note:</strong> Using this API requires holding * {@code android.permission.MANAGE_ROLE_HOLDERS}. * * @param roleName the name of the role to get the role holder for * * @return a list of package names of the role holders, or an empty list if none. * * @throws IllegalArgumentException if the role name is {@code null} or empty. * * @see #getRoleHoldersAsUser(String, UserHandle) * * @hide */ @NonNull @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) @SystemApi public List<String> getRoleHolders(@NonNull String roleName) { return getRoleHoldersAsUser(roleName, UserHandle.of(UserHandle.getCallingUserId())); } /** * Get package names of the applications holding the role. * <p> Loading @@ -172,7 +202,7 @@ public final class RoleManager { * @param roleName the name of the role to get the role holder for * @param user the user to get the role holder for * * @return the package name of the role holder, or {@code null} if none. * @return a list of package names of the role holders, or an empty list if none. * * @throws IllegalArgumentException if the role name is {@code null} or empty. * Loading @@ -185,16 +215,14 @@ public final class RoleManager { @NonNull @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) @SystemApi public Set<String> getRoleHoldersAsUser(@NonNull String roleName, @NonNull UserHandle user) { public List<String> getRoleHoldersAsUser(@NonNull String roleName, @NonNull UserHandle user) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkNotNull(user, "user cannot be null"); List<String> roleHolders; try { roleHolders = mService.getRoleHoldersAsUser(roleName, user.getIdentifier()); return mService.getRoleHoldersAsUser(roleName, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } return new ArraySet<>(roleHolders); } /** Loading Loading @@ -312,6 +340,74 @@ public final class RoleManager { } } /** * Add a specific application to the holders of a role, only modifying records inside * {@link RoleManager}. Should only be called from * {@link android.rolecontrollerservice.RoleControllerService}. * <p> * <strong>Note:</strong> Using this API requires holding * {@link #PERMISSION_MANAGE_ROLE_HOLDERS_FROM_CONTROLLER}. * * @param roleName the name of the role to add the role holder for * @param packageName the package name of the application to add to the role holders * * @return whether the operation was successful, and will also be {@code true} if a matching * role holder is already found. * * @throws IllegalArgumentException if the role name or package name is {@code null} or empty. * * @see #getRoleHolders(String) * @see #removeRoleHolderFromController(String, String) * * @hide */ @RequiresPermission(PERMISSION_MANAGE_ROLE_HOLDERS_FROM_CONTROLLER) @SystemApi public boolean addRoleHolderFromController(@NonNull String roleName, @NonNull String packageName) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); try { return mService.addRoleHolderFromController(roleName, packageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Remove a specific application from the holders of a role, only modifying records inside * {@link RoleManager}. Should only be called from * {@link android.rolecontrollerservice.RoleControllerService}. * <p> * <strong>Note:</strong> Using this API requires holding * {@link #PERMISSION_MANAGE_ROLE_HOLDERS_FROM_CONTROLLER}. * * @param roleName the name of the role to remove the role holder for * @param packageName the package name of the application to remove from the role holders * * @return whether the operation was successful, and will also be {@code true} if no matching * role holder was found to remove. * * @throws IllegalArgumentException if the role name or package name is {@code null} or empty. * * @see #getRoleHolders(String) * @see #addRoleHolderFromController(String, String) * * @hide */ @RequiresPermission(PERMISSION_MANAGE_ROLE_HOLDERS_FROM_CONTROLLER) @SystemApi public boolean removeRoleHolderFromController(@NonNull String roleName, @NonNull String packageName) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); try { return mService.removeRoleHolderFromController(roleName, packageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } private static class RoleManagerCallbackDelegate extends IRoleManagerCallback.Stub { @NonNull Loading
services/core/java/com/android/server/role/RemoteRoleControllerService.java +7 −5 Original line number Diff line number Diff line Loading @@ -105,6 +105,9 @@ public class RemoteRoleControllerService { @NonNull private final Queue<Call> mPendingCalls = new ArrayDeque<>(); @NonNull private final Handler mMainHandler = Handler.getMain(); @NonNull private final Runnable mUnbindRunnable = this::unbind; Loading Loading @@ -142,7 +145,7 @@ public class RemoteRoleControllerService { } public void enqueueCall(@NonNull Call call) { Handler.getMain().post(PooledLambda.obtainRunnable(this::executeCall, call)); mMainHandler.post(PooledLambda.obtainRunnable(this::executeCall, call)); } @MainThread Loading @@ -158,7 +161,7 @@ public class RemoteRoleControllerService { @MainThread private void ensureBound() { Handler.getMain().removeCallbacks(mUnbindRunnable); mMainHandler.removeCallbacks(mUnbindRunnable); if (!mBound) { Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE); intent.setPackage(mContext.getPackageManager() Loading @@ -169,9 +172,8 @@ public class RemoteRoleControllerService { } private void scheduleUnbind() { Handler mainHandler = Handler.getMain(); mainHandler.removeCallbacks(mUnbindRunnable); mainHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS); mMainHandler.removeCallbacks(mUnbindRunnable); mMainHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS); } @MainThread Loading
services/core/java/com/android/server/role/RoleManagerService.java +33 −0 Original line number Diff line number Diff line Loading @@ -249,9 +249,42 @@ public class RoleManagerService extends SystemService { userId = handleIncomingUser(userId, "clearRoleHoldersAsUser"); getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, "clearRoleHoldersAsUser"); getControllerService(userId).onClearRoleHolders(roleName, callback); } @Override public boolean addRoleHolderFromController(@NonNull String roleName, @NonNull String packageName) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); getContext().enforceCallingOrSelfPermission( RoleManager.PERMISSION_MANAGE_ROLE_HOLDERS_FROM_CONTROLLER, "addRoleHolderFromController"); int userId = UserHandle.getCallingUserId(); synchronized (mLock) { RoleUserState userState = getUserStateLocked(userId); return userState.addRoleHolderLocked(roleName, packageName); } } @Override public boolean removeRoleHolderFromController(@NonNull String roleName, @NonNull String packageName) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); getContext().enforceCallingOrSelfPermission( RoleManager.PERMISSION_MANAGE_ROLE_HOLDERS_FROM_CONTROLLER, "removeRoleHolderFromController"); int userId = UserHandle.getCallingUserId(); synchronized (mLock) { RoleUserState userState = getUserStateLocked(userId); return userState.removeRoleHolderLocked(roleName, packageName); } } @CheckResult private int handleIncomingUser(@UserIdInt int userId, @NonNull String name) { return ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId, Loading