summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--flags/flags.aconfig2
-rw-r--r--framework-s/Android.bp1
-rw-r--r--framework-s/api/system-current.txt2
-rw-r--r--framework-s/jarjar-rules.txt1
-rw-r--r--framework-s/java/android/app/role/IRoleManager.aidl4
-rw-r--r--framework-s/java/android/app/role/RoleManager.java49
-rw-r--r--service/Android.bp1
-rw-r--r--service/api/system-server-current.txt2
-rw-r--r--service/jarjar-rules.txt1
-rw-r--r--service/java/com/android/role/RoleService.java36
-rw-r--r--service/java/com/android/role/RoleUserState.java52
-rw-r--r--service/java/com/android/role/persistence/RolesPersistenceImpl.java12
-rw-r--r--service/java/com/android/role/persistence/RolesState.java41
-rw-r--r--service/proto/role_service.proto3
-rw-r--r--tests/apex/java/com/android/role/persistence/RolesPersistenceTest.kt50
-rw-r--r--tests/cts/role/src/android/app/role/cts/RoleManagerTest.java12
16 files changed, 248 insertions, 21 deletions
diff --git a/flags/flags.aconfig b/flags/flags.aconfig
index 050065368..64a9647ba 100644
--- a/flags/flags.aconfig
+++ b/flags/flags.aconfig
@@ -5,4 +5,4 @@ flag {
namespace: "permissions"
description: "This flag is used to support hotword activation events in privacy dashboard"
bug: "287264308"
-} \ No newline at end of file
+}
diff --git a/framework-s/Android.bp b/framework-s/Android.bp
index e017a7ea5..076b497cb 100644
--- a/framework-s/Android.bp
+++ b/framework-s/Android.bp
@@ -69,6 +69,7 @@ java_sdk_library {
static_libs: [
"framework-permission-s-shared",
"modules-utils-build",
+ "android.permission.flags-aconfig-java",
],
apex_available: [
"com.android.permission",
diff --git a/framework-s/api/system-current.txt b/framework-s/api/system-current.txt
index 9545356a4..f502a3231 100644
--- a/framework-s/api/system-current.txt
+++ b/framework-s/api/system-current.txt
@@ -29,12 +29,14 @@ package android.app.role {
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public java.util.List<java.lang.String> getRoleHoldersAsUser(@NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isApplicationVisibleForRole(@NonNull String, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public boolean isBypassingRoleQualification();
+ method @FlaggedApi(android.permission.flags.Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER) @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public boolean isRoleFallbackEnabled(@NonNull String);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isRoleVisible(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.OBSERVE_ROLE_HOLDERS) public void removeOnRoleHoldersChangedListenerAsUser(@NonNull android.app.role.OnRoleHoldersChangedListener, @NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void removeRoleHolderAsUser(@NonNull String, @NonNull String, int, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @Deprecated @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public boolean removeRoleHolderFromController(@NonNull String, @NonNull String);
method @RequiresPermission(android.Manifest.permission.BYPASS_ROLE_QUALIFICATION) public void setBypassingRoleQualification(boolean);
method @RequiresPermission(android.Manifest.permission.MANAGE_DEFAULT_APPLICATIONS) public void setDefaultApplication(@NonNull String, @Nullable String, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+ method @FlaggedApi(android.permission.flags.Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER) @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void setRoleFallbackEnabled(@NonNull String, boolean);
method @Deprecated @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public void setRoleNamesFromController(@NonNull java.util.List<java.lang.String>);
field public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; // 0x1
field public static final String ROLE_DEVICE_POLICY_MANAGEMENT = "android.app.role.DEVICE_POLICY_MANAGEMENT";
diff --git a/framework-s/jarjar-rules.txt b/framework-s/jarjar-rules.txt
index 3b888fe99..39f2ad3b7 100644
--- a/framework-s/jarjar-rules.txt
+++ b/framework-s/jarjar-rules.txt
@@ -1,4 +1,5 @@
rule android.os.HandlerExecutor android.permission.jarjar.@0
+rule android.permission.flags.** android.permission.jarjar.@0
rule android.util.IndentingPrintWriter android.permission.jarjar.@0
rule com.android.internal.** android.permission.jarjar.@0
rule com.android.modules.** android.permission.jarjar.@0
diff --git a/framework-s/java/android/app/role/IRoleManager.aidl b/framework-s/java/android/app/role/IRoleManager.aidl
index 5f7cb1bf5..5bcda037e 100644
--- a/framework-s/java/android/app/role/IRoleManager.aidl
+++ b/framework-s/java/android/app/role/IRoleManager.aidl
@@ -54,6 +54,10 @@ interface IRoleManager {
void setBypassingRoleQualification(boolean bypassRoleQualification);
+ boolean isRoleFallbackEnabledAsUser(in String roleName, int userId);
+
+ void setRoleFallbackEnabledAsUser(in String roleName, boolean fallbackEnabled, int userId);
+
void setRoleNamesFromController(in List<String> roleNames);
boolean addRoleHolderFromController(in String roleName, in String packageName);
diff --git a/framework-s/java/android/app/role/RoleManager.java b/framework-s/java/android/app/role/RoleManager.java
index d8e7149f2..cb3ebfe3c 100644
--- a/framework-s/java/android/app/role/RoleManager.java
+++ b/framework-s/java/android/app/role/RoleManager.java
@@ -18,6 +18,7 @@ package android.app.role;
import android.Manifest;
import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -35,6 +36,7 @@ import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.permission.flags.Flags;
import android.util.ArrayMap;
import android.util.SparseArray;
@@ -690,6 +692,53 @@ public final class RoleManager {
}
/**
+ * Check whether role currently enables fallback to default holder.
+ * <p>
+ * This is based on the "None" holder being actively selected, in which case don't fallback.
+ *
+ * @param roleName the name of the role being queried
+ *
+ * @return whether fallback is enabled for the provided role
+ *
+ * @hide
+ */
+ @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
+ @FlaggedApi(Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER)
+ @UserHandleAware
+ @SystemApi
+ public boolean isRoleFallbackEnabled(@NonNull String roleName) {
+ try {
+ return mService.isRoleFallbackEnabledAsUser(roleName,
+ mContext.getUser().getIdentifier());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Set whether role should fallback to a default role holder.
+ *
+ * @param roleName the name of the role being queried.
+ * @param fallbackEnabled whether to enable fallback holders for this role.
+ *
+ * @hide
+ */
+ @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
+ @FlaggedApi(Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER)
+ @UserHandleAware
+ @SystemApi
+ public void setRoleFallbackEnabled(@NonNull String roleName, boolean fallbackEnabled) {
+ try {
+ mService.setRoleFallbackEnabledAsUser(roleName, fallbackEnabled,
+ mContext.getUser().getIdentifier());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Set the names of all the available roles. Should only be called from
* {@link android.app.role.RoleControllerService}.
* <p>
diff --git a/service/Android.bp b/service/Android.bp
index 96b8fbb96..a6513508a 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -108,6 +108,7 @@ java_sdk_library {
"service-permission-shared",
"service-permission-statsd",
"service-permission-proto-stream",
+ "android.permission.flags-aconfig-java",
],
errorprone: {
javacflags: ["-Xep:GuardedBy:ERROR"],
diff --git a/service/api/system-server-current.txt b/service/api/system-server-current.txt
index b1869c2c7..ea9c9750c 100644
--- a/service/api/system-server-current.txt
+++ b/service/api/system-server-current.txt
@@ -45,6 +45,8 @@ package com.android.role.persistence {
public final class RolesState {
ctor public RolesState(int, @Nullable String, @NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>>);
+ ctor @FlaggedApi(android.permission.flags.Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER) public RolesState(int, @Nullable String, @NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>>, @NonNull java.util.Set<java.lang.String>);
+ method @FlaggedApi(android.permission.flags.Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER) @NonNull public java.util.Set<java.lang.String> getFallbackEnabledRoles();
method @Nullable public String getPackagesHash();
method @NonNull public java.util.Map<java.lang.String,java.util.Set<java.lang.String>> getRoles();
method public int getVersion();
diff --git a/service/jarjar-rules.txt b/service/jarjar-rules.txt
index 2b8765cf5..a3fd75930 100644
--- a/service/jarjar-rules.txt
+++ b/service/jarjar-rules.txt
@@ -1,4 +1,5 @@
rule android.os.HandlerExecutor com.android.permission.jarjar.@0
+rule android.permission.flags.** com.android.permission.jarjar.@0
rule android.util.IndentingPrintWriter com.android.permission.jarjar.@0
rule com.android.internal.** com.android.permission.jarjar.@0
rule com.android.modules.** com.android.permission.jarjar.@0
diff --git a/service/java/com/android/role/RoleService.java b/service/java/com/android/role/RoleService.java
index f18a9e79e..6845d506b 100644
--- a/service/java/com/android/role/RoleService.java
+++ b/service/java/com/android/role/RoleService.java
@@ -649,6 +649,42 @@ public class RoleService extends SystemService implements RoleUserState.Callback
}
@Override
+ public boolean isRoleFallbackEnabledAsUser(@NonNull String roleName,
+ @UserIdInt int userId) {
+ UserUtils.enforceCrossUserPermission(userId, false, "isRoleFallbackEnabledAsUser",
+ getContext());
+ if (!UserUtils.isUserExistent(userId, getContext())) {
+ Log.e(LOG_TAG, "user " + userId + " does not exist");
+ return false;
+ }
+
+ getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
+ "isRoleFallbackEnabledAsUser");
+
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+
+ return getOrCreateUserState(userId).isFallbackEnabled(roleName);
+ }
+
+ @Override
+ public void setRoleFallbackEnabledAsUser(@NonNull String roleName, boolean fallbackEnabled,
+ @UserIdInt int userId) {
+ UserUtils.enforceCrossUserPermission(userId, false, "setRoleFallbackEnabledAsUser",
+ getContext());
+ if (!UserUtils.isUserExistent(userId, getContext())) {
+ Log.e(LOG_TAG, "user " + userId + " does not exist");
+ return;
+ }
+
+ getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
+ "setRoleFallbackEnabledAsUser");
+
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+
+ getOrCreateUserState(userId).setFallbackEnabled(roleName, fallbackEnabled);
+ }
+
+ @Override
public void setRoleNamesFromController(@NonNull List<String> roleNames) {
getContext().enforceCallingOrSelfPermission(
RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
diff --git a/service/java/com/android/role/RoleUserState.java b/service/java/com/android/role/RoleUserState.java
index 727e0f122..201633898 100644
--- a/service/java/com/android/role/RoleUserState.java
+++ b/service/java/com/android/role/RoleUserState.java
@@ -53,6 +53,8 @@ class RoleUserState {
public static final int VERSION_UNDEFINED = -1;
+ public static final int VERSION_FALLBACK_STATE_MIGRATED = 1;
+
private static final long WRITE_DELAY_MILLIS = 200;
private final RolesPersistence mPersistence = RolesPersistence.createInstance();
@@ -86,6 +88,13 @@ class RoleUserState {
@NonNull
private ArrayMap<String, ArraySet<String>> mRoles = new ArrayMap<>();
+ /**
+ *
+ */
+ @GuardedBy("mLock")
+ @NonNull
+ private ArraySet<String> mFallbackEnabledRoles = new ArraySet<>();
+
@GuardedBy("mLock")
private boolean mWriteScheduled;
@@ -193,6 +202,31 @@ class RoleUserState {
}
}
+ public boolean isFallbackEnabled(@NonNull String roleName) {
+ synchronized (mLock) {
+ return mFallbackEnabledRoles.contains(roleName);
+ }
+ }
+
+ public void setFallbackEnabled(@NonNull String roleName, boolean fallbackEnabled) {
+ synchronized (mLock) {
+ if (!mRoles.containsKey(roleName)) {
+ Log.e(LOG_TAG, "Cannot set fallback enabled for unknown role, role: " + roleName
+ + ", fallbackEnabled: " + fallbackEnabled);
+ return;
+ }
+ if (mFallbackEnabledRoles.contains(roleName) == fallbackEnabled) {
+ return;
+ }
+ if (fallbackEnabled) {
+ mFallbackEnabledRoles.add(roleName);
+ } else {
+ mFallbackEnabledRoles.remove(roleName);
+ }
+ scheduleWriteFileLocked();
+ }
+ }
+
/**
* Get whether the role is available.
*
@@ -386,7 +420,8 @@ class RoleUserState {
// Force a reconciliation on next boot if we are bypassing role qualification now.
String packagesHash = mBypassingRoleQualification ? null : mPackagesHash;
roles = new RolesState(mVersion, packagesHash,
- (Map<String, Set<String>>) (Map<String, ?>) snapshotRolesLocked());
+ (Map<String, Set<String>>) (Map<String, ?>) snapshotRolesLocked(),
+ snapshotFallbackEnabledRoles());
}
mPersistence.writeForUser(roles, UserHandle.of(mUserId));
@@ -413,6 +448,9 @@ class RoleUserState {
if (roleState == null) {
scheduleWriteFileLocked();
+ } else {
+ mFallbackEnabledRoles.clear();
+ mFallbackEnabledRoles.addAll(roleState.getFallbackEnabledRoles());
}
}
}
@@ -427,10 +465,12 @@ class RoleUserState {
int version;
String packagesHash;
ArrayMap<String, ArraySet<String>> roles;
+ ArraySet<String> fallbackEnabledRoles;
synchronized (mLock) {
version = mVersion;
packagesHash = mPackagesHash;
roles = snapshotRolesLocked();
+ fallbackEnabledRoles = snapshotFallbackEnabledRoles();
}
long fieldToken = dumpOutputStream.start(fieldName, fieldId);
@@ -442,10 +482,12 @@ class RoleUserState {
for (int rolesIndex = 0; rolesIndex < rolesSize; rolesIndex++) {
String roleName = roles.keyAt(rolesIndex);
ArraySet<String> roleHolders = roles.valueAt(rolesIndex);
+ boolean fallbackEnabled = fallbackEnabledRoles.contains(roleName);
long rolesToken = dumpOutputStream.start("roles", RoleUserStateProto.ROLES);
dumpOutputStream.write("name", RoleProto.NAME, roleName);
-
+ dumpOutputStream.write("fallback_enabled", RoleProto.FALLBACK_ENABLED,
+ Boolean.toString(fallbackEnabled));
int roleHoldersSize = roleHolders.size();
for (int roleHoldersIndex = 0; roleHoldersIndex < roleHoldersSize; roleHoldersIndex++) {
String roleHolder = roleHolders.valueAt(roleHoldersIndex);
@@ -485,6 +527,12 @@ class RoleUserState {
return roles;
}
+ @GuardedBy("mLock")
+ @NonNull
+ private ArraySet<String> snapshotFallbackEnabledRoles() {
+ return new ArraySet<>(mFallbackEnabledRoles);
+ }
+
/**
* Destroy this user state and delete the corresponding file. Any pending writes to the file
* will be cancelled, and any future interaction with this state will throw an exception.
diff --git a/service/java/com/android/role/persistence/RolesPersistenceImpl.java b/service/java/com/android/role/persistence/RolesPersistenceImpl.java
index 76cf8f81f..242f7315f 100644
--- a/service/java/com/android/role/persistence/RolesPersistenceImpl.java
+++ b/service/java/com/android/role/persistence/RolesPersistenceImpl.java
@@ -66,6 +66,7 @@ public class RolesPersistenceImpl implements RolesPersistence {
private static final String ATTRIBUTE_VERSION = "version";
private static final String ATTRIBUTE_NAME = "name";
+ private static final String ATTRIBUTE_FALLBACK_ENABLED = "fallbackEnabled";
private static final String ATTRIBUTE_PACKAGES_HASH = "packagesHash";
@VisibleForTesting
@@ -142,6 +143,7 @@ public class RolesPersistenceImpl implements RolesPersistence {
String packagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH);
Map<String, Set<String>> roles = new ArrayMap<>();
+ Set<String> fallbackEnabledRoles = new ArraySet<>();
int type;
int depth;
int innerDepth = parser.getDepth() + 1;
@@ -153,12 +155,16 @@ public class RolesPersistenceImpl implements RolesPersistence {
if (parser.getName().equals(TAG_ROLE)) {
String roleName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+ String fallbackEnabled = parser.getAttributeValue(null, ATTRIBUTE_FALLBACK_ENABLED);
+ if (Boolean.parseBoolean(fallbackEnabled)) {
+ fallbackEnabledRoles.add(roleName);
+ }
Set<String> roleHolders = parseRoleHolders(parser);
roles.put(roleName, roleHolders);
}
}
- return new RolesState(version, packagesHash, roles);
+ return new RolesState(version, packagesHash, roles, fallbackEnabledRoles);
}
@NonNull
@@ -238,12 +244,16 @@ public class RolesPersistenceImpl implements RolesPersistence {
serializer.attribute(null, ATTRIBUTE_PACKAGES_HASH, packagesHash);
}
+ Set<String> fallbackEnabledRoles = roles.getFallbackEnabledRoles();
for (Map.Entry<String, Set<String>> entry : roles.getRoles().entrySet()) {
String roleName = entry.getKey();
Set<String> roleHolders = entry.getValue();
+ boolean isFallbackEnabled = fallbackEnabledRoles.contains(roleName);
serializer.startTag(null, TAG_ROLE);
serializer.attribute(null, ATTRIBUTE_NAME, roleName);
+ serializer.attribute(null, ATTRIBUTE_FALLBACK_ENABLED,
+ Boolean.toString(isFallbackEnabled));
serializeRoleHolders(serializer, roleHolders);
serializer.endTag(null, TAG_ROLE);
}
diff --git a/service/java/com/android/role/persistence/RolesState.java b/service/java/com/android/role/persistence/RolesState.java
index f61efa0e8..fc6b88f26 100644
--- a/service/java/com/android/role/persistence/RolesState.java
+++ b/service/java/com/android/role/persistence/RolesState.java
@@ -16,10 +16,13 @@
package com.android.role.persistence;
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.SystemApi.Client;
+import android.permission.flags.Flags;
+import android.util.ArraySet;
import java.util.Map;
import java.util.Objects;
@@ -33,7 +36,6 @@ import java.util.Set;
*/
@SystemApi(client = Client.SYSTEM_SERVER)
public final class RolesState {
-
/**
* The version of the roles.
*/
@@ -52,6 +54,12 @@ public final class RolesState {
private final Map<String, Set<String>> mRoles;
/**
+ * The names of roles with fallback enabled.
+ */
+ @NonNull
+ private final Set<String> mFallbackEnabledRoles;
+
+ /**
* Create a new instance of this class.
*
* @param version the version of the roles
@@ -60,9 +68,24 @@ public final class RolesState {
*/
public RolesState(int version, @Nullable String packagesHash,
@NonNull Map<String, Set<String>> roles) {
+ this(version, packagesHash, roles, new ArraySet<>());
+ }
+
+ /**
+ * Create a new instance of this class.
+ *
+ * @param version the version of the roles
+ * @param packagesHash the hash of all packages in the system
+ * @param roles the roles
+ * @param fallbackEnabledRoles the roles with fallback enabled
+ */
+ @FlaggedApi(Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER)
+ public RolesState(int version, @Nullable String packagesHash,
+ @NonNull Map<String, Set<String>> roles, @NonNull Set<String> fallbackEnabledRoles) {
mVersion = version;
mPackagesHash = packagesHash;
mRoles = roles;
+ mFallbackEnabledRoles = fallbackEnabledRoles;
}
/**
@@ -94,6 +117,17 @@ public final class RolesState {
return mRoles;
}
+ /**
+ * Get the fallback enabled roles.
+ *
+ * @return fallback enabled roles
+ */
+ @NonNull
+ @FlaggedApi(Flags.FLAG_ROLE_CONTROLLER_IN_SYSTEM_SERVER)
+ public Set<String> getFallbackEnabledRoles() {
+ return mFallbackEnabledRoles;
+ }
+
@Override
public boolean equals(Object object) {
if (this == object) {
@@ -105,11 +139,12 @@ public final class RolesState {
RolesState that = (RolesState) object;
return mVersion == that.mVersion
&& Objects.equals(mPackagesHash, that.mPackagesHash)
- && Objects.equals(mRoles, that.mRoles);
+ && Objects.equals(mRoles, that.mRoles)
+ && Objects.equals(mFallbackEnabledRoles, that.mFallbackEnabledRoles);
}
@Override
public int hashCode() {
- return Objects.hash(mVersion, mPackagesHash, mRoles);
+ return Objects.hash(mVersion, mPackagesHash, mRoles, mFallbackEnabledRoles);
}
}
diff --git a/service/proto/role_service.proto b/service/proto/role_service.proto
index 79c422992..f982ead5b 100644
--- a/service/proto/role_service.proto
+++ b/service/proto/role_service.proto
@@ -53,4 +53,7 @@ message RoleProto {
// The package names of the holders of this role.
repeated string holders = 2;
+
+ // Whether fallback holders are enabled for this role.
+ optional bool fallback_enabled = 3;
}
diff --git a/tests/apex/java/com/android/role/persistence/RolesPersistenceTest.kt b/tests/apex/java/com/android/role/persistence/RolesPersistenceTest.kt
index d90ffade9..0cf1fa665 100644
--- a/tests/apex/java/com/android/role/persistence/RolesPersistenceTest.kt
+++ b/tests/apex/java/com/android/role/persistence/RolesPersistenceTest.kt
@@ -20,7 +20,6 @@ import android.content.ApexEnvironment
import android.content.Context
import android.os.Process
import android.os.UserHandle
-import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.google.common.truth.Truth.assertThat
@@ -29,6 +28,7 @@ import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
@@ -37,27 +37,36 @@ import org.mockito.MockitoAnnotations.initMocks
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
-@RunWith(AndroidJUnit4::class)
+@RunWith(Parameterized::class)
class RolesPersistenceTest {
private val context = InstrumentationRegistry.getInstrumentation().context
private lateinit var mockDataDirectory: File
-
private lateinit var mockitoSession: MockitoSession
@Mock lateinit var apexEnvironment: ApexEnvironment
+ @Parameterized.Parameter(0) lateinit var stateVersion: StateVersion
+ private lateinit var state: RolesState
private val persistence = RolesPersistenceImpl {}
- private val state = RolesState(1, "packagesHash", mapOf("role" to setOf("holder1", "holder2")))
+ private val defaultRoles = mapOf(ROLE_NAME to setOf(HOLDER_1, HOLDER_2))
+ private val stateVersionUndefined = RolesState(VERSION_UNDEFINED, PACKAGE_HASH, defaultRoles)
+ private val stateVersionFallbackMigrated =
+ RolesState(VERSION_FALLBACK_MIGRATED, PACKAGE_HASH, defaultRoles, setOf(ROLE_NAME))
private val user = Process.myUserHandle()
@Before
- fun createMockDataDirectory() {
+ fun setUp() {
+ createMockDataDirectory()
+ mockApexEnvironment()
+ state = getState()
+ }
+
+ private fun createMockDataDirectory() {
mockDataDirectory = context.getDir("mock_data", Context.MODE_PRIVATE)
mockDataDirectory.listFiles()!!.forEach { assertThat(it.deleteRecursively()).isTrue() }
}
- @Before
- fun mockApexEnvironment() {
+ private fun mockApexEnvironment() {
initMocks(this)
mockitoSession =
mockitoSession()
@@ -80,7 +89,7 @@ class RolesPersistenceTest {
persistence.writeForUser(state, user)
val persistedState = persistence.readForUser(user)
- checkPersistedState(persistedState)
+ assertThat(persistedState).isEqualTo(state)
}
@Test
@@ -91,7 +100,7 @@ class RolesPersistenceTest {
.writeText("<roles version=\"-1\"><role name=\"com.foo.bar\"><holder")
val persistedState = persistence.readForUser(user)
- checkPersistedState(persistedState)
+ assertThat(persistedState).isEqualTo(state)
}
@Test
@@ -102,15 +111,28 @@ class RolesPersistenceTest {
assertThat(persistedState).isNull()
}
+ private fun getState(): RolesState =
+ when (stateVersion) {
+ StateVersion.VERSION_UNDEFINED -> stateVersionUndefined
+ StateVersion.VERSION_FALLBACK_MIGRATED -> stateVersionFallbackMigrated
+ }
- private fun checkPersistedState(persistedState: RolesState?) {
- assertThat(persistedState).isEqualTo(state)
- assertThat(persistedState?.version).isEqualTo(state.version)
- assertThat(persistedState?.packagesHash).isEqualTo(state.packagesHash)
- assertThat(persistedState?.roles).isEqualTo(state.roles)
+ enum class StateVersion {
+ VERSION_UNDEFINED,
+ VERSION_FALLBACK_MIGRATED
}
companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun data(): Array<StateVersion> = StateVersion.values()
+
+ private const val VERSION_UNDEFINED = -1
+ private const val VERSION_FALLBACK_MIGRATED = 1
private const val APEX_MODULE_NAME = "com.android.permission"
+ private const val PACKAGE_HASH = "packagesHash"
+ private const val ROLE_NAME = "roleName"
+ private const val HOLDER_1 = "holder1"
+ private const val HOLDER_2 = "holder2"
}
}
diff --git a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java
index a7429ac99..61625d587 100644
--- a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java
+++ b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java
@@ -1153,6 +1153,18 @@ public class RoleManagerTest {
});
}
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM,
+ codeName = "VanillaIceCream")
+ @Test
+ public void testSetAndGetRoleFallbackEnabled() {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
+
+ runWithShellPermissionIdentity(() -> {
+ sRoleManager.setRoleFallbackEnabled(RoleManager.ROLE_SMS, true);
+ assertThat(sRoleManager.isRoleFallbackEnabled(RoleManager.ROLE_SMS)).isTrue();
+ });
+ }
+
@NonNull
private List<String> getRoleHolders(@NonNull String roleName) throws Exception {
return callWithShellPermissionIdentity(() -> sRoleManager.getRoleHolders(roleName));