diff options
author | 2024-01-26 14:38:06 +0000 | |
---|---|---|
committer | 2024-02-14 01:26:25 +0000 | |
commit | 4675be8559d10d1fb60bfde9bfe4214ec5ad2c64 (patch) | |
tree | 0cf1a7e3b90d20329861cd115166d28cc6376cd4 | |
parent | 516e07ac988a28443fb579ba945e82909c5de6d9 (diff) |
Add getEmergencyRoleHolder SystemApi to RoleManager.
This API then enables TelephonyManager to expose the emergency
role holder to priviliged clients via getEmergencyAssistancePackageName.
Bug: 323157319
Test: atest RoleManagerTest
LOW_COVERAGE_REASON=Flagged test added but flag not enabled
Change-Id: I91089701248a32a720b488147405b2566cca2be9
-rw-r--r-- | framework-s/api/module-lib-current.txt | 1 | ||||
-rw-r--r-- | framework-s/java/android/app/role/IRoleManager.aidl | 2 | ||||
-rw-r--r-- | framework-s/java/android/app/role/RoleManager.java | 22 | ||||
-rw-r--r-- | service/java/com/android/role/RoleService.java | 27 | ||||
-rw-r--r-- | tests/cts/role/Android.bp | 2 | ||||
-rw-r--r-- | tests/cts/role/src/android/app/role/cts/RoleManagerTest.java | 22 |
6 files changed, 75 insertions, 1 deletions
diff --git a/framework-s/api/module-lib-current.txt b/framework-s/api/module-lib-current.txt index 14f71782e..97a8623b3 100644 --- a/framework-s/api/module-lib-current.txt +++ b/framework-s/api/module-lib-current.txt @@ -15,6 +15,7 @@ package android.app.role { public final class RoleManager { method @Nullable public String getBrowserRoleHolder(int); + method @FlaggedApi("android.permission.flags.get_emergency_role_holder_api_enabled") @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getEmergencyRoleHolder(int); method @Nullable public String getSmsRoleHolder(int); method @Nullable @RequiresPermission(android.Manifest.permission.SET_PREFERRED_APPLICATIONS) public boolean setBrowserRoleHolder(@Nullable String, int); } diff --git a/framework-s/java/android/app/role/IRoleManager.aidl b/framework-s/java/android/app/role/IRoleManager.aidl index 0aef871e6..522967630 100644 --- a/framework-s/java/android/app/role/IRoleManager.aidl +++ b/framework-s/java/android/app/role/IRoleManager.aidl @@ -74,6 +74,8 @@ interface IRoleManager { String getSmsRoleHolder(int userId); + String getEmergencyRoleHolder(int userId); + boolean isRoleVisibleAsUser(in String roleName, int userId); boolean isApplicationVisibleForRoleAsUser(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 fe27d50f3..4b8c9b388 100644 --- a/framework-s/java/android/app/role/RoleManager.java +++ b/framework-s/java/android/app/role/RoleManager.java @@ -975,6 +975,28 @@ public final class RoleManager { } /** + * Allows getting the role holder for {@link #ROLE_EMERGENCY} without requiring + * {@link Manifest.permission#OBSERVE_ROLE_HOLDERS}. + * + * @param userId the user ID to get the default emergency package for + * @return the package name of the default emergency app, or {@code null} if none + * + * @hide + */ + @FlaggedApi(Flags.FLAG_GET_EMERGENCY_ROLE_HOLDER_API_ENABLED) + @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) + @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @Nullable + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public String getEmergencyRoleHolder(@UserIdInt int userId) { + try { + return mService.getEmergencyRoleHolder(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Check whether a role should be visible to user. * * @param roleName name of the role to check for diff --git a/service/java/com/android/role/RoleService.java b/service/java/com/android/role/RoleService.java index a2a6bab35..f441ce2f3 100644 --- a/service/java/com/android/role/RoleService.java +++ b/service/java/com/android/role/RoleService.java @@ -930,6 +930,33 @@ public class RoleService extends SystemService implements RoleUserState.Callback } @Override + public String getEmergencyRoleHolder(int userId) { + final Context context = getContext(); + UserUtils.enforceCrossUserPermission(userId, false, "getEmergencyRoleHolder", context); + if (!UserUtils.isUserExistent(userId, getContext())) { + Log.e(LOG_TAG, "user " + userId + " does not exist"); + return null; + } + + getContext().enforceCallingOrSelfPermission( + Manifest.permission.READ_PRIVILEGED_PHONE_STATE, "getEmergencyRoleHolder"); + + final String packageName; + final long identity = Binder.clearCallingIdentity(); + try { + packageName = CollectionUtils.firstOrNull(getRoleHoldersAsUser( + RoleManager.ROLE_EMERGENCY, userId)); + } finally { + Binder.restoreCallingIdentity(identity); + } + if (packageName != null && !PackageUtils.canCallingOrSelfPackageQuery(packageName, + userId, context)) { + return null; + } + return packageName; + } + + @Override public boolean isRoleVisibleAsUser(@NonNull String roleName, @UserIdInt int userId) { UserUtils.enforceCrossUserPermission(userId, false, "isRoleVisibleAsUser", getContext()); diff --git a/tests/cts/role/Android.bp b/tests/cts/role/Android.bp index cf6b7ee8c..2a312976b 100644 --- a/tests/cts/role/Android.bp +++ b/tests/cts/role/Android.bp @@ -32,8 +32,8 @@ android_test { "androidx.test.rules", "compatibility-device-util-axt", "ctstestrunner-axt", - "truth", "platform-test-annotations", + "truth", ], test_suites: [ 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 c53718ba4..ee898d660 100644 --- a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java +++ b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java @@ -49,6 +49,7 @@ import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.Settings; import android.provider.Telephony; +import android.telephony.TelephonyManager; import android.util.Pair; import androidx.annotation.NonNull; @@ -1103,6 +1104,27 @@ public class RoleManagerTest { assertThat(Telephony.Sms.getDefaultSmsPackage(sContext)).isEqualTo(APP_PACKAGE_NAME); } + @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, + codeName = "VanillaIceCream") + @Test + @RequiresFlagsEnabled(Flags.FLAG_GET_EMERGENCY_ROLE_HOLDER_API_ENABLED) + public void telephonyManagerGetEmergencyAssistancePackageNameBackedByRole() throws Exception { + TelephonyManager telephonyManager = sContext.getSystemService(TelephonyManager.class); + List<String> emergencyRoleHolders = getRoleHolders(RoleManager.ROLE_EMERGENCY); + + if (callWithShellPermissionIdentity(() -> + telephonyManager.isEmergencyAssistanceEnabled())) { + String emergencyAssistancePackageName = callWithShellPermissionIdentity(() -> + telephonyManager.getEmergencyAssistancePackage()); + assertThat(emergencyRoleHolders).hasSize(1); + assertThat(emergencyAssistancePackageName).isEqualTo(emergencyRoleHolders.get(0)); + } else { + assertThrows(IllegalStateException.class, () -> + callWithShellPermissionIdentity(() -> + telephonyManager.getEmergencyAssistancePackage())); + } + } + @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S") @Test public void cannotBypassRoleQualificationWithoutPermission() throws Exception { |