summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2018-11-01 22:22:45 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2018-11-01 22:22:45 +0000
commiteb651edabfaf9ac214183cfbf672c0b37b06831b (patch)
tree3987324fad904f521c749bc982c3081a07248638
parent8c2aef9ff8004f526ba148c5c9c9115feb4afd6d (diff)
parent87ed09ae425051c80ef7376d39b0bfcbf24df6b2 (diff)
Merge "Add controller APIs for RoleManager."
-rw-r--r--api/system-current.txt5
-rw-r--r--core/java/android/app/role/IRoleManager.aidl4
-rw-r--r--core/java/android/app/role/RoleManager.java132
-rw-r--r--services/core/java/com/android/server/role/RemoteRoleControllerService.java12
-rw-r--r--services/core/java/com/android/server/role/RoleManagerService.java33
-rw-r--r--services/core/java/com/android/server/role/RoleUserState.java19
6 files changed, 162 insertions, 43 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index 7e2953512431..1649fc775634 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -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";
}
diff --git a/core/java/android/app/role/IRoleManager.aidl b/core/java/android/app/role/IRoleManager.aidl
index 64f69c182f78..2cf13ec24141 100644
--- a/core/java/android/app/role/IRoleManager.aidl
+++ b/core/java/android/app/role/IRoleManager.aidl
@@ -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);
}
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index f7c6dea21e85..ed27d9fe9fd4 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -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;
/**
@@ -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.
@@ -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;
@@ -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
*
@@ -165,14 +172,37 @@ public final class RoleManager {
/**
* Get package names of the applications holding the role.
* <p>
- * <strong>Note: </strong>Using this API requires holding
+ * <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>
+ * <strong>Note:</strong> Using this API requires holding
* {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user
* {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
*
* @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.
*
@@ -185,23 +215,21 @@ 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);
}
/**
* Add a specific application to the holders of a role. If the role is exclusive, the previous
* holder will be replaced.
* <p>
- * <strong>Note: </strong>Using this API requires holding
+ * <strong>Note:</strong> Using this API requires holding
* {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user
* {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
*
@@ -240,7 +268,7 @@ public final class RoleManager {
/**
* Remove a specific application from the holders of a role.
* <p>
- * <strong>Note: </strong>Using this API requires holding
+ * <strong>Note:</strong> Using this API requires holding
* {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user
* {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
*
@@ -279,7 +307,7 @@ public final class RoleManager {
/**
* Remove all holders of a role.
* <p>
- * <strong>Note: </strong>Using this API requires holding
+ * <strong>Note:</strong> Using this API requires holding
* {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user
* {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
*
@@ -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
diff --git a/services/core/java/com/android/server/role/RemoteRoleControllerService.java b/services/core/java/com/android/server/role/RemoteRoleControllerService.java
index c737e8bb8710..b670291ba94b 100644
--- a/services/core/java/com/android/server/role/RemoteRoleControllerService.java
+++ b/services/core/java/com/android/server/role/RemoteRoleControllerService.java
@@ -106,6 +106,9 @@ public class RemoteRoleControllerService {
private final Queue<Call> mPendingCalls = new ArrayDeque<>();
@NonNull
+ private final Handler mMainHandler = Handler.getMain();
+
+ @NonNull
private final Runnable mUnbindRunnable = this::unbind;
Connection(@UserIdInt int userId, @NonNull Context context) {
@@ -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
@@ -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()
@@ -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
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 5c9cef507b67..b7d2ce29563e 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -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,
diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java
index bd5449151beb..caa7c2845ccb 100644
--- a/services/core/java/com/android/server/role/RoleUserState.java
+++ b/services/core/java/com/android/server/role/RoleUserState.java
@@ -174,25 +174,6 @@ public class RoleUserState {
}
/**
- * Remove all holders of a role.
- *
- * @param roleName the name of the role to remove all its holders
- *
- * @return {@code false} only if the set of role holders is null, which should not happen and
- * indicates an issue.
- */
- @GuardedBy("RoleManagerService.mLock")
- public boolean clearRoleHolderLocked(@NonNull String roleName) {
- throwIfDestroyedLocked();
- ArraySet<String> roleHolders = mRoles.get(roleName);
- if (roleHolders == null) {
- return false;
- }
- roleHolders.clear();
- return true;
- }
-
- /**
* Schedule writing the state to file.
*/
@GuardedBy("RoleManagerService.mLock")