summaryrefslogtreecommitdiff
path: root/PermissionController/role-controller/java
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2024-03-06 09:30:09 -0800
committerXin Li <delphij@google.com>2024-03-06 09:30:09 -0800
commit3624ef6638b619f2f7bdaea0ce60687582cc6e76 (patch)
treeaf45b4b9b8a6479bcd0a0cf50882f598c7892c97 /PermissionController/role-controller/java
parent92bfe739812beec44c20532857713720d5946294 (diff)
parent60508898c865eba3829b42017d22bd7f44a64622 (diff)
downloadPermission-3624ef6638b619f2f7bdaea0ce60687582cc6e76.tar.gz
Merge Android 14 QPR2 to AOSP main
Bug: 319669529 Merged-In: I9355c44d196061398015858c96f51bc78f8e4374 Change-Id: I26b18315958b277873976b15c2f6d4119c5639bc
Diffstat (limited to 'PermissionController/role-controller/java')
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java125
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/BrowserRoleBehavior.java42
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceAppStreamingRoleBehavior.java16
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceComputerRoleBehavior.java16
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceGlassesRoleBehavior.java16
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceWatchRoleBehavior.java16
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/DialerRoleBehavior.java23
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/DocumentManagerRoleBehavior.java8
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/EmergencyRoleBehavior.java17
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java104
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/RetailDemoRoleBehavior.java65
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/SmsRoleBehavior.java35
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/SystemShellRoleBehavior.java10
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/SystemUiRoleBehavior.java59
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/AppOp.java25
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/AppOpPermissions.java50
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/Permission.java21
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/Permissions.java288
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/PreferredActivity.java18
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RequiredActivity.java19
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RequiredBroadcastReceiver.java14
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RequiredComponent.java55
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RequiredContentProvider.java14
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RequiredService.java13
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/Role.java162
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RoleBehavior.java57
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RoleParser.java44
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/VisibilityMixin.java70
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/service/RoleControllerServiceImpl.java491
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/util/LegacyRoleFallbackEnabledUtils.java107
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/util/NotificationUtils.java39
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/util/PackageUtils.java27
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/util/ResourceUtils.java57
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/util/RoleManagerCompat.java52
34 files changed, 1580 insertions, 595 deletions
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java
index 12710cfd3..c20734cde 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java
@@ -20,12 +20,12 @@ import android.app.ActivityManager;
import android.app.role.RoleManager;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
-import android.os.Process;
import android.os.UserHandle;
import android.service.voice.VoiceInteractionService;
import android.util.ArraySet;
@@ -38,6 +38,7 @@ import androidx.annotation.Nullable;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.RoleBehavior;
+import com.android.role.controller.model.VisibilityMixin;
import com.android.role.controller.util.UserUtils;
import org.xmlpull.v1.XmlPullParserException;
@@ -54,20 +55,17 @@ public class AssistantRoleBehavior implements RoleBehavior {
private static final String LOG_TAG = AssistantRoleBehavior.class.getSimpleName();
- private static final Intent ASSIST_SERVICE_PROBE =
- new Intent(VoiceInteractionService.SERVICE_INTERFACE);
- private static final Intent ASSIST_ACTIVITY_PROBE = new Intent(Intent.ACTION_ASSIST);
-
@Override
- public void onRoleAdded(@NonNull Role role, @NonNull Context context) {
+ public void onRoleAddedAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
PackageManager packageManager = context.getPackageManager();
if (packageManager.isDeviceUpgrading()) {
RoleManager roleManager = context.getSystemService(RoleManager.class);
- List<String> packageNames = roleManager.getRoleHolders(role.getName());
+ List<String> packageNames = roleManager.getRoleHoldersAsUser(role.getName(), user);
if (packageNames.isEmpty()) {
// If the device was upgraded, and there isn't any legacy role holders, it means
// user selected "None" in Settings and we need to keep that.
- role.onNoneHolderSelectedAsUser(Process.myUserHandle(), context);
+ role.onNoneHolderSelectedAsUser(user, context);
}
}
}
@@ -82,81 +80,72 @@ public class AssistantRoleBehavior implements RoleBehavior {
@Override
public List<String> getQualifyingPackagesAsUser(@NonNull Role role, @NonNull UserHandle user,
@NonNull Context context) {
+ return getQualifyingPackagesInternal(null, user, context);
+ }
+
+ @Nullable
+ @Override
+ public Boolean isPackageQualifiedAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ return !getQualifyingPackagesInternal(packageName, user, context)
+ .isEmpty();
+ }
+
+ @NonNull
+ private List<String> getQualifyingPackagesInternal(@Nullable String filterPackageName,
+ @NonNull UserHandle user, @NonNull Context context) {
Context userContext = UserUtils.getUserContext(context, user);
ActivityManager userActivityManager = userContext.getSystemService(ActivityManager.class);
PackageManager userPackageManager = userContext.getPackageManager();
- Set<String> availableAssistants = new ArraySet<>();
+ Set<String> packageNames = new ArraySet<>();
if (!userActivityManager.isLowRamDevice()) {
- List<ResolveInfo> services = userPackageManager.queryIntentServices(
- ASSIST_SERVICE_PROBE, PackageManager.GET_META_DATA
+ Intent serviceIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
+ if (filterPackageName != null) {
+ serviceIntent.setPackage(filterPackageName);
+ }
+ List<ResolveInfo> serviceResolveInfos = userPackageManager.queryIntentServices(
+ serviceIntent, PackageManager.GET_META_DATA
| PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
- int numServices = services.size();
- for (int i = 0; i < numServices; i++) {
- ResolveInfo service = services.get(i);
-
- if (isAssistantVoiceInteractionService(userPackageManager, service.serviceInfo)) {
- availableAssistants.add(service.serviceInfo.packageName);
+ int serviceResolveInfosSize = serviceResolveInfos.size();
+ for (int i = 0; i < serviceResolveInfosSize; i++) {
+ ResolveInfo serviceResolveInfo = serviceResolveInfos.get(i);
+
+ ServiceInfo serviceInfo = serviceResolveInfo.serviceInfo;
+ if (!isAssistantVoiceInteractionService(userPackageManager, serviceInfo)) {
+ if (filterPackageName != null) {
+ Log.w(LOG_TAG, "Package " + filterPackageName
+ + " has an unqualified voice interaction service");
+ }
+ continue;
}
+
+ packageNames.add(serviceInfo.packageName);
}
}
- List<ResolveInfo> activities = userPackageManager.queryIntentActivities(
- ASSIST_ACTIVITY_PROBE, PackageManager.MATCH_DEFAULT_ONLY
+ Intent activityIntent = new Intent(Intent.ACTION_ASSIST);
+ if (filterPackageName != null) {
+ activityIntent.setPackage(filterPackageName);
+ }
+ List<ResolveInfo> activityResolveInfos = userPackageManager.queryIntentActivities(
+ activityIntent, PackageManager.MATCH_DEFAULT_ONLY
| PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
- int numActivities = activities.size();
- for (int i = 0; i < numActivities; i++) {
- availableAssistants.add(activities.get(i).activityInfo.packageName);
- }
-
- return new ArrayList<>(availableAssistants);
- }
-
- @Nullable
- @Override
- public Boolean isPackageQualified(@NonNull Role role, @NonNull String packageName,
- @NonNull Context context) {
- ActivityManager activityManager = context.getSystemService(ActivityManager.class);
- PackageManager packageManager = context.getPackageManager();
-
- boolean hasAssistantService = false;
- if (!activityManager.isLowRamDevice()) {
- Intent pkgServiceProbe = new Intent(ASSIST_SERVICE_PROBE).setPackage(packageName);
- List<ResolveInfo> services = packageManager.queryIntentServices(pkgServiceProbe,
- PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
- hasAssistantService = !services.isEmpty();
- int numServices = services.size();
- for (int i = 0; i < numServices; i++) {
- ResolveInfo service = services.get(i);
+ int activityResolveInfosSize = activityResolveInfos.size();
+ for (int i = 0; i < activityResolveInfosSize; i++) {
+ ResolveInfo activityResolveInfo = activityResolveInfos.get(i);
- if (isAssistantVoiceInteractionService(packageManager, service.serviceInfo)) {
- return true;
- }
+ ActivityInfo activityInfo = activityResolveInfo.activityInfo;
+ if (!activityInfo.exported) {
+ continue;
}
- }
- Intent pkgActivityProbe = new Intent(ASSIST_ACTIVITY_PROBE).setPackage(packageName);
- boolean hasAssistantActivity = !packageManager.queryIntentActivities(pkgActivityProbe,
- PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE).isEmpty();
- if (!hasAssistantActivity) {
- Log.w(LOG_TAG, "Package " + packageName + " not qualified for " + role.getName()
- + " due to " + (hasAssistantService ? "unqualified" : "missing")
- + " service and missing activity");
+ packageNames.add(activityInfo.packageName);
}
- return hasAssistantActivity;
- }
-
- @Override
- public void grant(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- }
-
- @Override
- public void revoke(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
+ return new ArrayList<>(packageNames);
}
private boolean isAssistantVoiceInteractionService(@NonNull PackageManager pm,
@@ -205,4 +194,10 @@ public class AssistantRoleBehavior implements RoleBehavior {
return true;
}
+
+ @Override
+ public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ return VisibilityMixin.isVisible("config_showDefaultAssistant", false, user, context);
+ }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/BrowserRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/BrowserRoleBehavior.java
index 2cf6a0b14..0261e1eee 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/BrowserRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/BrowserRoleBehavior.java
@@ -21,7 +21,6 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
-import android.os.Process;
import android.os.UserHandle;
import android.util.ArraySet;
@@ -32,6 +31,7 @@ import com.android.modules.utils.build.SdkLevel;
import com.android.role.controller.model.Permissions;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.RoleBehavior;
+import com.android.role.controller.model.VisibilityMixin;
import com.android.role.controller.util.CollectionUtils;
import com.android.role.controller.util.PackageUtils;
import com.android.role.controller.util.UserUtils;
@@ -61,10 +61,10 @@ public class BrowserRoleBehavior implements RoleBehavior {
@Nullable
@Override
- public String getFallbackHolder(@NonNull Role role, @NonNull Context context) {
- UserHandle user = Process.myUserHandle();
- List<String> qualifyingPackageNames = getQualifyingPackagesAsUserInternal(null, false, user,
- context);
+ public String getFallbackHolderAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ List<String> qualifyingPackageNames = getQualifyingPackagesAsUserInternal(null, false,
+ user, context);
if (qualifyingPackageNames.size() == 1) {
return qualifyingPackageNames.get(0);
}
@@ -76,7 +76,7 @@ public class BrowserRoleBehavior implements RoleBehavior {
return qualifyingSystemPackageNames.get(0);
}
- List<String> defaultPackageNames = role.getDefaultHolders(context);
+ List<String> defaultPackageNames = role.getDefaultHoldersAsUser(user, context);
return CollectionUtils.firstOrNull(defaultPackageNames);
} else {
return null;
@@ -95,10 +95,10 @@ public class BrowserRoleBehavior implements RoleBehavior {
@Nullable
@Override
- public Boolean isPackageQualified(@NonNull Role role, @NonNull String packageName,
- @NonNull Context context) {
+ public Boolean isPackageQualifiedAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
List<String> packageNames = getQualifyingPackagesAsUserInternal(packageName, false,
- Process.myUserHandle(), context);
+ user, context);
return !packageNames.isEmpty();
}
@@ -133,24 +133,32 @@ public class BrowserRoleBehavior implements RoleBehavior {
}
@Override
- public void grant(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
+ public void grantAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
// @see com.android.server.pm.permission.DefaultPermissionGrantPolicy
// #grantDefaultPermissionsToDefaultBrowser(java.lang.String, int)
if (SdkLevel.isAtLeastS()) {
- if (PackageUtils.isSystemPackage(packageName, context)) {
- Permissions.grant(packageName, SYSTEM_BROWSER_PERMISSIONS, false, false, true,
- false, false, context);
+ if (PackageUtils.isSystemPackageAsUser(packageName, user, context)) {
+ Permissions.grantAsUser(packageName, SYSTEM_BROWSER_PERMISSIONS, false, false,
+ true, false, false, user, context);
}
}
}
@Override
- public void revoke(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
+ public void revokeAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
if (SdkLevel.isAtLeastT()) {
- if (PackageUtils.isSystemPackage(packageName, context)) {
- Permissions.revoke(packageName, SYSTEM_BROWSER_PERMISSIONS, true, false, false,
- context);
+ if (PackageUtils.isSystemPackageAsUser(packageName, user, context)) {
+ Permissions.revokeAsUser(packageName, SYSTEM_BROWSER_PERMISSIONS, true, false,
+ false, user, context);
}
}
}
+
+ @Override
+ public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ return VisibilityMixin.isVisible("config_showBrowserRole", true, user, context);
+ }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceAppStreamingRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceAppStreamingRoleBehavior.java
index 131690fd7..c164de3d8 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceAppStreamingRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceAppStreamingRoleBehavior.java
@@ -17,12 +17,14 @@
package com.android.role.controller.behavior;
import android.content.Context;
+import android.os.UserHandle;
import androidx.annotation.NonNull;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.RoleBehavior;
import com.android.role.controller.util.NotificationUtils;
+import com.android.role.controller.util.UserUtils;
/**
* Class for behavior of the "App Streaming" Companion device profile role.
@@ -30,12 +32,18 @@ import com.android.role.controller.util.NotificationUtils;
public class CompanionDeviceAppStreamingRoleBehavior implements RoleBehavior {
@Override
- public void grant(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- NotificationUtils.grantNotificationAccessForPackage(context, packageName);
+ public void grantAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ if (!UserUtils.isManagedProfile(user, context)) {
+ NotificationUtils.grantNotificationAccessForPackageAsUser(packageName, user, context);
+ }
}
@Override
- public void revoke(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- NotificationUtils.revokeNotificationAccessForPackage(context, packageName);
+ public void revokeAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ if (!UserUtils.isManagedProfile(user, context)) {
+ NotificationUtils.revokeNotificationAccessForPackageAsUser(packageName, user, context);
+ }
}
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceComputerRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceComputerRoleBehavior.java
index c59d5e58d..e5d996675 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceComputerRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceComputerRoleBehavior.java
@@ -17,12 +17,14 @@
package com.android.role.controller.behavior;
import android.content.Context;
+import android.os.UserHandle;
import androidx.annotation.NonNull;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.RoleBehavior;
import com.android.role.controller.util.NotificationUtils;
+import com.android.role.controller.util.UserUtils;
/**
* Class for behavior of the "Computer" Companion device profile role.
@@ -30,12 +32,18 @@ import com.android.role.controller.util.NotificationUtils;
public class CompanionDeviceComputerRoleBehavior implements RoleBehavior {
@Override
- public void grant(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- NotificationUtils.grantNotificationAccessForPackage(context, packageName);
+ public void grantAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ if (!UserUtils.isManagedProfile(user, context)) {
+ NotificationUtils.grantNotificationAccessForPackageAsUser(packageName, user, context);
+ }
}
@Override
- public void revoke(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- NotificationUtils.revokeNotificationAccessForPackage(context, packageName);
+ public void revokeAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ if (!UserUtils.isManagedProfile(user, context)) {
+ NotificationUtils.revokeNotificationAccessForPackageAsUser(packageName, user, context);
+ }
}
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceGlassesRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceGlassesRoleBehavior.java
index 2e4691b9c..5464a1518 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceGlassesRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceGlassesRoleBehavior.java
@@ -17,12 +17,14 @@
package com.android.role.controller.behavior;
import android.content.Context;
+import android.os.UserHandle;
import androidx.annotation.NonNull;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.RoleBehavior;
import com.android.role.controller.util.NotificationUtils;
+import com.android.role.controller.util.UserUtils;
/**
* Class for behavior of the "glasses" Companion device profile role.
@@ -30,12 +32,18 @@ import com.android.role.controller.util.NotificationUtils;
public class CompanionDeviceGlassesRoleBehavior implements RoleBehavior {
@Override
- public void grant(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- NotificationUtils.grantNotificationAccessForPackage(context, packageName);
+ public void grantAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ if (!UserUtils.isManagedProfile(user, context)) {
+ NotificationUtils.grantNotificationAccessForPackageAsUser(packageName, user, context);
+ }
}
@Override
- public void revoke(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- NotificationUtils.revokeNotificationAccessForPackage(context, packageName);
+ public void revokeAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ if (!UserUtils.isManagedProfile(user, context)) {
+ NotificationUtils.revokeNotificationAccessForPackageAsUser(packageName, user, context);
+ }
}
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceWatchRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceWatchRoleBehavior.java
index 233c0d92e..0645c84d1 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceWatchRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/CompanionDeviceWatchRoleBehavior.java
@@ -17,12 +17,14 @@
package com.android.role.controller.behavior;
import android.content.Context;
+import android.os.UserHandle;
import androidx.annotation.NonNull;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.RoleBehavior;
import com.android.role.controller.util.NotificationUtils;
+import com.android.role.controller.util.UserUtils;
/**
* Class for behavior of the "watch" Companion device profile role.
@@ -30,12 +32,18 @@ import com.android.role.controller.util.NotificationUtils;
public class CompanionDeviceWatchRoleBehavior implements RoleBehavior {
@Override
- public void grant(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- NotificationUtils.grantNotificationAccessForPackage(context, packageName);
+ public void grantAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ if (!UserUtils.isManagedProfile(user, context)) {
+ NotificationUtils.grantNotificationAccessForPackageAsUser(packageName, user, context);
+ }
}
@Override
- public void revoke(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- NotificationUtils.revokeNotificationAccessForPackage(context, packageName);
+ public void revokeAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ if (!UserUtils.isManagedProfile(user, context)) {
+ NotificationUtils.revokeNotificationAccessForPackageAsUser(packageName, user, context);
+ }
}
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/DialerRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/DialerRoleBehavior.java
index 79c139cee..57b5412dc 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/DialerRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/DialerRoleBehavior.java
@@ -26,6 +26,7 @@ import com.android.modules.utils.build.SdkLevel;
import com.android.role.controller.model.Permissions;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.RoleBehavior;
+import com.android.role.controller.model.VisibilityMixin;
import com.android.role.controller.util.PackageUtils;
import java.util.Arrays;
@@ -55,20 +56,28 @@ public class DialerRoleBehavior implements RoleBehavior {
}
@Override
- public void grant(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
+ public void grantAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
if (SdkLevel.isAtLeastS()) {
- if (PackageUtils.isSystemPackage(packageName, context)) {
- Permissions.grant(packageName, SYSTEM_DIALER_PERMISSIONS, false, false,
- true, false, false, context);
+ if (PackageUtils.isSystemPackageAsUser(packageName, user, context)) {
+ Permissions.grantAsUser(packageName, SYSTEM_DIALER_PERMISSIONS, false, false,
+ true, false, false, user, context);
}
}
}
@Override
- public void revoke(@NonNull Role role, @NonNull String packageName,
- @NonNull Context context) {
+ public void revokeAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
if (SdkLevel.isAtLeastS()) {
- Permissions.revoke(packageName, SYSTEM_DIALER_PERMISSIONS, true, false, false, context);
+ Permissions.revokeAsUser(packageName, SYSTEM_DIALER_PERMISSIONS, true, false, false,
+ user, context);
}
}
+
+ @Override
+ public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ return VisibilityMixin.isVisible("config_showDialerRole", true, user, context);
+ }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/DocumentManagerRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/DocumentManagerRoleBehavior.java
index ee7984274..fa030a00a 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/DocumentManagerRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/DocumentManagerRoleBehavior.java
@@ -17,7 +17,7 @@
package com.android.role.controller.behavior;
import android.content.Context;
-import android.os.Process;
+import android.os.UserHandle;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -36,9 +36,9 @@ public class DocumentManagerRoleBehavior implements RoleBehavior {
@NonNull
@Override
- public List<String> getDefaultHolders(@NonNull Role role, @NonNull Context context) {
- List<String> qualifyingPackageNames = role.getQualifyingPackagesAsUser(
- Process.myUserHandle(), context);
+ public List<String> getDefaultHoldersAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ List<String> qualifyingPackageNames = role.getQualifyingPackagesAsUser(user, context);
if (qualifyingPackageNames.size() == 1) {
return qualifyingPackageNames;
} else {
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/EmergencyRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/EmergencyRoleBehavior.java
index a54006bb5..f19c86596 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/EmergencyRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/EmergencyRoleBehavior.java
@@ -18,7 +18,6 @@ package com.android.role.controller.behavior;
import android.content.Context;
import android.content.pm.PackageInfo;
-import android.os.Process;
import android.os.UserHandle;
import android.telephony.TelephonyManager;
@@ -27,6 +26,7 @@ import androidx.annotation.Nullable;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.RoleBehavior;
+import com.android.role.controller.model.VisibilityMixin;
import com.android.role.controller.util.PackageUtils;
import java.util.List;
@@ -49,15 +49,16 @@ public class EmergencyRoleBehavior implements RoleBehavior {
@Nullable
@Override
- public String getFallbackHolder(@NonNull Role role, @NonNull Context context) {
- List<String> packageNames = role.getQualifyingPackagesAsUser(Process.myUserHandle(),
- context);
+ public String getFallbackHolderAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ List<String> packageNames = role.getQualifyingPackagesAsUser(user, context);
PackageInfo fallbackPackageInfo = null;
int packageNamesSize = packageNames.size();
for (int i = 0; i < packageNamesSize; i++) {
String packageName = packageNames.get(i);
- PackageInfo packageInfo = PackageUtils.getPackageInfo(packageName, 0, context);
+ PackageInfo packageInfo = PackageUtils.getPackageInfoAsUser(packageName, 0,
+ user, context);
if (packageInfo == null) {
continue;
}
@@ -68,4 +69,10 @@ public class EmergencyRoleBehavior implements RoleBehavior {
}
return fallbackPackageInfo != null ? fallbackPackageInfo.packageName : null;
}
+
+ @Override
+ public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ return VisibilityMixin.isVisible("config_showDefaultEmergency", false, user, context);
+ }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java
index 3254bc6e4..4bf5a6294 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java
@@ -22,15 +22,20 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.content.pm.ResolveInfo;
+import android.os.Build;
import android.os.UserHandle;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import com.android.modules.utils.build.SdkLevel;
+import com.android.role.controller.model.AppOpPermissions;
import com.android.role.controller.model.Permissions;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.RoleBehavior;
+import com.android.role.controller.model.VisibilityMixin;
import com.android.role.controller.util.UserUtils;
import java.util.Arrays;
@@ -51,6 +56,18 @@ public class HomeRoleBehavior implements RoleBehavior {
android.Manifest.permission.WRITE_CALL_LOG,
android.Manifest.permission.READ_CONTACTS);
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private static final List<String> WEAR_PERMISSIONS_T = Arrays.asList(
+ android.Manifest.permission.POST_NOTIFICATIONS,
+ android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY);
+
+ @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ private static final List<String> WEAR_PERMISSIONS_V = Arrays.asList(
+ android.Manifest.permission.ALWAYS_UPDATE_WALLPAPER);
+
+ private static final List<String> WEAR_APP_OP_PERMISSIONS = Arrays.asList(
+ android.Manifest.permission.SYSTEM_ALERT_WINDOW);
+
@Override
public boolean isAvailableAsUser(@NonNull Role role, @NonNull UserHandle user,
@NonNull Context context) {
@@ -62,10 +79,12 @@ public class HomeRoleBehavior implements RoleBehavior {
*/
@Nullable
@Override
- public String getFallbackHolder(@NonNull Role role, @NonNull Context context) {
- PackageManager packageManager = context.getPackageManager();
+ public String getFallbackHolderAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ PackageManager userPackageManager = userContext.getPackageManager();
Intent intent = role.getRequiredComponents().get(0).getIntentFilterData().createIntent();
- List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(intent,
+ List<ResolveInfo> resolveInfos = userPackageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
@@ -78,7 +97,8 @@ public class HomeRoleBehavior implements RoleBehavior {
// Leave the fallback to PackageManagerService if there is only the fallback home in
// Settings, because if we fallback to it here, we cannot fallback to a normal home
// later, and user cannot see the fallback home in the UI anyway.
- if (isSettingsApplication(resolveInfo.activityInfo.applicationInfo, context)) {
+ if (isSettingsApplicationAsUser(resolveInfo.activityInfo.applicationInfo, user,
+ context)) {
continue;
}
if (resolveInfo.priority > priority) {
@@ -94,14 +114,16 @@ public class HomeRoleBehavior implements RoleBehavior {
/**
* Check if the application is a settings application
*/
- public static boolean isSettingsApplication(@NonNull ApplicationInfo applicationInfo,
- @NonNull Context context) {
- PackageManager packageManager = context.getPackageManager();
- ResolveInfo resolveInfo = packageManager.resolveActivity(new Intent(
- Settings.ACTION_SETTINGS), PackageManager.MATCH_DEFAULT_ONLY
+ private static boolean isSettingsApplicationAsUser(@NonNull ApplicationInfo applicationInfo,
+ @NonNull UserHandle user, @NonNull Context context) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ PackageManager userPackageManager = userContext.getPackageManager();
+ ResolveInfo resolveInfo = userPackageManager.resolveActivity(
+ new Intent(Settings.ACTION_SETTINGS), PackageManager.MATCH_DEFAULT_ONLY
| PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
- if (resolveInfo == null || resolveInfo.activityInfo == null) {
+ if (resolveInfo == null || resolveInfo.activityInfo == null
+ || !resolveInfo.activityInfo.exported) {
return false;
}
return Objects.equals(applicationInfo.packageName, resolveInfo.activityInfo.packageName);
@@ -119,31 +141,62 @@ public class HomeRoleBehavior implements RoleBehavior {
}
@Override
- public void grant(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
+ public void grantAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
- Permissions.grant(packageName, AUTOMOTIVE_PERMISSIONS,
- true, false, true, false, false, context);
+ Permissions.grantAsUser(packageName, AUTOMOTIVE_PERMISSIONS,
+ true, false, true, false, false, user, context);
}
// Before T, ALLOW_SLIPPERY_TOUCHES may either not exist, or may not be a role permission
if (isRolePermission(android.Manifest.permission.ALLOW_SLIPPERY_TOUCHES, context)) {
- Permissions.grant(packageName,
+ Permissions.grantAsUser(packageName,
Arrays.asList(android.Manifest.permission.ALLOW_SLIPPERY_TOUCHES),
- true, false, true, false, false, context);
+ true, false, true, false, false, user, context);
+ }
+
+ if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+ if (SdkLevel.isAtLeastT()) {
+ Permissions.grantAsUser(packageName, WEAR_PERMISSIONS_T,
+ true, false, true, false, false, user, context);
+ for (String permission : WEAR_APP_OP_PERMISSIONS) {
+ AppOpPermissions.grantAsUser(packageName, permission, true, user, context);
+ }
+ }
+ if (SdkLevel.isAtLeastV()) {
+ Permissions.grantAsUser(packageName, WEAR_PERMISSIONS_V,
+ true, false, true, false, false, user, context);
+ }
}
}
@Override
- public void revoke(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
+ public void revokeAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
- Permissions.revoke(packageName, AUTOMOTIVE_PERMISSIONS, true, false, false, context);
+ Permissions.revokeAsUser(packageName, AUTOMOTIVE_PERMISSIONS, true, false, false,
+ user, context);
}
// Before T, ALLOW_SLIPPERY_TOUCHES may either not exist, or may not be a role permission
if (isRolePermission(android.Manifest.permission.ALLOW_SLIPPERY_TOUCHES, context)) {
- Permissions.revoke(packageName,
+ Permissions.revokeAsUser(packageName,
Arrays.asList(android.Manifest.permission.ALLOW_SLIPPERY_TOUCHES),
- true, false, false, context);
+ true, false, false, user, context);
+ }
+
+ if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+ if (SdkLevel.isAtLeastT()) {
+ Permissions.revokeAsUser(packageName, WEAR_PERMISSIONS_T, true, false, false,
+ user, context);
+ for (String permission : WEAR_APP_OP_PERMISSIONS) {
+ AppOpPermissions.revokeAsUser(packageName, permission, user, context);
+ }
+ }
+ if (SdkLevel.isAtLeastV()) {
+ Permissions.revokeAsUser(packageName, WEAR_PERMISSIONS_V, true, false, false,
+ user, context);
+ }
}
}
@@ -161,4 +214,17 @@ public class HomeRoleBehavior implements RoleBehavior {
final int flags = permissionInfo.getProtectionFlags();
return (flags & PermissionInfo.PROTECTION_FLAG_ROLE) == PermissionInfo.PROTECTION_FLAG_ROLE;
}
+
+ @Override
+ public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ return VisibilityMixin.isVisible("config_showDefaultHome", false, user, context);
+ }
+
+ @Override
+ public boolean isApplicationVisibleAsUser(@NonNull Role role,
+ @NonNull ApplicationInfo applicationInfo, @NonNull UserHandle user,
+ @NonNull Context context) {
+ return !isSettingsApplicationAsUser(applicationInfo, user, context);
+ }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/RetailDemoRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/RetailDemoRoleBehavior.java
new file mode 100644
index 000000000..6dcdafd4c
--- /dev/null
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/RetailDemoRoleBehavior.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.role.controller.behavior;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.Build;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import com.android.role.controller.model.Role;
+import com.android.role.controller.model.RoleBehavior;
+import com.android.role.controller.util.UserUtils;
+
+/**
+ * Class for behavior of the Retail Demo role.
+ */
+@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+public class RetailDemoRoleBehavior implements RoleBehavior {
+
+ @Override
+ public Boolean isPackageQualifiedAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ if (Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.DEVICE_DEMO_MODE, 0) == 0) {
+ return false;
+ }
+ Context userContext = UserUtils.getUserContext(context, user);
+ DevicePolicyManager userDevicePolicyManager =
+ userContext.getSystemService(DevicePolicyManager.class);
+ if (!(userDevicePolicyManager.isDeviceOwnerApp(packageName)
+ || userDevicePolicyManager.isProfileOwnerApp(packageName))) {
+ return false;
+ }
+ // Fallback to do additional default check.
+ return null;
+ }
+
+ @Override
+ public boolean isAvailableAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ UserManager userUserManager = userContext.getSystemService(UserManager.class);
+ return userUserManager.isSystemUser() || userUserManager.isMainUser()
+ || userUserManager.isDemoUser();
+ }
+}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/SmsRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/SmsRoleBehavior.java
index c1186a930..b614594c5 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/SmsRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/SmsRoleBehavior.java
@@ -19,7 +19,6 @@ package com.android.role.controller.behavior;
import android.app.admin.DevicePolicyManager;
import android.app.admin.ManagedSubscriptionsPolicy;
import android.content.Context;
-import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.TelephonyManager;
@@ -31,6 +30,7 @@ import com.android.modules.utils.build.SdkLevel;
import com.android.role.controller.model.Permissions;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.RoleBehavior;
+import com.android.role.controller.model.VisibilityMixin;
import com.android.role.controller.util.CollectionUtils;
import com.android.role.controller.util.PackageUtils;
import com.android.role.controller.util.UserUtils;
@@ -90,7 +90,7 @@ public class SmsRoleBehavior implements RoleBehavior {
TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
if (!telephonyManager.isSmsCapable()
// Ensure sms role is present on car despite !isSmsCapable config (b/132972702)
- && role.getDefaultHolders(context).isEmpty()) {
+ && role.getDefaultHoldersAsUser(user, context).isEmpty()) {
return false;
}
return true;
@@ -98,8 +98,9 @@ public class SmsRoleBehavior implements RoleBehavior {
@Nullable
@Override
- public String getFallbackHolder(@NonNull Role role, @NonNull Context context) {
- List<String> defaultPackageNames = role.getDefaultHolders(context);
+ public String getFallbackHolderAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ List<String> defaultPackageNames = role.getDefaultHoldersAsUser(user, context);
if (!defaultPackageNames.isEmpty()) {
return defaultPackageNames.get(0);
}
@@ -107,24 +108,32 @@ public class SmsRoleBehavior implements RoleBehavior {
// TODO(b/132916161): This was the previous behavior, however this may allow any third-party
// app to suddenly become the default SMS app and get the permissions, if no system default
// SMS app is available.
- List<String> qualifyingPackageNames = role.getQualifyingPackagesAsUser(
- Process.myUserHandle(), context);
+ List<String> qualifyingPackageNames = role.getQualifyingPackagesAsUser(user, context);
return CollectionUtils.firstOrNull(qualifyingPackageNames);
}
@Override
- public void grant(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- if (SdkLevel.isAtLeastS() && PackageUtils.isSystemPackage(packageName, context)) {
- Permissions.grant(packageName, SYSTEM_SMS_PERMISSIONS, false, false,
- true, false, false, context);
+ public void grantAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ if (SdkLevel.isAtLeastS() && PackageUtils.isSystemPackageAsUser(packageName, user,
+ context)) {
+ Permissions.grantAsUser(packageName, SYSTEM_SMS_PERMISSIONS, false, false, true,
+ false, false, user, context);
}
}
@Override
- public void revoke(@NonNull Role role, @NonNull String packageName,
- @NonNull Context context) {
+ public void revokeAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
if (SdkLevel.isAtLeastS()) {
- Permissions.revoke(packageName, SYSTEM_SMS_PERMISSIONS, true, false, false, context);
+ Permissions.revokeAsUser(packageName, SYSTEM_SMS_PERMISSIONS, true, false, false,
+ user, context);
}
}
+
+ @Override
+ public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ return VisibilityMixin.isVisible("config_showSmsRole", true, user, context);
+ }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/SystemShellRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/SystemShellRoleBehavior.java
index c0cbe9c25..621955770 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/SystemShellRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/SystemShellRoleBehavior.java
@@ -26,6 +26,7 @@ import androidx.annotation.Nullable;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.RoleBehavior;
+import com.android.role.controller.util.UserUtils;
/**
* Class for behavior of the system shell role.
@@ -33,12 +34,13 @@ import com.android.role.controller.model.RoleBehavior;
public class SystemShellRoleBehavior implements RoleBehavior {
@Nullable
@Override
- public Boolean isPackageQualified(@NonNull Role role, @NonNull String packageName,
- @NonNull Context context) {
- PackageManager packageManager = context.getPackageManager();
+ public Boolean isPackageQualifiedAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ PackageManager userPackageManager = userContext.getPackageManager();
int uid;
try {
- uid = packageManager.getPackageUid(packageName, 0);
+ uid = userPackageManager.getPackageUid(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
return false;
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/SystemUiRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/SystemUiRoleBehavior.java
deleted file mode 100644
index 210c2313f..000000000
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/SystemUiRoleBehavior.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.role.controller.behavior;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-import androidx.annotation.NonNull;
-
-import com.android.modules.utils.build.SdkLevel;
-import com.android.role.controller.model.AppOpPermissions;
-import com.android.role.controller.model.Role;
-import com.android.role.controller.model.RoleBehavior;
-
-import java.util.Arrays;
-import java.util.List;
-
-/** The role behavior for system ui. */
-public class SystemUiRoleBehavior implements RoleBehavior {
-
- private static final List<String> WEAR_APP_OP_PERMISSIONS =
- Arrays.asList(android.Manifest.permission.SYSTEM_ALERT_WINDOW);
-
- @Override
- public void grant(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- if (SdkLevel.isAtLeastT()) {
- if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
- for (String permission : WEAR_APP_OP_PERMISSIONS) {
- AppOpPermissions.grant(packageName, permission, true, context);
- }
- }
- }
- }
-
- @Override
- public void revoke(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- if (SdkLevel.isAtLeastT()) {
- if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
- for (String permission : WEAR_APP_OP_PERMISSIONS) {
- AppOpPermissions.revoke(packageName, permission, context);
- }
- }
- }
- }
-}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/AppOp.java b/PermissionController/role-controller/java/com/android/role/controller/model/AppOp.java
index 3efa68bc9..6647a4f94 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/AppOp.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/AppOp.java
@@ -18,7 +18,7 @@ package com.android.role.controller.model;
import android.content.Context;
import android.content.pm.ApplicationInfo;
-import android.os.Process;
+import android.os.UserHandle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -73,39 +73,44 @@ public class AppOp {
* Grant this app op to an application.
*
* @param packageName the package name of the application
+ * @param user the user of the application
* @param context the {@code Context} to retrieve system services
*
* @return whether any app mode has changed
*/
- public boolean grant(@NonNull String packageName, @NonNull Context context) {
- if (!checkTargetSdkVersion(packageName, context)) {
+ public boolean grantAsUser(@NonNull String packageName, @NonNull UserHandle user,
+ @NonNull Context context) {
+ if (!checkTargetSdkVersionAsUser(packageName, user, context)) {
return false;
}
- return Permissions.setAppOpUidMode(packageName, mName, mMode, context);
+ return Permissions.setAppOpUidModeAsUser(packageName, mName, mMode, user, context);
}
/**
* Revoke this app op from an application.
*
* @param packageName the package name of the application
+ * @param user the user of the application
* @param context the {@code Context} to retrieve system services
*
* @return whether any app mode has changed
*/
- public boolean revoke(@NonNull String packageName, @NonNull Context context) {
- if (!checkTargetSdkVersion(packageName, context)) {
+ public boolean revokeAsUser(@NonNull String packageName, @NonNull UserHandle user,
+ @NonNull Context context) {
+ if (!checkTargetSdkVersionAsUser(packageName, user, context)) {
return false;
}
int defaultMode = Permissions.getDefaultAppOpMode(mName);
- return Permissions.setAppOpUidMode(packageName, mName, defaultMode, context);
+ return Permissions.setAppOpUidModeAsUser(packageName, mName, defaultMode, user, context);
}
- private boolean checkTargetSdkVersion(@NonNull String packageName, @NonNull Context context) {
+ private boolean checkTargetSdkVersionAsUser(@NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
if (mMaxTargetSdkVersion == null) {
return true;
}
- ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName,
- Process.myUserHandle(), context);
+ ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName, user,
+ context);
if (applicationInfo == null) {
return false;
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/AppOpPermissions.java b/PermissionController/role-controller/java/com/android/role/controller/model/AppOpPermissions.java
index 29939a1a5..edd74e31e 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/AppOpPermissions.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/AppOpPermissions.java
@@ -21,6 +21,7 @@ import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
+import android.os.UserHandle;
import androidx.annotation.NonNull;
@@ -42,14 +43,15 @@ public class AppOpPermissions {
* @param appOpPermission the name of the app op permission
* @param overrideNonDefaultMode whether to override the app opp mode if it isn't in the default
* mode
+ * @param user the user of the application
* @param context the {@code Context} to retrieve system services
*
* @return whether any app op mode has changed
*/
- public static boolean grant(@NonNull String packageName, @NonNull String appOpPermission,
- boolean overrideNonDefaultMode, @NonNull Context context) {
- PackageInfo packageInfo = PackageUtils.getPackageInfo(packageName,
- PackageManager.GET_PERMISSIONS, context);
+ public static boolean grantAsUser(@NonNull String packageName, @NonNull String appOpPermission,
+ boolean overrideNonDefaultMode, @NonNull UserHandle user, @NonNull Context context) {
+ PackageInfo packageInfo = PackageUtils.getPackageInfoAsUser(packageName,
+ PackageManager.GET_PERMISSIONS, user, context);
if (packageInfo == null) {
return false;
}
@@ -58,14 +60,16 @@ public class AppOpPermissions {
}
String appOp = AppOpsManagerCompat.permissionToOp(appOpPermission);
if (!overrideNonDefaultMode) {
- Integer currentMode = Permissions.getAppOpMode(packageName, appOp, context);
+ Integer currentMode = Permissions.getAppOpModeAsUser(packageName, appOp, user, context);
if (currentMode != null && currentMode != Permissions.getDefaultAppOpMode(appOp)) {
return false;
}
}
- boolean changed = setAppOpMode(packageName, appOp, AppOpsManager.MODE_ALLOWED, context);
+ boolean changed = setAppOpModeAsUser(packageName, appOp, AppOpsManager.MODE_ALLOWED, user,
+ context);
if (changed) {
- Permissions.setPermissionGrantedByRole(packageName, appOpPermission, true, context);
+ Permissions.setPermissionGrantedByRoleAsUser(packageName, appOpPermission, true,
+ user, context);
}
return changed;
}
@@ -75,24 +79,27 @@ public class AppOpPermissions {
*
* @param packageName the package name of the application
* @param appOpPermission the name of the app op permission
+ * @param user the user of the application
* @param context the {@code Context} to retrieve system services
*
* @return whether any app op mode has changed
*/
- public static boolean revoke(@NonNull String packageName, @NonNull String appOpPermission,
- @NonNull Context context) {
- if (!Permissions.isPermissionGrantedByRole(packageName, appOpPermission, context)) {
+ public static boolean revokeAsUser(@NonNull String packageName, @NonNull String appOpPermission,
+ @NonNull UserHandle user, @NonNull Context context) {
+ if (!Permissions.isPermissionGrantedByRoleAsUser(packageName, appOpPermission, user,
+ context)) {
return false;
}
String appOp = AppOpsManager.permissionToOp(appOpPermission);
int defaultMode = Permissions.getDefaultAppOpMode(appOp);
- boolean changed = setAppOpMode(packageName, appOp, defaultMode, context);
- Permissions.setPermissionGrantedByRole(packageName, appOpPermission, false, context);
+ boolean changed = setAppOpModeAsUser(packageName, appOp, defaultMode, user, context);
+ Permissions.setPermissionGrantedByRoleAsUser(packageName, appOpPermission, false,
+ user, context);
return changed;
}
- private static boolean setAppOpMode(@NonNull String packageName, @NonNull String appOp,
- int mode, @NonNull Context context) {
+ private static boolean setAppOpModeAsUser(@NonNull String packageName, @NonNull String appOp,
+ int mode, @NonNull UserHandle user, @NonNull Context context) {
switch (appOp) {
case AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS:
case AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW:
@@ -105,22 +112,25 @@ public class AppOpPermissions {
case AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS:
case AppOpsManager.OPSTR_INSTANT_APP_START_FOREGROUND:
case AppOpsManager.OPSTR_LOADER_USAGE_STATS:
- return Permissions.setAppOpPackageMode(packageName, appOp, mode, context);
+ return Permissions.setAppOpPackageModeAsUser(packageName, appOp, mode, user,
+ context);
case AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// We fixed OP_INTERACT_ACROSS_PROFILES to use UID mode on S and backported it
// to R, but still, we might have an out-of-date platform or an upgraded
// platform with old state.
boolean changed = false;
- changed |= Permissions.setAppOpUidMode(packageName, appOp, mode, context);
- changed |= Permissions.setAppOpPackageMode(packageName, appOp,
- Permissions.getDefaultAppOpMode(appOp), context);
+ changed |= Permissions.setAppOpUidModeAsUser(packageName, appOp, mode, user,
+ context);
+ changed |= Permissions.setAppOpPackageModeAsUser(packageName, appOp,
+ Permissions.getDefaultAppOpMode(appOp), user, context);
return changed;
} else {
- return Permissions.setAppOpPackageMode(packageName, appOp, mode, context);
+ return Permissions.setAppOpPackageModeAsUser(packageName, appOp, mode, user,
+ context);
}
default:
- return Permissions.setAppOpUidMode(packageName, appOp, mode, context);
+ return Permissions.setAppOpUidModeAsUser(packageName, appOp, mode, user, context);
}
}
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/Permission.java b/PermissionController/role-controller/java/com/android/role/controller/model/Permission.java
index 0c4a14574..6ded32d58 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/Permission.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/Permission.java
@@ -60,14 +60,29 @@ public class Permission {
* @return whether this permission is available
*/
public boolean isAvailable() {
- // Workaround to match the value 34+ for U+ in roles.xml before SDK finalization.
- if (mMinSdkVersion >= 34) {
- return SdkLevel.isAtLeastU();
+ // Workaround to match the value 35+ for V+ in roles.xml before SDK finalization.
+ if (mMinSdkVersion >= 35) {
+ return SdkLevel.isAtLeastV();
} else {
return Build.VERSION.SDK_INT >= mMinSdkVersion;
}
}
+ /**
+ * Return a new permission with the specified minimum SDK version, or this permission if it
+ * already has the same minimum SDK version.
+ *
+ * @param minSdkVersion the minimum SDK version
+ * @return a permission with the specified minimum SDK version
+ */
+ @NonNull
+ public Permission withMinSdkVersion(int minSdkVersion) {
+ if (mMinSdkVersion == minSdkVersion) {
+ return this;
+ }
+ return new Permission(mName, minSdkVersion);
+ }
+
@Override
public String toString() {
return "Permission{"
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/Permissions.java b/PermissionController/role-controller/java/com/android/role/controller/model/Permissions.java
index f55a84c07..8a15612b9 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/Permissions.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/Permissions.java
@@ -24,7 +24,6 @@ import android.content.pm.PackageManager;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.os.Build;
-import android.os.Process;
import android.os.UserHandle;
import android.permission.PermissionManager;
import android.util.ArrayMap;
@@ -37,6 +36,7 @@ import androidx.annotation.Nullable;
import com.android.role.controller.util.ArrayUtils;
import com.android.role.controller.util.CollectionUtils;
import com.android.role.controller.util.PackageUtils;
+import com.android.role.controller.util.UserUtils;
import java.util.ArrayList;
import java.util.List;
@@ -89,6 +89,7 @@ public class Permissions {
* @param setGrantedByRole whether the permissions will be granted as granted-by-role
* @param setGrantedByDefault whether the permissions will be granted as granted-by-default
* @param setSystemFixed whether the permissions will be granted as system-fixed
+ * @param user the user of the application
* @param context the {@code Context} to retrieve system services
*
* @return whether any permission or app op changed
@@ -96,16 +97,16 @@ public class Permissions {
* @see com.android.server.pm.permission.DefaultPermissionGrantPolicy#grantRuntimePermissions(
* PackageInfo, java.util.Set, boolean, boolean, int)
*/
- public static boolean grant(@NonNull String packageName, @NonNull List<String> permissions,
- boolean overrideDisabledSystemPackage, boolean overrideUserSetAndFixed,
- boolean setGrantedByRole, boolean setGrantedByDefault, boolean setSystemFixed,
- @NonNull Context context) {
+ public static boolean grantAsUser(@NonNull String packageName,
+ @NonNull List<String> permissions, boolean overrideDisabledSystemPackage,
+ boolean overrideUserSetAndFixed, boolean setGrantedByRole, boolean setGrantedByDefault,
+ boolean setSystemFixed, @NonNull UserHandle user, @NonNull Context context) {
if (setGrantedByRole == setGrantedByDefault) {
throw new IllegalArgumentException("Permission must be either granted by role, or"
+ " granted by default, but not both");
}
- PackageInfo packageInfo = getPackageInfo(packageName, context);
+ PackageInfo packageInfo = getPackageInfoAsUser(packageName, user, context);
if (packageInfo == null) {
return false;
}
@@ -142,7 +143,8 @@ public class Permissions {
// apps, (default grants on first boot and user creation) we don't grant default
// permissions if the version on the system image does not declare them.
if (!overrideDisabledSystemPackage && isUpdatedSystemApp(packageInfo)) {
- PackageInfo disabledSystemPackageInfo = getFactoryPackageInfo(packageName, context);
+ PackageInfo disabledSystemPackageInfo = getFactoryPackageInfoAsUser(packageName, user,
+ context);
if (disabledSystemPackageInfo != null) {
if (ArrayUtils.isEmpty(disabledSystemPackageInfo.requestedPermissions)) {
return false;
@@ -176,9 +178,10 @@ public class Permissions {
boolean permissionOrAppOpChanged = false;
- PackageManager packageManager = context.getPackageManager();
+ Context userContext = UserUtils.getUserContext(context, user);
+ PackageManager userPackageManager = userContext.getPackageManager();
Set<String> whitelistedRestrictedPermissions = new ArraySet<>(
- packageManager.getWhitelistedRestrictedPermissions(packageName,
+ userPackageManager.getWhitelistedRestrictedPermissions(packageName,
PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM));
int sortedPermissionsToGrantLength = sortedPermissionsToGrant.length;
@@ -187,24 +190,26 @@ public class Permissions {
if (isRestrictedPermission(permission, context)
&& whitelistedRestrictedPermissions.add(permission)) {
- packageManager.addWhitelistedRestrictedPermission(packageName, permission,
+ userPackageManager.addWhitelistedRestrictedPermission(packageName, permission,
PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM);
}
- permissionOrAppOpChanged |= grantSingle(packageName, permission,
+ permissionOrAppOpChanged |= grantSingleAsUser(packageName, permission,
overrideUserSetAndFixed, setGrantedByRole, setGrantedByDefault, setSystemFixed,
- context);
+ user, context);
}
return permissionOrAppOpChanged;
}
- private static boolean grantSingle(@NonNull String packageName, @NonNull String permission,
- boolean overrideUserSetAndFixed, boolean setGrantedByRole, boolean setGrantedByDefault,
- boolean setSystemFixed, @NonNull Context context) {
- boolean wasPermissionOrAppOpGranted = isPermissionAndAppOpGranted(packageName, permission,
- context);
- if (isPermissionFixed(packageName, permission, false, overrideUserSetAndFixed, context)
+ private static boolean grantSingleAsUser(@NonNull String packageName,
+ @NonNull String permission, boolean overrideUserSetAndFixed, boolean setGrantedByRole,
+ boolean setGrantedByDefault, boolean setSystemFixed, @NonNull UserHandle user,
+ @NonNull Context context) {
+ boolean wasPermissionOrAppOpGranted = isPermissionAndAppOpGrantedAsUser(packageName,
+ permission, user, context);
+ if (isPermissionFixedAsUser(packageName, permission, false,
+ overrideUserSetAndFixed, user, context)
&& !wasPermissionOrAppOpGranted) {
// Stop granting if this permission is fixed to revoked.
return false;
@@ -217,7 +222,8 @@ public class Permissions {
for (int i = 0; i < foregroundPermissionsSize; i++) {
String foregroundPermission = foregroundPermissions.get(i);
- if (isPermissionAndAppOpGranted(packageName, foregroundPermission, context)) {
+ if (isPermissionAndAppOpGrantedAsUser(packageName, foregroundPermission, user,
+ context)) {
isAnyForegroundPermissionGranted = true;
break;
}
@@ -230,8 +236,8 @@ public class Permissions {
}
}
- boolean permissionOrAppOpChanged = grantPermissionAndAppOp(packageName, permission,
- context);
+ boolean permissionOrAppOpChanged = grantPermissionAndAppOpAsUser(packageName, permission,
+ user, context);
// Update permission flags.
int newFlags = 0;
@@ -254,7 +260,7 @@ public class Permissions {
// If a component gets a permission for being the default handler A and also default handler
// B, we grant the weaker grant form. This only applies to default permission grant.
if (setGrantedByDefault && !setSystemFixed) {
- int oldFlags = getPermissionFlags(packageName, permission, context);
+ int oldFlags = getPermissionFlagsAsUser(packageName, permission, user, context);
if ((oldFlags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0
&& (oldFlags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
if (DEBUG) {
@@ -265,20 +271,22 @@ public class Permissions {
}
}
- setPermissionFlags(packageName, permission, newFlags, newMask, context);
+ setPermissionFlagsAsUser(packageName, permission, newFlags, newMask,
+ user, context);
return permissionOrAppOpChanged;
}
- private static boolean isPermissionAndAppOpGranted(@NonNull String packageName,
- @NonNull String permission, @NonNull Context context) {
+ private static boolean isPermissionAndAppOpGrantedAsUser(@NonNull String packageName,
+ @NonNull String permission, @NonNull UserHandle user, @NonNull Context context) {
// Check this permission.
- if (!isPermissionGrantedWithoutCheckingAppOp(packageName, permission, context)) {
+ if (!isPermissionGrantedWithoutCheckingAppOpAsUser(packageName, permission, user,
+ context)) {
return false;
}
// Check if the permission is review required.
- if (isPermissionReviewRequired(packageName, permission, context)) {
+ if (isPermissionReviewRequiredAsUser(packageName, permission, user, context)) {
return false;
}
@@ -288,7 +296,7 @@ public class Permissions {
if (appOp == null) {
return true;
}
- Integer appOpMode = getAppOpMode(packageName, appOp, context);
+ Integer appOpMode = getAppOpModeAsUser(packageName, appOp, user, context);
if (appOpMode == null) {
return false;
}
@@ -314,7 +322,8 @@ public class Permissions {
if (foregroundAppOp == null) {
continue;
}
- Integer foregroundAppOpMode = getAppOpMode(packageName, foregroundAppOp, context);
+ Integer foregroundAppOpMode = getAppOpModeAsUser(packageName, foregroundAppOp,
+ user, context);
if (foregroundAppOpMode == null) {
continue;
}
@@ -326,11 +335,11 @@ public class Permissions {
}
}
- private static boolean grantPermissionAndAppOp(@NonNull String packageName,
- @NonNull String permission, @NonNull Context context) {
+ private static boolean grantPermissionAndAppOpAsUser(@NonNull String packageName,
+ @NonNull String permission, @NonNull UserHandle user, @NonNull Context context) {
// Grant the permission.
- boolean permissionOrAppOpChanged = grantPermissionWithoutAppOp(packageName, permission,
- context);
+ boolean permissionOrAppOpChanged = grantPermissionWithoutAppOpAsUser(packageName,
+ permission, user, context);
// Grant the app op.
if (!isBackgroundPermission(permission, context)) {
@@ -345,13 +354,15 @@ public class Permissions {
// This permission is a foreground permission, set its app op mode according to
// whether its background permission is granted.
String backgroundPermission = getBackgroundPermission(permission, context);
- if (!isPermissionAndAppOpGranted(packageName, backgroundPermission, context)) {
+ if (!isPermissionAndAppOpGrantedAsUser(packageName, backgroundPermission,
+ user, context)) {
appOpMode = AppOpsManager.MODE_FOREGROUND;
} else {
appOpMode = AppOpsManager.MODE_ALLOWED;
}
}
- permissionOrAppOpChanged |= setAppOpUidMode(packageName, appOp, appOpMode, context);
+ permissionOrAppOpChanged |= setAppOpUidModeAsUser(packageName, appOp, appOpMode,
+ user, context);
}
} else {
// This permission is a background permission, set all its foreground permissions' app
@@ -365,8 +376,8 @@ public class Permissions {
if (foregroundAppOp == null) {
continue;
}
- permissionOrAppOpChanged |= setAppOpUidMode(packageName, foregroundAppOp,
- AppOpsManager.MODE_ALLOWED, context);
+ permissionOrAppOpChanged |= setAppOpUidModeAsUser(packageName, foregroundAppOp,
+ AppOpsManager.MODE_ALLOWED, user, context);
}
}
@@ -382,16 +393,18 @@ public class Permissions {
* @param onlyIfGrantedByDefault revoke the permission only if it is granted by default
* @param overrideSystemFixed whether system-fixed permissions can be revoked
* @param context the {@code Context} to retrieve system services
+ * @param user the user of the application
*
* @return whether any permission or app op changed
*
* @see com.android.server.pm.permission.DefaultPermissionGrantPolicy#revokeRuntimePermissions(
* String, java.util.Set, boolean, int)
*/
- public static boolean revoke(@NonNull String packageName, @NonNull List<String> permissions,
- boolean onlyIfGrantedByRole, boolean onlyIfGrantedByDefault,
- boolean overrideSystemFixed, @NonNull Context context) {
- PackageInfo packageInfo = getPackageInfo(packageName, context);
+ public static boolean revokeAsUser(@NonNull String packageName,
+ @NonNull List<String> permissions, boolean onlyIfGrantedByRole,
+ boolean onlyIfGrantedByDefault, boolean overrideSystemFixed, @NonNull UserHandle user,
+ @NonNull Context context) {
+ PackageInfo packageInfo = getPackageInfoAsUser(packageName, user, context);
if (packageInfo == null) {
return false;
}
@@ -425,9 +438,10 @@ public class Permissions {
}
}
- PackageManager packageManager = context.getPackageManager();
+ Context userContext = UserUtils.getUserContext(context, user);
+ PackageManager userPackageManager = userContext.getPackageManager();
Set<String> whitelistedRestrictedPermissions =
- packageManager.getWhitelistedRestrictedPermissions(packageName,
+ userPackageManager.getWhitelistedRestrictedPermissions(packageName,
PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
| PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
| PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
@@ -438,13 +452,14 @@ public class Permissions {
for (int i = 0; i < sortedPermissionsToRevokeLength; i++) {
String permission = sortedPermissionsToRevoke[i];
- permissionOrAppOpChanged |= revokeSingle(packageName, permission, onlyIfGrantedByRole,
- onlyIfGrantedByDefault, overrideSystemFixed, context);
+ permissionOrAppOpChanged |= revokeSingleAsUser(packageName, permission,
+ onlyIfGrantedByRole, onlyIfGrantedByDefault, overrideSystemFixed, user,
+ context);
// Remove from the system whitelist only if not granted by default.
- if (!isPermissionGrantedByDefault(packageName, permission, context)
+ if (!isPermissionGrantedByDefaultAsUser(packageName, permission, user, context)
&& whitelistedRestrictedPermissions.remove(permission)) {
- packageManager.removeWhitelistedRestrictedPermission(packageName, permission,
+ userPackageManager.removeWhitelistedRestrictedPermission(packageName, permission,
PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM);
}
}
@@ -452,59 +467,62 @@ public class Permissions {
return permissionOrAppOpChanged;
}
- private static boolean revokeSingle(@NonNull String packageName, @NonNull String permission,
- boolean onlyIfGrantedByRole, boolean onlyIfGrantedByDefault,
- boolean overrideSystemFixed, @NonNull Context context) {
+ private static boolean revokeSingleAsUser(@NonNull String packageName,
+ @NonNull String permission, boolean onlyIfGrantedByRole, boolean onlyIfGrantedByDefault,
+ boolean overrideSystemFixed, @NonNull UserHandle user, @NonNull Context context) {
if (onlyIfGrantedByRole == onlyIfGrantedByDefault) {
throw new IllegalArgumentException("Permission can be revoked only if either granted by"
+ " role, or granted by default, but not both");
}
if (onlyIfGrantedByRole) {
- if (!isPermissionGrantedByRole(packageName, permission, context)) {
+ if (!isPermissionGrantedByRoleAsUser(packageName, permission, user, context)) {
return false;
}
- setPermissionFlags(packageName, permission, 0,
- PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE, context);
+ setPermissionFlagsAsUser(packageName, permission, 0,
+ PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE, user, context);
}
if (onlyIfGrantedByDefault) {
- if (!isPermissionGrantedByDefault(packageName, permission, context)) {
+ if (!isPermissionGrantedByDefaultAsUser(packageName, permission, user, context)) {
return false;
}
// Remove the granted-by-default permission flag.
- setPermissionFlags(packageName, permission, 0,
- PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, context);
+ setPermissionFlagsAsUser(packageName, permission, 0,
+ PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, user, context);
// Note that we do not revoke FLAG_PERMISSION_SYSTEM_FIXED. That bit remains sticky once
// set.
}
- if (isPermissionFixed(packageName, permission, overrideSystemFixed, false, context)
- && isPermissionAndAppOpGranted(packageName, permission, context)) {
+ if (isPermissionFixedAsUser(packageName, permission, overrideSystemFixed, false,
+ user, context)
+ && isPermissionAndAppOpGrantedAsUser(packageName, permission, user, context)) {
// Stop revoking if this permission is fixed to granted.
return false;
}
if (isForegroundPermission(permission, context)) {
String backgroundPermission = getBackgroundPermission(permission, context);
- if (isPermissionAndAppOpGranted(packageName, backgroundPermission, context)) {
+ if (isPermissionAndAppOpGrantedAsUser(packageName, backgroundPermission, user,
+ context)) {
// Stop revoking if this foreground permission has a granted background permission.
return false;
}
}
- return revokePermissionAndAppOp(packageName, permission, context);
+ return revokePermissionAndAppOpAsUser(packageName, permission, user, context);
}
- private static boolean revokePermissionAndAppOp(@NonNull String packageName,
- @NonNull String permission, @NonNull Context context) {
+ private static boolean revokePermissionAndAppOpAsUser(@NonNull String packageName,
+ @NonNull String permission, @NonNull UserHandle user, @NonNull Context context) {
boolean permissionOrAppOpChanged = false;
- boolean isRuntimePermissionsSupported = isRuntimePermissionsSupported(packageName, context);
+ boolean isRuntimePermissionsSupported = isRuntimePermissionsSupportedAsUser(packageName,
+ user, context);
if (isRuntimePermissionsSupported) {
// Revoke the permission.
- permissionOrAppOpChanged |= revokePermissionWithoutAppOp(packageName, permission,
- context);
+ permissionOrAppOpChanged |= revokePermissionWithoutAppOpAsUser(packageName, permission,
+ user, context);
}
// Revoke the app op.
@@ -514,7 +532,8 @@ public class Permissions {
// This permission is an ordinary or foreground permission, reset its app op mode to
// default.
int appOpMode = getDefaultAppOpMode(appOp);
- boolean appOpModeChanged = setAppOpUidMode(packageName, appOp, appOpMode, context);
+ boolean appOpModeChanged = setAppOpUidModeAsUser(packageName, appOp, appOpMode,
+ user, context);
permissionOrAppOpChanged |= appOpModeChanged;
if (appOpModeChanged) {
@@ -523,9 +542,9 @@ public class Permissions {
|| appOpMode == AppOpsManager.MODE_ALLOWED)) {
// We've reset this permission's app op mode to be permissive, so we'll need
// the user to review it again.
- setPermissionFlags(packageName, permission,
+ setPermissionFlagsAsUser(packageName, permission,
PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED,
- PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, context);
+ PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, user, context);
}
}
}
@@ -537,7 +556,8 @@ public class Permissions {
for (int i = 0; i < foregroundPermissionsSize; i++) {
String foregroundPermission = foregroundPermissions.get(i);
- if (!isPermissionAndAppOpGranted(packageName, foregroundPermission, context)) {
+ if (!isPermissionAndAppOpGrantedAsUser(packageName, foregroundPermission, user,
+ context)) {
continue;
}
@@ -545,8 +565,8 @@ public class Permissions {
if (foregroundAppOp == null) {
continue;
}
- permissionOrAppOpChanged |= setAppOpUidMode(packageName, foregroundAppOp,
- AppOpsManager.MODE_FOREGROUND, context);
+ permissionOrAppOpChanged |= setAppOpUidModeAsUser(packageName, foregroundAppOp,
+ AppOpsManager.MODE_FOREGROUND, user, context);
}
}
@@ -554,24 +574,25 @@ public class Permissions {
}
@Nullable
- private static PackageInfo getPackageInfo(@NonNull String packageName,
- @NonNull Context context) {
- return getPackageInfo(packageName, 0, context);
+ private static PackageInfo getPackageInfoAsUser(@NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ return getPackageInfoAsUser(packageName, 0, user, context);
}
@Nullable
- private static PackageInfo getFactoryPackageInfo(@NonNull String packageName,
- @NonNull Context context) {
- return getPackageInfo(packageName, PackageManager.MATCH_FACTORY_ONLY, context);
+ private static PackageInfo getFactoryPackageInfoAsUser(@NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ return getPackageInfoAsUser(packageName, PackageManager.MATCH_FACTORY_ONLY,
+ user, context);
}
@Nullable
- private static PackageInfo getPackageInfo(@NonNull String packageName, int extraFlags,
- @NonNull Context context) {
- return PackageUtils.getPackageInfo(packageName, extraFlags
+ private static PackageInfo getPackageInfoAsUser(@NonNull String packageName, int extraFlags,
+ @NonNull UserHandle user, @NonNull Context context) {
+ return PackageUtils.getPackageInfoAsUser(packageName, extraFlags
// TODO: Why MATCH_UNINSTALLED_PACKAGES?
| PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_PERMISSIONS,
- context);
+ user, context);
}
private static boolean isUpdatedSystemApp(@NonNull PackageInfo packageInfo) {
@@ -579,27 +600,26 @@ public class Permissions {
& ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
}
- static boolean isRuntimePermissionsSupported(@NonNull String packageName,
- @NonNull Context context) {
- ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName,
- Process.myUserHandle(), context);
+ static boolean isRuntimePermissionsSupportedAsUser(@NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName, user,
+ context);
if (applicationInfo == null) {
return false;
}
return applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M;
}
- private static int getPermissionFlags(@NonNull String packageName, @NonNull String permission,
- @NonNull Context context) {
+ private static int getPermissionFlagsAsUser(@NonNull String packageName,
+ @NonNull String permission, @NonNull UserHandle user, @NonNull Context context) {
PackageManager packageManager = context.getPackageManager();
- UserHandle user = Process.myUserHandle();
return packageManager.getPermissionFlags(permission, packageName, user);
}
- private static boolean isPermissionFixed(@NonNull String packageName,
+ private static boolean isPermissionFixedAsUser(@NonNull String packageName,
@NonNull String permission, boolean overrideSystemFixed,
- boolean overrideUserSetAndFixed, @NonNull Context context) {
- int flags = getPermissionFlags(packageName, permission, context);
+ boolean overrideUserSetAndFixed, @NonNull UserHandle user, @NonNull Context context) {
+ int flags = getPermissionFlagsAsUser(packageName, permission, user, context);
int fixedFlags = PackageManager.FLAG_PERMISSION_POLICY_FIXED;
if (!overrideSystemFixed) {
fixedFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
@@ -611,67 +631,69 @@ public class Permissions {
return (flags & fixedFlags) != 0;
}
- private static boolean isPermissionGrantedByDefault(@NonNull String packageName,
- @NonNull String permission, @NonNull Context context) {
- int flags = getPermissionFlags(packageName, permission, context);
+ private static boolean isPermissionGrantedByDefaultAsUser(@NonNull String packageName,
+ @NonNull String permission, @NonNull UserHandle user, @NonNull Context context) {
+ int flags = getPermissionFlagsAsUser(packageName, permission, user, context);
return (flags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0;
}
- static boolean isPermissionGrantedByRole(@NonNull String packageName,
- @NonNull String permission, @NonNull Context context) {
- int flags = getPermissionFlags(packageName, permission, context);
+ static boolean isPermissionGrantedByRoleAsUser(@NonNull String packageName,
+ @NonNull String permission, @NonNull UserHandle user, @NonNull Context context) {
+ int flags = getPermissionFlagsAsUser(packageName, permission, user, context);
return (flags & PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE) != 0;
}
- private static boolean isPermissionReviewRequired(@NonNull String packageName,
- @NonNull String permission, @NonNull Context context) {
- int flags = getPermissionFlags(packageName, permission, context);
+ private static boolean isPermissionReviewRequiredAsUser(@NonNull String packageName,
+ @NonNull String permission, @NonNull UserHandle user, @NonNull Context context) {
+ int flags = getPermissionFlagsAsUser(packageName, permission, user, context);
return (flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0;
}
- private static void setPermissionFlags(@NonNull String packageName, @NonNull String permission,
- int flags, int mask, @NonNull Context context) {
+ private static void setPermissionFlagsAsUser(@NonNull String packageName,
+ @NonNull String permission, int flags, int mask, @NonNull UserHandle user,
+ @NonNull Context context) {
PackageManager packageManager = context.getPackageManager();
- UserHandle user = Process.myUserHandle();
packageManager.updatePermissionFlags(permission, packageName, mask, flags, user);
}
- static void setPermissionGrantedByRole(@NonNull String packageName,
- @NonNull String permission, boolean grantedByRole, @NonNull Context context) {
- setPermissionFlags(packageName, permission,
+ static void setPermissionGrantedByRoleAsUser(@NonNull String packageName,
+ @NonNull String permission, boolean grantedByRole, @NonNull UserHandle user,
+ @NonNull Context context) {
+ setPermissionFlagsAsUser(packageName, permission,
grantedByRole ? PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE : 0,
- PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE, context);
+ PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE, user, context);
}
/**
* Most of the time {@link #isPermissionAndAppOpGranted(String, String, Context)} should be used
* instead.
*/
- private static boolean isPermissionGrantedWithoutCheckingAppOp(@NonNull String packageName,
- @NonNull String permission, @NonNull Context context) {
- PackageManager packageManager = context.getPackageManager();
- return packageManager.checkPermission(permission, packageName)
+ private static boolean isPermissionGrantedWithoutCheckingAppOpAsUser(
+ @NonNull String packageName, @NonNull String permission, @NonNull UserHandle user,
+ @NonNull Context context) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ PackageManager userPackageManager = userContext.getPackageManager();
+ return userPackageManager.checkPermission(permission, packageName)
== PackageManager.PERMISSION_GRANTED;
}
- private static boolean grantPermissionWithoutAppOp(@NonNull String packageName,
- @NonNull String permission, @NonNull Context context) {
- if (isPermissionGrantedWithoutCheckingAppOp(packageName, permission, context)) {
+ private static boolean grantPermissionWithoutAppOpAsUser(@NonNull String packageName,
+ @NonNull String permission, @NonNull UserHandle user, @NonNull Context context) {
+ if (isPermissionGrantedWithoutCheckingAppOpAsUser(packageName, permission, user, context)) {
return false;
}
PackageManager packageManager = context.getPackageManager();
- UserHandle user = Process.myUserHandle();
packageManager.grantRuntimePermission(packageName, permission, user);
return true;
}
- private static boolean revokePermissionWithoutAppOp(@NonNull String packageName,
- @NonNull String permission, @NonNull Context context) {
- if (!isPermissionGrantedWithoutCheckingAppOp(packageName, permission, context)) {
+ private static boolean revokePermissionWithoutAppOpAsUser(@NonNull String packageName,
+ @NonNull String permission, @NonNull UserHandle user, @NonNull Context context) {
+ if (!isPermissionGrantedWithoutCheckingAppOpAsUser(packageName, permission, user,
+ context)) {
return false;
}
PackageManager packageManager = context.getPackageManager();
- UserHandle user = Process.myUserHandle();
packageManager.revokeRuntimePermission(packageName, permission, user);
return true;
}
@@ -816,10 +838,10 @@ public class Permissions {
}
@Nullable
- static Integer getAppOpMode(@NonNull String packageName, @NonNull String appOp,
- @NonNull Context context) {
+ static Integer getAppOpModeAsUser(@NonNull String packageName, @NonNull String appOp,
+ @NonNull UserHandle user, @NonNull Context context) {
ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName,
- Process.myUserHandle(), context);
+ user, context);
if (applicationInfo == null) {
return null;
}
@@ -831,24 +853,24 @@ public class Permissions {
return AppOpsManager.opToDefaultMode(appOp);
}
- static boolean setAppOpUidMode(@NonNull String packageName, @NonNull String appOp, int mode,
- @NonNull Context context) {
- return setAppOpMode(packageName, appOp, mode, true, context);
+ static boolean setAppOpUidModeAsUser(@NonNull String packageName, @NonNull String appOp,
+ int mode, @NonNull UserHandle user, @NonNull Context context) {
+ return setAppOpModeAsUser(packageName, appOp, mode, true, user, context);
}
- static boolean setAppOpPackageMode(@NonNull String packageName, @NonNull String appOp, int mode,
- @NonNull Context context) {
- return setAppOpMode(packageName, appOp, mode, false, context);
+ static boolean setAppOpPackageModeAsUser(@NonNull String packageName, @NonNull String appOp,
+ int mode, @NonNull UserHandle user, @NonNull Context context) {
+ return setAppOpModeAsUser(packageName, appOp, mode, false, user, context);
}
- private static boolean setAppOpMode(@NonNull String packageName, @NonNull String appOp,
- int mode, boolean setUidMode, @NonNull Context context) {
- Integer currentMode = getAppOpMode(packageName, appOp, context);
+ private static boolean setAppOpModeAsUser(@NonNull String packageName, @NonNull String appOp,
+ int mode, boolean setUidMode, @NonNull UserHandle user, @NonNull Context context) {
+ Integer currentMode = getAppOpModeAsUser(packageName, appOp, user, context);
if (currentMode != null && currentMode == mode) {
return false;
}
- ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName,
- Process.myUserHandle(), context);
+ ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName, user,
+ context);
if (applicationInfo == null) {
Log.e(LOG_TAG, "Cannot get ApplicationInfo for package to set app op mode: "
+ packageName);
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/PreferredActivity.java b/PermissionController/role-controller/java/com/android/role/controller/model/PreferredActivity.java
index 5b9c22b67..7ea7de046 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/PreferredActivity.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/PreferredActivity.java
@@ -22,9 +22,12 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
import androidx.annotation.NonNull;
+import com.android.role.controller.util.UserUtils;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -67,18 +70,21 @@ public class PreferredActivity {
* Configure this preferred activity specification for an application.
*
* @param packageName the package name of the application
+ * @param user the user of the application
* @param context the {@code Context} to retrieve system services
*/
- public void configure(@NonNull String packageName, @NonNull Context context) {
- ComponentName packageActivity = mActivity.getQualifyingComponentForPackage(
- packageName, context);
+ public void configureAsUser(@NonNull String packageName, @NonNull UserHandle user,
+ @NonNull Context context) {
+ ComponentName packageActivity = mActivity.getQualifyingComponentForPackageAsUser(
+ packageName, user, context);
if (packageActivity == null) {
// We might be running into some race condition here, but we can't do anything about it.
// This should be handled by a future reconciliation started by the package change.
return;
}
- PackageManager packageManager = context.getPackageManager();
+ Context userContext = UserUtils.getUserContext(context, user);
+ PackageManager userPackageManager = userContext.getPackageManager();
int intentFilterDatasSize = mIntentFilterDatas.size();
for (int i = 0; i < intentFilterDatasSize; i++) {
IntentFilterData intentFilterData = mIntentFilterDatas.get(i);
@@ -92,7 +98,7 @@ public class PreferredActivity {
? IntentFilter.MATCH_CATEGORY_SCHEME : IntentFilter.MATCH_CATEGORY_EMPTY;
Intent intent = intentFilterData.createIntent();
- List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(intent,
+ List<ResolveInfo> resolveInfos = userPackageManager.queryIntentActivities(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_DEFAULT_ONLY);
@@ -107,7 +113,7 @@ public class PreferredActivity {
set.add(componentName);
}
- packageManager.replacePreferredActivity(intentFilter, match, set, packageActivity);
+ userPackageManager.replacePreferredActivity(intentFilter, match, set, packageActivity);
}
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredActivity.java b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredActivity.java
index 58c878e56..25c97aefb 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredActivity.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredActivity.java
@@ -16,12 +16,11 @@
package com.android.role.controller.model;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.os.Bundle;
import android.os.UserHandle;
import androidx.annotation.NonNull;
@@ -52,11 +51,15 @@ public class RequiredActivity extends RequiredComponent {
return userPackageManager.queryIntentActivities(intent, flags);
}
+ @Override
+ protected boolean isComponentQualified(@NonNull ResolveInfo resolveInfo) {
+ return resolveInfo.activityInfo.exported;
+ }
+
@NonNull
@Override
- protected ComponentName getComponentComponentName(@NonNull ResolveInfo resolveInfo) {
- return new ComponentName(resolveInfo.activityInfo.packageName,
- resolveInfo.activityInfo.name);
+ protected ComponentInfo getComponentComponentInfo(@NonNull ResolveInfo resolveInfo) {
+ return resolveInfo.activityInfo;
}
@Override
@@ -69,10 +72,4 @@ public class RequiredActivity extends RequiredComponent {
protected String getComponentPermission(@NonNull ResolveInfo resolveInfo) {
return resolveInfo.activityInfo.permission;
}
-
- @Nullable
- @Override
- protected Bundle getComponentMetaData(@NonNull ResolveInfo resolveInfo) {
- return resolveInfo.activityInfo.metaData;
- }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredBroadcastReceiver.java b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredBroadcastReceiver.java
index 945fda3c3..1e23af256 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredBroadcastReceiver.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredBroadcastReceiver.java
@@ -16,12 +16,11 @@
package com.android.role.controller.model;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.os.Bundle;
import android.os.UserHandle;
import androidx.annotation.NonNull;
@@ -53,9 +52,8 @@ public class RequiredBroadcastReceiver extends RequiredComponent {
@NonNull
@Override
- protected ComponentName getComponentComponentName(@NonNull ResolveInfo resolveInfo) {
- return new ComponentName(resolveInfo.activityInfo.packageName,
- resolveInfo.activityInfo.name);
+ protected ComponentInfo getComponentComponentInfo(@NonNull ResolveInfo resolveInfo) {
+ return resolveInfo.activityInfo;
}
@Override
@@ -68,10 +66,4 @@ public class RequiredBroadcastReceiver extends RequiredComponent {
protected String getComponentPermission(@NonNull ResolveInfo resolveInfo) {
return resolveInfo.activityInfo.permission;
}
-
- @Nullable
- @Override
- protected Bundle getComponentMetaData(@NonNull ResolveInfo resolveInfo) {
- return resolveInfo.activityInfo.metaData;
- }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredComponent.java b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredComponent.java
index ae6156e7f..6e067488c 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredComponent.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredComponent.java
@@ -20,11 +20,11 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Bundle;
-import android.os.Process;
import android.os.UserHandle;
import android.util.ArraySet;
@@ -108,9 +108,9 @@ public abstract class RequiredComponent {
* @return whether this required component is available
*/
public boolean isAvailable() {
- // Workaround to match the value 34+ for U+ in roles.xml before SDK finalization.
- if (mMinTargetSdkVersion >= 34) {
- return SdkLevel.isAtLeastU();
+ // Workaround to match the value 35+ for V+ in roles.xml before SDK finalization.
+ if (mMinTargetSdkVersion >= 35) {
+ return SdkLevel.isAtLeastV();
} else {
return Build.VERSION.SDK_INT >= mMinTargetSdkVersion;
}
@@ -144,15 +144,16 @@ public abstract class RequiredComponent {
* Get the component that matches this required component within a package, if any.
*
* @param packageName the package name for this query
+ * @param user the user of the component
* @param context the {@code Context} to retrieve system services
*
* @return the matching component, or {@code null} if none.
*/
@Nullable
- public ComponentName getQualifyingComponentForPackage(@NonNull String packageName,
- @NonNull Context context) {
- List<ComponentName> componentNames = getQualifyingComponentsInternal(packageName,
- Process.myUserHandle(), context);
+ public ComponentName getQualifyingComponentForPackageAsUser(@NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ List<ComponentName> componentNames = getQualifyingComponentsAsUserInternal(packageName,
+ user, context);
return !componentNames.isEmpty() ? componentNames.get(0) : null;
}
@@ -170,11 +171,11 @@ public abstract class RequiredComponent {
@NonNull
public List<ComponentName> getQualifyingComponentsAsUser(@NonNull UserHandle user,
@NonNull Context context) {
- return getQualifyingComponentsInternal(null, user, context);
+ return getQualifyingComponentsAsUserInternal(null, user, context);
}
@NonNull
- private List<ComponentName> getQualifyingComponentsInternal(@Nullable String packageName,
+ private List<ComponentName> getQualifyingComponentsAsUserInternal(@Nullable String packageName,
@NonNull UserHandle user, @NonNull Context context) {
Intent intent = mIntentFilterData.createIntent();
if (packageName != null) {
@@ -195,6 +196,10 @@ public abstract class RequiredComponent {
for (int resolveInfosIndex = 0; resolveInfosIndex < resolveInfosSize; resolveInfosIndex++) {
ResolveInfo resolveInfo = resolveInfos.get(resolveInfosIndex);
+ if (!isComponentQualified(resolveInfo)) {
+ continue;
+ }
+
if (mFlags != 0) {
int componentFlags = getComponentFlags(resolveInfo);
if ((componentFlags & mFlags) != mFlags) {
@@ -209,8 +214,9 @@ public abstract class RequiredComponent {
}
}
+ ComponentInfo componentInfo = getComponentComponentInfo(resolveInfo);
if (hasMetaData) {
- Bundle componentMetaData = getComponentMetaData(resolveInfo);
+ Bundle componentMetaData = componentInfo.metaData;
if (componentMetaData == null) {
componentMetaData = Bundle.EMPTY;
}
@@ -229,13 +235,14 @@ public abstract class RequiredComponent {
}
}
- ComponentName componentName = getComponentComponentName(resolveInfo);
- String componentPackageName = componentName.getPackageName();
+ String componentPackageName = componentInfo.packageName;
if (componentPackageNames.contains(componentPackageName)) {
continue;
}
-
componentPackageNames.add(componentPackageName);
+
+ ComponentName componentName = new ComponentName(componentPackageName,
+ componentInfo.name);
componentNames.add(componentName);
}
return componentNames;
@@ -256,15 +263,19 @@ public abstract class RequiredComponent {
protected abstract List<ResolveInfo> queryIntentComponentsAsUser(@NonNull Intent intent,
int flags, @NonNull UserHandle user, @NonNull Context context);
+ protected boolean isComponentQualified(@NonNull ResolveInfo resolveInfo) {
+ return true;
+ }
+
/**
- * Get the {@code ComponentName} of a component.
+ * Get the {@code ComponentInfo} of a component.
*
* @param resolveInfo the {@code ResolveInfo} of the component
*
- * @return the {@code ComponentName} of the component
+ * @return the {@code ComponentInfo} of the component
*/
@NonNull
- protected abstract ComponentName getComponentComponentName(@NonNull ResolveInfo resolveInfo);
+ protected abstract ComponentInfo getComponentComponentInfo(@NonNull ResolveInfo resolveInfo);
/**
* Get the flags that have been set on a component.
@@ -285,16 +296,6 @@ public abstract class RequiredComponent {
@Nullable
protected abstract String getComponentPermission(@NonNull ResolveInfo resolveInfo);
- /**
- * Get the meta data associated with a component.
- *
- * @param resolveInfo the {@code ResolveInfo} of the component
- *
- * @return the meta data associated with a component
- */
- @Nullable
- protected abstract Bundle getComponentMetaData(@NonNull ResolveInfo resolveInfo);
-
@Override
public String toString() {
return "RequiredComponent{"
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredContentProvider.java b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredContentProvider.java
index 7b53a25bb..b02062b11 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredContentProvider.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredContentProvider.java
@@ -16,12 +16,11 @@
package com.android.role.controller.model;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.os.Bundle;
import android.os.UserHandle;
import androidx.annotation.NonNull;
@@ -53,9 +52,8 @@ public class RequiredContentProvider extends RequiredComponent {
@NonNull
@Override
- protected ComponentName getComponentComponentName(@NonNull ResolveInfo resolveInfo) {
- return new ComponentName(resolveInfo.providerInfo.packageName,
- resolveInfo.providerInfo.name);
+ protected ComponentInfo getComponentComponentInfo(@NonNull ResolveInfo resolveInfo) {
+ return resolveInfo.providerInfo;
}
@Override
@@ -70,10 +68,4 @@ public class RequiredContentProvider extends RequiredComponent {
//return resolveInfo.providerInfo.readPermission;
throw new UnsupportedOperationException();
}
-
- @Nullable
- @Override
- protected Bundle getComponentMetaData(@NonNull ResolveInfo resolveInfo) {
- return resolveInfo.providerInfo.metaData;
- }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredService.java b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredService.java
index f27aae013..0532e53b2 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredService.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredService.java
@@ -16,12 +16,11 @@
package com.android.role.controller.model;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.os.Bundle;
import android.os.UserHandle;
import androidx.annotation.NonNull;
@@ -53,8 +52,8 @@ public class RequiredService extends RequiredComponent {
@NonNull
@Override
- protected ComponentName getComponentComponentName(@NonNull ResolveInfo resolveInfo) {
- return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
+ protected ComponentInfo getComponentComponentInfo(@NonNull ResolveInfo resolveInfo) {
+ return resolveInfo.serviceInfo;
}
@Override
@@ -67,10 +66,4 @@ public class RequiredService extends RequiredComponent {
protected String getComponentPermission(@NonNull ResolveInfo resolveInfo) {
return resolveInfo.serviceInfo.permission;
}
-
- @Nullable
- @Override
- protected Bundle getComponentMetaData(@NonNull ResolveInfo resolveInfo) {
- return resolveInfo.serviceInfo.metaData;
- }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/Role.java b/PermissionController/role-controller/java/com/android/role/controller/model/Role.java
index 9ff16db0f..6c7eb7d9e 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/Role.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/Role.java
@@ -26,7 +26,6 @@ import android.content.pm.SharedLibraryInfo;
import android.content.pm.Signature;
import android.content.res.Resources;
import android.os.Build;
-import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -360,11 +359,12 @@ public class Role {
/**
* Callback when this role is added to the system for the first time.
*
+ * @param user the user to add the role for
* @param context the {@code Context} to retrieve system services
*/
- public void onRoleAdded(@NonNull Context context) {
+ public void onRoleAddedAsUser(@NonNull UserHandle user, @NonNull Context context) {
if (mBehavior != null) {
- mBehavior.onRoleAdded(this, context);
+ mBehavior.onRoleAddedAsUser(this, user, context);
}
}
@@ -392,26 +392,15 @@ public class Role {
* @return whether this role is available based on SDK version
*/
boolean isAvailableBySdkVersion() {
- // Workaround to match the value 34+ for U+ in roles.xml before SDK finalization.
- if (mMinSdkVersion >= 34) {
- return SdkLevel.isAtLeastU();
+ // Workaround to match the value 35+ for V+ in roles.xml before SDK finalization.
+ if (mMinSdkVersion >= 35) {
+ return SdkLevel.isAtLeastV();
} else {
return Build.VERSION.SDK_INT >= mMinSdkVersion
&& Build.VERSION.SDK_INT <= mMaxSdkVersion;
}
}
- /**
- * Check whether this role is available, for current user.
- *
- * @param context the {@code Context} to retrieve system services
- *
- * @return whether this role is available.
- */
- public boolean isAvailable(@NonNull Context context) {
- return isAvailableAsUser(Process.myUserHandle(), context);
- }
-
public boolean isStatic() {
return mStatic;
}
@@ -420,15 +409,16 @@ public class Role {
* Get the default holders of this role, which will be added when the role is added for the
* first time.
*
+ * @param user the user of the role
* @param context the {@code Context} to retrieve system services
- *
* @return the list of package names of the default holders
*/
@NonNull
- public List<String> getDefaultHolders(@NonNull Context context) {
+ public List<String> getDefaultHoldersAsUser(@NonNull UserHandle user,
+ @NonNull Context context) {
if (mDefaultHoldersResourceName == null) {
if (mBehavior != null) {
- return mBehavior.getDefaultHolders(this, context);
+ return mBehavior.getDefaultHoldersAsUser(this, user, context);
}
return Collections.emptyList();
}
@@ -454,7 +444,8 @@ public class Role {
}
if (isExclusive()) {
- String packageName = getQualifiedDefaultHolderPackageName(defaultHolders, context);
+ String packageName = getQualifiedDefaultHolderPackageNameAsUser(defaultHolders, user,
+ context);
if (packageName == null) {
return Collections.emptyList();
}
@@ -462,7 +453,8 @@ public class Role {
} else {
List<String> packageNames = new ArrayList<>();
for (String defaultHolder : defaultHolders.split(DEFAULT_HOLDER_SEPARATOR)) {
- String packageName = getQualifiedDefaultHolderPackageName(defaultHolder, context);
+ String packageName = getQualifiedDefaultHolderPackageNameAsUser(defaultHolder,
+ user, context);
if (packageName != null) {
packageNames.add(packageName);
}
@@ -472,8 +464,8 @@ public class Role {
}
@Nullable
- private String getQualifiedDefaultHolderPackageName(@NonNull String defaultHolder,
- @NonNull Context context) {
+ private String getQualifiedDefaultHolderPackageNameAsUser(@NonNull String defaultHolder,
+ @NonNull UserHandle user, @NonNull Context context) {
String packageName;
byte[] certificate;
int certificateSeparatorIndex = defaultHolder.indexOf(CERTIFICATE_SEPARATOR);
@@ -492,8 +484,9 @@ public class Role {
}
if (certificate != null) {
- PackageManager packageManager = context.getPackageManager();
- if (!packageManager.hasSigningCertificate(packageName, certificate,
+ Context userContext = UserUtils.getUserContext(context, user);
+ PackageManager userPackageManager = userContext.getPackageManager();
+ if (!userPackageManager.hasSigningCertificate(packageName, certificate,
PackageManager.CERT_INPUT_SHA256)) {
Log.w(LOG_TAG, "Default holder doesn't have required signing certificate: "
+ defaultHolder);
@@ -501,7 +494,7 @@ public class Role {
}
} else {
ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName,
- Process.myUserHandle(), context);
+ user, context);
if (applicationInfo == null) {
Log.w(LOG_TAG, "Cannot get ApplicationInfo for default holder: " + packageName);
return null;
@@ -521,20 +514,20 @@ public class Role {
* <p>
* Should return {@code null} if this role {@link #mShowNone shows a "None" item}.
*
+ * @param user the user of the role
* @param context the {@code Context} to retrieve system services
- *
* @return the package name of the fallback holder, or {@code null} if none
*/
@Nullable
- public String getFallbackHolder(@NonNull Context context) {
- if (!RoleManagerCompat.isRoleFallbackEnabledAsUser(this, Process.myUserHandle(), context)) {
+ public String getFallbackHolderAsUser(@NonNull UserHandle user, @NonNull Context context) {
+ if (!RoleManagerCompat.isRoleFallbackEnabledAsUser(this, user, context)) {
return null;
}
if (mFallBackToDefaultHolder) {
- return CollectionUtils.firstOrNull(getDefaultHolders(context));
+ return CollectionUtils.firstOrNull(getDefaultHoldersAsUser(user, context));
}
if (mBehavior != null) {
- return mBehavior.getFallbackHolder(this, context);
+ return mBehavior.getFallbackHolderAsUser(this, user, context);
}
return null;
}
@@ -562,29 +555,32 @@ public class Role {
* components (plus meeting some other general restrictions).
*
* @param packageName the package name to check for
+ * @param user the user to check for
* @param context the {@code Context} to retrieve system services
*
* @return whether the package is qualified for a role
*/
- public boolean isPackageQualified(@NonNull String packageName, @NonNull Context context) {
+ public boolean isPackageQualifiedAsUser(@NonNull String packageName, @NonNull UserHandle user,
+ @NonNull Context context) {
RoleManager roleManager = context.getSystemService(RoleManager.class);
if (shouldAllowBypassingQualification(context)
&& RoleManagerCompat.isBypassingRoleQualification(roleManager)) {
return true;
}
- ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName,
- Process.myUserHandle(), context);
+ ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName, user,
+ context);
if (applicationInfo == null) {
Log.w(LOG_TAG, "Cannot get ApplicationInfo for package: " + packageName);
return false;
}
- if (!isPackageMinimallyQualifiedAsUser(applicationInfo, Process.myUserHandle(), context)) {
+ if (!isPackageMinimallyQualifiedAsUser(applicationInfo, user, context)) {
return false;
}
if (mBehavior != null) {
- Boolean isPackageQualified = mBehavior.isPackageQualified(this, packageName, context);
+ Boolean isPackageQualified = mBehavior.isPackageQualifiedAsUser(this, packageName,
+ user, context);
if (isPackageQualified != null) {
return isPackageQualified;
}
@@ -598,14 +594,15 @@ public class Role {
continue;
}
- if (requiredComponent.getQualifyingComponentForPackage(packageName, context) == null) {
+ if (requiredComponent.getQualifyingComponentForPackageAsUser(packageName, user, context)
+ == null) {
Log.i(LOG_TAG, packageName + " not qualified for " + mName
+ " due to missing " + requiredComponent);
return false;
}
}
- if (mStatic && !getDefaultHolders(context).contains(packageName)) {
+ if (mStatic && !getDefaultHoldersAsUser(user, context).contains(packageName)) {
return false;
}
@@ -778,41 +775,42 @@ public class Role {
* @param packageName the package name of the application to be granted this role to
* @param dontKillApp whether this application should not be killed despite changes
* @param overrideUser whether to override user when granting privileges
+ * @param user the user of the application
* @param context the {@code Context} to retrieve system services
*/
- public void grant(@NonNull String packageName, boolean dontKillApp,
- boolean overrideUser, @NonNull Context context) {
- boolean permissionOrAppOpChanged = Permissions.grant(packageName,
+ public void grantAsUser(@NonNull String packageName, boolean dontKillApp,
+ boolean overrideUser, @NonNull UserHandle user, @NonNull Context context) {
+ boolean permissionOrAppOpChanged = Permissions.grantAsUser(packageName,
Permissions.filterBySdkVersion(mPermissions),
SdkLevel.isAtLeastS() ? !mSystemOnly : true, overrideUser, true, false, false,
- context);
+ user, context);
List<String> appOpPermissionsToGrant = Permissions.filterBySdkVersion(mAppOpPermissions);
int appOpPermissionsSize = appOpPermissionsToGrant.size();
for (int i = 0; i < appOpPermissionsSize; i++) {
String appOpPermission = appOpPermissionsToGrant.get(i);
- AppOpPermissions.grant(packageName, appOpPermission, overrideUser, context);
+ AppOpPermissions.grantAsUser(packageName, appOpPermission, overrideUser, user, context);
}
int appOpsSize = mAppOps.size();
for (int i = 0; i < appOpsSize; i++) {
AppOp appOp = mAppOps.get(i);
- appOp.grant(packageName, context);
+ appOp.grantAsUser(packageName, user, context);
}
int preferredActivitiesSize = mPreferredActivities.size();
for (int i = 0; i < preferredActivitiesSize; i++) {
PreferredActivity preferredActivity = mPreferredActivities.get(i);
- preferredActivity.configure(packageName, context);
+ preferredActivity.configureAsUser(packageName, user, context);
}
if (mBehavior != null) {
- mBehavior.grant(this, packageName, context);
+ mBehavior.grantAsUser(this, packageName, user, context);
}
- if (!dontKillApp && permissionOrAppOpChanged && !Permissions.isRuntimePermissionsSupported(
- packageName, context)) {
- killApp(packageName, context);
+ if (!dontKillApp && permissionOrAppOpChanged
+ && !Permissions.isRuntimePermissionsSupportedAsUser(packageName, user, context)) {
+ killAppAsUser(packageName, user, context);
}
}
@@ -822,12 +820,15 @@ public class Role {
* @param packageName the package name of the application to be granted this role to
* @param dontKillApp whether this application should not be killed despite changes
* @param overrideSystemFixedPermissions whether system-fixed permissions can be revoked
+ * @param user the user of the role
* @param context the {@code Context} to retrieve system services
*/
- public void revoke(@NonNull String packageName, boolean dontKillApp,
- boolean overrideSystemFixedPermissions, @NonNull Context context) {
- RoleManager roleManager = context.getSystemService(RoleManager.class);
- List<String> otherRoleNames = roleManager.getHeldRolesFromController(packageName);
+ public void revokeAsUser(@NonNull String packageName, boolean dontKillApp,
+ boolean overrideSystemFixedPermissions, @NonNull UserHandle user,
+ @NonNull Context context) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ RoleManager userRoleManager = userContext.getSystemService(RoleManager.class);
+ List<String> otherRoleNames = userRoleManager.getHeldRolesFromController(packageName);
otherRoleNames.remove(mName);
List<String> permissionsToRevoke = Permissions.filterBySdkVersion(mPermissions);
@@ -839,8 +840,8 @@ public class Role {
permissionsToRevoke.removeAll(Permissions.filterBySdkVersion(role.mPermissions));
}
- boolean permissionOrAppOpChanged = Permissions.revoke(packageName, permissionsToRevoke,
- true, false, overrideSystemFixedPermissions, context);
+ boolean permissionOrAppOpChanged = Permissions.revokeAsUser(packageName,
+ permissionsToRevoke, true, false, overrideSystemFixedPermissions, user, context);
List<String> appOpPermissionsToRevoke = Permissions.filterBySdkVersion(mAppOpPermissions);
for (int i = 0; i < otherRoleNamesSize; i++) {
@@ -852,7 +853,7 @@ public class Role {
int appOpPermissionsSize = appOpPermissionsToRevoke.size();
for (int i = 0; i < appOpPermissionsSize; i++) {
String appOpPermission = appOpPermissionsToRevoke.get(i);
- AppOpPermissions.revoke(packageName, appOpPermission, context);
+ AppOpPermissions.revokeAsUser(packageName, appOpPermission, user, context);
}
List<AppOp> appOpsToRevoke = new ArrayList<>(mAppOps);
@@ -864,7 +865,7 @@ public class Role {
int appOpsSize = appOpsToRevoke.size();
for (int i = 0; i < appOpsSize; i++) {
AppOp appOp = appOpsToRevoke.get(i);
- appOp.revoke(packageName, context);
+ appOp.revokeAsUser(packageName, user, context);
}
// TODO: Revoke preferred activities? But this is unnecessary for most roles using it as
@@ -873,22 +874,23 @@ public class Role {
// wrong thing when we are removing a exclusive role holder for adding another.
if (mBehavior != null) {
- mBehavior.revoke(this, packageName, context);
+ mBehavior.revokeAsUser(this, packageName, user, context);
}
if (!dontKillApp && permissionOrAppOpChanged) {
- killApp(packageName, context);
+ killAppAsUser(packageName, user, context);
}
}
- private void killApp(@NonNull String packageName, @NonNull Context context) {
+ private void killAppAsUser(@NonNull String packageName, @NonNull UserHandle user,
+ @NonNull Context context) {
if (DEBUG) {
Log.i(LOG_TAG, "Killing " + packageName + " due to "
+ Thread.currentThread().getStackTrace()[3].getMethodName()
+ "(" + mName + ")");
}
- ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName,
- Process.myUserHandle(), context);
+ ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName, user,
+ context);
if (applicationInfo == null) {
Log.w(LOG_TAG, "Cannot get ApplicationInfo for package: " + packageName);
return;
@@ -947,6 +949,40 @@ public class Role {
RoleManagerCompat.setRoleFallbackEnabledAsUser(this, false, user, context);
}
+ /**
+ * Check whether this role should be visible to user.
+ *
+ * @param user the user to check for
+ * @param context the `Context` to retrieve system services
+ *
+ * @return whether this role should be visible to user
+ */
+ public boolean isVisibleAsUser(@NonNull UserHandle user, @NonNull Context context) {
+ RoleBehavior behavior = getBehavior();
+ if (behavior == null) {
+ return isVisible();
+ }
+ return isVisible() && behavior.isVisibleAsUser(this, user, context);
+ }
+
+ /**
+ * Check whether a qualifying application should be visible to user.
+ *
+ * @param applicationInfo the {@link ApplicationInfo} for the application
+ * @param user the user for the application
+ * @param context the {@code Context} to retrieve system services
+ *
+ * @return whether the qualifying application should be visible to user
+ */
+ public boolean isApplicationVisibleAsUser(@NonNull ApplicationInfo applicationInfo,
+ @NonNull UserHandle user, @NonNull Context context) {
+ RoleBehavior behavior = getBehavior();
+ if (behavior == null) {
+ return true;
+ }
+ return behavior.isApplicationVisibleAsUser(this, applicationInfo, user, context);
+ }
+
@Override
public String toString() {
return "Role{"
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/RoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/model/RoleBehavior.java
index f0c4fc018..4bc1873d5 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/RoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/RoleBehavior.java
@@ -17,6 +17,7 @@
package com.android.role.controller.model;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.os.UserHandle;
import androidx.annotation.NonNull;
@@ -31,9 +32,10 @@ import java.util.List;
public interface RoleBehavior {
/**
- * @see Role#onRoleAdded(Context)
+ * @see Role#onRoleAddedAsUser(UserHandle, Context)
*/
- default void onRoleAdded(@NonNull Role role, @NonNull Context context) {}
+ default void onRoleAddedAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {}
/**
* @see Role#isAvailableAsUser(UserHandle, Context)
@@ -47,7 +49,8 @@ public interface RoleBehavior {
* @see Role#getDefaultHolders(Context)
*/
@NonNull
- default List<String> getDefaultHolders(@NonNull Role role, @NonNull Context context) {
+ default List<String> getDefaultHoldersAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
return Collections.emptyList();
}
@@ -55,7 +58,8 @@ public interface RoleBehavior {
* @see Role#getFallbackHolder(Context)
*/
@Nullable
- default String getFallbackHolder(@NonNull Role role, @NonNull Context context) {
+ default String getFallbackHolderAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
return null;
}
@@ -72,8 +76,8 @@ public interface RoleBehavior {
* @see Role#isPackageQualified(String, Context)
*/
@Nullable
- default Boolean isPackageQualified(@NonNull Role role, @NonNull String packageName,
- @NonNull Context context) {
+ default Boolean isPackageQualifiedAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
return null;
}
@@ -87,15 +91,16 @@ public interface RoleBehavior {
}
/**
- * @see Role#grant(String, boolean, boolean, boolean, Context)
+ * @see Role#grantAsUser(String, boolean, boolean, UserHandle, Context)
*/
- default void grant(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {}
+ default void grantAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {}
/**
- * @see Role#revoke(String, boolean, boolean, Context)
+ * @see Role#revokeAsUser(String, boolean, boolean, UserHandle, Context)
*/
- default void revoke(@NonNull Role role, @NonNull String packageName,
- @NonNull Context context) {}
+ default void revokeAsUser(@NonNull Role role, @NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {}
/**
* @see Role#onHolderSelectedAsUser(String, UserHandle, Context)
@@ -108,4 +113,34 @@ public interface RoleBehavior {
*/
default void onHolderChangedAsUser(@NonNull Role role, @NonNull UserHandle user,
@NonNull Context context) {}
+
+ /**
+ * Check whether this role should be visible to user.
+ *
+ * @param role the role to check for
+ * @param user the user to check for
+ * @param context the `Context` to retrieve system services
+ *
+ * @return whether this role should be visible to user
+ */
+ default boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ return true;
+ }
+
+ /**
+ * Check whether a qualifying application should be visible to user.
+ *
+ * @param role the role to check for
+ * @param applicationInfo the {@link ApplicationInfo} for the application
+ * @param user the user for the application
+ * @param context the {@code Context} to retrieve system services
+ *
+ * @return whether the qualifying application should be visible to user
+ */
+ default boolean isApplicationVisibleAsUser(@NonNull Role role,
+ @NonNull ApplicationInfo applicationInfo, @NonNull UserHandle user,
+ @NonNull Context context) {
+ return true;
+ }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/RoleParser.java b/PermissionController/role-controller/java/com/android/role/controller/model/RoleParser.java
index 23299419e..cc2d102c8 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/RoleParser.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/RoleParser.java
@@ -21,8 +21,10 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
+import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.Build;
+import android.permission.flags.Flags;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
@@ -31,7 +33,9 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import com.android.modules.utils.build.SdkLevel;
import com.android.role.controller.behavior.BrowserRoleBehavior;
+import com.android.role.controller.util.ResourceUtils;
import org.xmlpull.v1.XmlPullParserException;
@@ -149,7 +153,7 @@ public class RoleParser {
*/
@NonNull
public ArrayMap<String, Role> parse() {
- try (XmlResourceParser parser = sGetRolesXml.apply(mContext)) {
+ try (XmlResourceParser parser = getRolesXml()) {
Pair<ArrayMap<String, PermissionSet>, ArrayMap<String, Role>> xml = parseXml(parser);
if (xml == null) {
return new ArrayMap<>();
@@ -164,6 +168,20 @@ public class RoleParser {
}
}
+ /**
+ * Retrieves the roles.xml resource from a context
+ */
+ private XmlResourceParser getRolesXml() {
+ if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) {
+ Resources resources = ResourceUtils.getPermissionControllerResources(mContext);
+ int resourceId = resources.getIdentifier("roles", "xml",
+ ResourceUtils.RESOURCE_PACKAGE_NAME_PERMISSION_CONTROLLER);
+ return resources.getXml(resourceId);
+ } else {
+ return sGetRolesXml.apply(mContext);
+ }
+ }
+
@Nullable
private Pair<ArrayMap<String, PermissionSet>, ArrayMap<String, Role>> parseXml(
@NonNull XmlResourceParser parser) throws IOException, XmlPullParserException {
@@ -252,6 +270,9 @@ public class RoleParser {
return null;
}
+ int minSdkVersion = getAttributeIntValue(parser, ATTRIBUTE_MIN_SDK_VERSION,
+ Build.VERSION_CODES.BASE);
+
List<Permission> permissions = new ArrayList<>();
int type;
@@ -269,6 +290,8 @@ public class RoleParser {
if (permission == null) {
continue;
}
+ int mergedMinSdkVersion = Math.max(permission.getMinSdkVersion(), minSdkVersion);
+ permission = permission.withMinSdkVersion(mergedMinSdkVersion);
validateNoDuplicateElement(permission, permissions, "permission");
permissions.add(permission);
} else {
@@ -738,13 +761,24 @@ public class RoleParser {
if (permissionSetName == null) {
continue;
}
- if (!permissionSets.containsKey(permissionSetName)) {
+ PermissionSet permissionSet = permissionSets.get(permissionSetName);
+ if (permissionSet == null) {
throwOrLogMessage("Unknown permission set:" + permissionSetName);
continue;
}
- PermissionSet permissionSet = permissionSets.get(permissionSetName);
- // We do allow intersection between permission sets.
- permissions.addAll(permissionSet.getPermissions());
+ int minSdkVersion = getAttributeIntValue(parser, ATTRIBUTE_MIN_SDK_VERSION,
+ Build.VERSION_CODES.BASE);
+ List<Permission> permissionsInSet = permissionSet.getPermissions();
+ int permissionsInSetSize = permissionsInSet.size();
+ for (int permissionsInSetIndex = 0;
+ permissionsInSetIndex < permissionsInSetSize; permissionsInSetIndex++) {
+ Permission permission = permissionsInSet.get(permissionsInSetIndex);
+ int mergedMinSdkVersion =
+ Math.max(permission.getMinSdkVersion(), minSdkVersion);
+ permission = permission.withMinSdkVersion(mergedMinSdkVersion);
+ // We do allow intersection between permission sets.
+ permissions.add(permission);
+ }
break;
}
case TAG_PERMISSION: {
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/VisibilityMixin.java b/PermissionController/role-controller/java/com/android/role/controller/model/VisibilityMixin.java
new file mode 100644
index 000000000..fdfb45143
--- /dev/null
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/VisibilityMixin.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.role.controller.model;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.UserHandle;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.android.role.controller.util.ResourceUtils;
+
+/**
+ * Mixin for {@link RoleBehavior#isVisibleAsUser(Role, UserHandle, Context)} that returns whether
+ * the role should be visible from a corresponding boolean resource.
+ */
+public class VisibilityMixin {
+
+ private static final String LOG_TAG = VisibilityMixin.class.getSimpleName();
+
+ private VisibilityMixin() {}
+
+ /**
+ * Get the boolean resource value that represents whether a role is visible to the user.
+ *
+ * @param resourceName the name of the resource
+ * @param isPermissionControllerResource if {@code true}, and if the current SDK level is at
+ * least V, get the resource from a PermissionController context for the given user.
+ * Otherwise, get the resource the provided context.
+ * @param user the user to get the PermissionController context for
+ * @param context the `Context` to retrieve the resource (and system services)
+ *
+ * @return whether this role should be visible to user
+ */
+ public static boolean isVisible(@NonNull String resourceName,
+ boolean isPermissionControllerResource, @NonNull UserHandle user,
+ @NonNull Context context) {
+ Resources resources = isPermissionControllerResource
+ ? ResourceUtils.getPermissionControllerResources(context) : context.getResources();
+ String packageName = isPermissionControllerResource
+ ? ResourceUtils.RESOURCE_PACKAGE_NAME_PERMISSION_CONTROLLER : "android";
+
+ int resourceId = resources.getIdentifier(resourceName, "bool", packageName);
+ if (resourceId == 0) {
+ Log.w(LOG_TAG, "Cannot find resource for visibility: " + resourceName);
+ return true;
+ }
+ try {
+ return resources.getBoolean(resourceId);
+ } catch (Resources.NotFoundException e) {
+ Log.w(LOG_TAG, "Cannot get resource for visibility: " + resourceName, e);
+ return true;
+ }
+ }
+}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/service/RoleControllerServiceImpl.java b/PermissionController/role-controller/java/com/android/role/controller/service/RoleControllerServiceImpl.java
new file mode 100644
index 000000000..2a6010c4d
--- /dev/null
+++ b/PermissionController/role-controller/java/com/android/role/controller/service/RoleControllerServiceImpl.java
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.role.controller.service;
+
+import android.app.role.RoleControllerService;
+import android.app.role.RoleManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.os.Process;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.WorkerThread;
+
+import com.android.role.controller.model.Role;
+import com.android.role.controller.model.Roles;
+import com.android.role.controller.util.CollectionUtils;
+import com.android.role.controller.util.LegacyRoleFallbackEnabledUtils;
+import com.android.role.controller.util.PackageUtils;
+import com.android.role.controller.util.UserUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Implementation of {@link RoleControllerService}.
+ */
+public class RoleControllerServiceImpl extends RoleControllerService {
+
+ private static final String LOG_TAG = RoleControllerServiceImpl.class.getSimpleName();
+
+ private static final boolean DEBUG = false;
+
+
+ private UserHandle mUser;
+ private Context mContext;
+ private RoleManager mUserRoleManager;
+
+ public RoleControllerServiceImpl() {}
+
+ public RoleControllerServiceImpl(@NonNull UserHandle user, @NonNull Context context) {
+ init(user, context);
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ init(Process.myUserHandle(), this);
+ }
+
+ private void init(@NonNull UserHandle user, @NonNull Context context) {
+ mUser = user;
+ mContext = context;
+ Context userContext = UserUtils.getUserContext(context, user);
+ mUserRoleManager = userContext.getSystemService(RoleManager.class);
+ }
+
+ @Override
+ @WorkerThread
+ public boolean onGrantDefaultRoles() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Granting default roles, user: " + mUser.myUserId());
+ }
+
+ // Gather the available roles for current user.
+ ArrayMap<String, Role> roleMap = Roles.get(mContext);
+ List<Role> roles = new ArrayList<>();
+ List<String> roleNames = new ArrayList<>();
+ ArraySet<String> addedRoleNames = new ArraySet<>();
+ int roleMapSize = roleMap.size();
+ for (int i = 0; i < roleMapSize; i++) {
+ Role role = roleMap.valueAt(i);
+
+ if (!role.isAvailableAsUser(mUser, mContext)) {
+ continue;
+ }
+ roles.add(role);
+ String roleName = role.getName();
+ roleNames.add(roleName);
+ if (!mUserRoleManager.isRoleAvailable(roleName)) {
+ addedRoleNames.add(roleName);
+ }
+ }
+
+ // TODO: Clean up holders of roles that will be removed.
+
+ // Set the available role names in RoleManager.
+ mUserRoleManager.setRoleNamesFromController(roleNames);
+
+ int addedRoleNamesSize = addedRoleNames.size();
+ for (int i = 0; i < addedRoleNamesSize; i++) {
+ String roleName = addedRoleNames.valueAt(i);
+
+ Role role = roleMap.get(roleName);
+ role.onRoleAddedAsUser(mUser, mContext);
+ }
+
+ // Go through the holders of all roles.
+ int rolesSize = roles.size();
+ for (int rolesIndex = 0; rolesIndex < rolesSize; rolesIndex++) {
+ Role role = roles.get(rolesIndex);
+
+ String roleName = role.getName();
+
+ // For each of the current holders, check if it is still qualified, redo grant if so, or
+ // remove it otherwise.
+ List<String> currentPackageNames = mUserRoleManager.getRoleHolders(roleName);
+ int currentPackageNamesSize = currentPackageNames.size();
+ for (int currentPackageNamesIndex = 0;
+ currentPackageNamesIndex < currentPackageNamesSize;
+ currentPackageNamesIndex++) {
+ String packageName = currentPackageNames.get(currentPackageNamesIndex);
+
+ if (role.isPackageQualifiedAsUser(packageName, mUser, mContext)) {
+ // We should not override user set or fixed permissions because we are only
+ // redoing the grant here. Otherwise, user won't be able to revoke permissions
+ // granted by role.
+ addRoleHolderInternal(role, packageName, false, false, true);
+ } else {
+ Log.i(LOG_TAG, "Removing package that no longer qualifies for the role,"
+ + " package: " + packageName + ", role: " + roleName);
+ removeRoleHolderInternal(role, packageName, false);
+ }
+ }
+
+ // If there is no holder for a role now, or the role is static, we need to add default
+ // or fallback holders, if any.
+ currentPackageNames = mUserRoleManager.getRoleHolders(roleName);
+ currentPackageNamesSize = currentPackageNames.size();
+ boolean isStaticRole = role.isStatic();
+ if (currentPackageNamesSize == 0 || isStaticRole) {
+ List<String> packageNamesToAdd = null;
+ if (addedRoleNames.contains(roleName) || isStaticRole) {
+ packageNamesToAdd = role.getDefaultHoldersAsUser(mUser, mContext);
+ }
+ if (packageNamesToAdd == null || packageNamesToAdd.isEmpty()) {
+ packageNamesToAdd = CollectionUtils.singletonOrEmpty(
+ role.getFallbackHolderAsUser(mUser, mContext));
+ }
+
+ int packageNamesToAddSize = packageNamesToAdd.size();
+ for (int packageNamesToAddIndex = 0; packageNamesToAddIndex < packageNamesToAddSize;
+ packageNamesToAddIndex++) {
+ String packageName = packageNamesToAdd.get(packageNamesToAddIndex);
+
+ if (currentPackageNames.contains(packageName)) {
+ // This may happen when we are ensuring all default holders are added for
+ // static roles.
+ continue;
+ }
+ if (!role.isPackageQualifiedAsUser(packageName, mUser, mContext)) {
+ Log.e(LOG_TAG, "Default/fallback role holder package doesn't qualify for"
+ + " the role, package: " + packageName + ", role: " + roleName);
+ continue;
+ }
+ Log.i(LOG_TAG, "Adding package as default/fallback role holder, package: "
+ + packageName + ", role: " + roleName);
+ // TODO: If we don't override user here, user might end up missing incoming
+ // phone calls or SMS, so we just keep the old behavior. But overriding user
+ // choice about permission without explicit user action is bad, so maybe we
+ // should at least show a notification?
+ addRoleHolderInternal(role, packageName, role.shouldOverrideUserWhenGranting());
+ }
+ }
+
+ // Ensure that an exclusive role has at most one holder.
+ currentPackageNames = mUserRoleManager.getRoleHolders(roleName);
+ currentPackageNamesSize = currentPackageNames.size();
+ if (role.isExclusive() && currentPackageNamesSize > 1) {
+ Log.w(LOG_TAG, "Multiple packages holding an exclusive role, role: "
+ + roleName);
+ // No good way to determine who should be the only one, just keep the first one.
+ for (int currentPackageNamesIndex = 1;
+ currentPackageNamesIndex < currentPackageNamesSize;
+ currentPackageNamesIndex++) {
+ String packageName = currentPackageNames.get(currentPackageNamesIndex);
+
+ Log.i(LOG_TAG, "Removing extraneous package for an exclusive role, package: "
+ + packageName + ", role: " + roleName);
+ removeRoleHolderInternal(role, packageName, false);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ @WorkerThread
+ public boolean onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
+ int flags) {
+ if (!checkFlags(flags, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP)) {
+ return false;
+ }
+
+ Role role = Roles.get(mContext).get(roleName);
+ if (role == null) {
+ Log.e(LOG_TAG, "Unknown role: " + roleName);
+ return false;
+ }
+ if (!role.isAvailableAsUser(mUser, mContext)) {
+ Log.e(LOG_TAG, "Role is unavailable: " + roleName);
+ return false;
+ }
+
+ if (!role.isPackageQualifiedAsUser(packageName, mUser, mContext)) {
+ Log.e(LOG_TAG, "Package does not qualify for the role, package: " + packageName
+ + ", role: " + roleName);
+ return false;
+ }
+
+ boolean added = false;
+ if (role.isExclusive()) {
+ List<String> currentPackageNames = mUserRoleManager.getRoleHolders(roleName);
+ int currentPackageNamesSize = currentPackageNames.size();
+ for (int i = 0; i < currentPackageNamesSize; i++) {
+ String currentPackageName = currentPackageNames.get(i);
+
+ if (Objects.equals(currentPackageName, packageName)) {
+ Log.i(LOG_TAG, "Package is already a role holder, package: " + packageName
+ + ", role: " + roleName);
+ added = true;
+ continue;
+ }
+
+ boolean removed = removeRoleHolderInternal(role, currentPackageName, false);
+ if (!removed) {
+ // TODO: Clean up?
+ return false;
+ }
+ }
+ }
+
+ boolean dontKillApp = hasFlag(flags, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP);
+ added = addRoleHolderInternal(role, packageName, dontKillApp,
+ role.shouldOverrideUserWhenGranting(), added);
+ if (!added) {
+ return false;
+ }
+
+ role.onHolderAddedAsUser(packageName, mUser, mContext);
+ role.onHolderChangedAsUser(mUser, mContext);
+
+ return true;
+ }
+
+ @Override
+ @WorkerThread
+ public boolean onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
+ int flags) {
+ if (!checkFlags(flags, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP)) {
+ return false;
+ }
+
+ Role role = Roles.get(mContext).get(roleName);
+ if (role == null) {
+ Log.e(LOG_TAG, "Unknown role: " + roleName);
+ return false;
+ }
+ if (!role.isAvailableAsUser(mUser, mContext)) {
+ Log.e(LOG_TAG, "Role is unavailable: " + roleName);
+ return false;
+ }
+
+ boolean dontKillApp = hasFlag(flags, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP);
+ boolean removed = removeRoleHolderInternal(role, packageName, dontKillApp);
+ if (!removed) {
+ return false;
+ }
+
+ // TODO: Should we consider this successful regardless?
+ boolean fallbackSuccessful = addFallbackRoleHolderMaybe(role);
+ if (!fallbackSuccessful) {
+ return false;
+ }
+
+ role.onHolderChangedAsUser(mUser, mContext);
+
+ return true;
+ }
+
+ @Override
+ @WorkerThread
+ public boolean onClearRoleHolders(@NonNull String roleName, int flags) {
+ if (!checkFlags(flags, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP)) {
+ return false;
+ }
+
+ Role role = Roles.get(mContext).get(roleName);
+ if (role == null) {
+ Log.e(LOG_TAG, "Unknown role: " + roleName);
+ return false;
+ }
+ if (!role.isAvailableAsUser(mUser, mContext)) {
+ Log.e(LOG_TAG, "Role is unavailable: " + roleName);
+ return false;
+ }
+
+ boolean dontKillApp = hasFlag(flags, RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP);
+ boolean cleared = clearRoleHoldersInternal(role, dontKillApp);
+ if (!cleared) {
+ return false;
+ }
+
+ // TODO: Should we consider this successful regardless?
+ boolean fallbackSuccessful = addFallbackRoleHolderMaybe(role);
+ if (!fallbackSuccessful) {
+ return false;
+ }
+
+ role.onHolderChangedAsUser(mUser, mContext);
+
+ return true;
+ }
+
+ @WorkerThread
+ private boolean addRoleHolderInternal(@NonNull Role role, @NonNull String packageName,
+ boolean overrideUser) {
+ return addRoleHolderInternal(role, packageName, false, overrideUser, false);
+ }
+
+ @WorkerThread
+ private boolean addRoleHolderInternal(@NonNull Role role, @NonNull String packageName,
+ boolean dontKillApp, boolean overrideUser, boolean added) {
+ role.grantAsUser(packageName, dontKillApp, overrideUser, mUser, mContext);
+
+ String roleName = role.getName();
+ if (!added) {
+ added = mUserRoleManager.addRoleHolderFromController(roleName, packageName);
+ }
+ if (!added) {
+ Log.e(LOG_TAG, "Failed to add role holder in RoleManager, package: " + packageName
+ + ", role: " + roleName);
+ }
+ return added;
+ }
+
+ @WorkerThread
+ private boolean removeRoleHolderInternal(@NonNull Role role, @NonNull String packageName,
+ boolean dontKillApp) {
+ ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName,
+ mUser, mContext);
+ if (applicationInfo == null) {
+ Log.w(LOG_TAG, "Cannot get ApplicationInfo for package: " + packageName);
+ }
+
+ if (applicationInfo != null) {
+ role.revokeAsUser(packageName, dontKillApp, false, mUser, mContext);
+ }
+
+ String roleName = role.getName();
+ boolean removed = mUserRoleManager.removeRoleHolderFromController(roleName, packageName);
+ if (!removed) {
+ Log.e(LOG_TAG, "Failed to remove role holder in RoleManager," + " package: "
+ + packageName + ", role: " + roleName);
+ }
+ return removed;
+ }
+
+ @WorkerThread
+ private boolean clearRoleHoldersInternal(@NonNull Role role, boolean dontKillApp) {
+ String roleName = role.getName();
+ List<String> packageNames = mUserRoleManager.getRoleHolders(roleName);
+ boolean cleared = true;
+
+ int packageNamesSize = packageNames.size();
+ for (int i = 0; i < packageNamesSize; i++) {
+ String packageName = packageNames.get(i);
+ boolean removed = removeRoleHolderInternal(role, packageName, dontKillApp);
+ if (!removed) {
+ cleared = false;
+ }
+ }
+
+ if (!cleared) {
+ Log.e(LOG_TAG, "Failed to clear role holders, role: " + roleName);
+ }
+ return cleared;
+ }
+
+ @WorkerThread
+ private boolean addFallbackRoleHolderMaybe(@NonNull Role role) {
+ String roleName = role.getName();
+ List<String> currentPackageNames = mUserRoleManager.getRoleHolders(roleName);
+ if (!currentPackageNames.isEmpty()) {
+ return true;
+ }
+
+ String fallbackPackageName = role.getFallbackHolderAsUser(mUser, mContext);
+ if (fallbackPackageName == null) {
+ return true;
+ }
+
+ if (!role.isPackageQualifiedAsUser(fallbackPackageName, mUser, mContext)) {
+ Log.e(LOG_TAG, "Fallback role holder package doesn't qualify for the role, package: "
+ + fallbackPackageName + ", role: " + roleName);
+ return false;
+ }
+
+ Log.i(LOG_TAG, "Adding package as fallback role holder, package: " + fallbackPackageName
+ + ", role: " + roleName);
+ // TODO: If we don't override user here, user might end up missing incoming
+ // phone calls or SMS, so we just keep the old behavior. But overriding user
+ // choice about permission without explicit user action is bad, so maybe we
+ // should at least show a notification?
+ return addRoleHolderInternal(role, fallbackPackageName,
+ role.shouldOverrideUserWhenGranting());
+ }
+
+ @Override
+ public boolean onIsApplicationQualifiedForRole(@NonNull String roleName,
+ @NonNull String packageName) {
+ // This API has been deprecated and Settings has been using onIsApplicationVisibleForRole()
+ // instead.
+ return false;
+ }
+
+ @Override
+ public boolean onIsApplicationVisibleForRole(@NonNull String roleName,
+ @NonNull String packageName) {
+ Role role = Roles.get(mContext).get(roleName);
+ if (role == null) {
+ return false;
+ }
+ if (!role.isAvailableAsUser(mUser, mContext)) {
+ return false;
+ }
+ if (!role.isPackageQualifiedAsUser(packageName, mUser, mContext)) {
+ return false;
+ }
+ ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName,
+ mUser, mContext);
+ if (applicationInfo == null || !role.isApplicationVisibleAsUser(applicationInfo, mUser,
+ mContext)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onIsRoleVisible(@NonNull String roleName) {
+ Role role = Roles.get(mContext).get(roleName);
+ if (role == null) {
+ return false;
+ }
+ if (!role.isAvailableAsUser(mUser, mContext)) {
+ return false;
+ }
+
+ return role.isVisibleAsUser(mUser, mContext);
+ }
+
+ @Override
+ @NonNull
+ public List<String> onGetLegacyFallbackDisabledRoles() {
+ return LegacyRoleFallbackEnabledUtils.getFallbackDisabledRoles(mUser, mContext);
+ }
+
+
+ private static boolean checkFlags(int flags, int allowedFlags) {
+ if ((flags & allowedFlags) != flags) {
+ Log.e(LOG_TAG, "flags is invalid, flags: 0x" + Integer.toHexString(flags)
+ + ", allowed flags: 0x" + Integer.toHexString(allowedFlags));
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean hasFlag(int flags, int flag) {
+ return (flags & flag) == flag;
+ }
+}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/util/LegacyRoleFallbackEnabledUtils.java b/PermissionController/role-controller/java/com/android/role/controller/util/LegacyRoleFallbackEnabledUtils.java
new file mode 100644
index 000000000..5be10a26a
--- /dev/null
+++ b/PermissionController/role-controller/java/com/android/role/controller/util/LegacyRoleFallbackEnabledUtils.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.role.controller.util;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.UserHandle;
+
+import androidx.annotation.NonNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LegacyRoleFallbackEnabledUtils {
+ /**
+ * Name of generic shared preferences file.
+ */
+ private static final String PREFERENCES_FILE = "preferences";
+
+ /**
+ * Key in the generic shared preferences that stores if the user manually selected the "none"
+ * role holder for a role.
+ */
+ private static final String IS_NONE_ROLE_HOLDER_SELECTED_KEY = "is_none_role_holder_selected:";
+
+ /**
+ * Get a device protected storage based shared preferences. Avoid storing sensitive data in it.
+ *
+ * @param context the context to get the shared preferences
+ * @return a device protected storage based shared preferences
+ */
+ @NonNull
+ @TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ private static SharedPreferences getSharedPreferences(@NonNull UserHandle user,
+ @NonNull Context context) {
+ String packageName = context.getPackageManager().getPermissionControllerPackageName();
+ try {
+ context = context.createPackageContextAsUser(packageName, 0, user);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ if (!context.isDeviceProtectedStorage()) {
+ context = context.createDeviceProtectedStorageContext();
+ }
+ return context.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE);
+ }
+
+ /**
+ * Get all role names with fallback disabled, which means their "none" are set to true.
+ *
+ * @return A list of role names with fallback disabled.
+ */
+ public static List<String> getFallbackDisabledRoles(@NonNull UserHandle user,
+ @NonNull Context context) {
+ List<String> fallbackDisabledRoles = new ArrayList<>();
+ SharedPreferences sharedPreferences = getSharedPreferences(user, context);
+ for (String key : sharedPreferences.getAll().keySet()) {
+ if (key.startsWith(IS_NONE_ROLE_HOLDER_SELECTED_KEY)
+ && sharedPreferences.getBoolean(key, false)) {
+ String roleName = key.substring(IS_NONE_ROLE_HOLDER_SELECTED_KEY.length());
+ fallbackDisabledRoles.add(roleName);
+ }
+ }
+ return fallbackDisabledRoles;
+ }
+
+ /**
+ * Check whether the role has the fallback holder enabled.
+ *
+ * @return whether the "none" role holder is not selected
+ */
+ public static boolean isRoleFallbackEnabledAsUser(@NonNull String roleName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ return !getSharedPreferences(user, context)
+ .getBoolean(IS_NONE_ROLE_HOLDER_SELECTED_KEY + roleName, false);
+ }
+
+ /**
+ * Set whether the role has fallback holder enabled.
+ */
+ public static void setRoleFallbackEnabledAsUser(@NonNull String roleName,
+ boolean fallbackEnabled, @NonNull UserHandle user, @NonNull Context context) {
+ String key = IS_NONE_ROLE_HOLDER_SELECTED_KEY + roleName;
+ if (fallbackEnabled) {
+ getSharedPreferences(user, context).edit().remove(key).apply();
+ } else {
+ getSharedPreferences(user, context).edit().putBoolean(key, true).apply();
+ }
+ }
+}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/util/NotificationUtils.java b/PermissionController/role-controller/java/com/android/role/controller/util/NotificationUtils.java
index 3b11d7d92..365c3b491 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/util/NotificationUtils.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/util/NotificationUtils.java
@@ -23,6 +23,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
import android.util.Log;
@@ -44,41 +45,45 @@ public final class NotificationUtils {
/**
* Grants the NotificationListener access.
*
- * @param context the {@code Context} to retrieve system services
* @param packageName the package name implements the NotificationListener
+ * @param user the user of the component
+ * @param context the {@code Context} to retrieve system services
*/
- public static void grantNotificationAccessForPackage(@NonNull Context context,
- @NonNull String packageName) {
- setNotificationGrantStateForPackage(context, packageName, true);
+ public static void grantNotificationAccessForPackageAsUser(@NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ setNotificationGrantStateForPackageAsUser(packageName, true, user, context);
}
/**
* Revokes the NotificationListener access.
*
- * @param context the {@code Context} to retrieve system services
* @param packageName the package name implements the NotificationListener
+ * @param user the user of the component
+ * @param context the {@code Context} to retrieve system services
*/
- public static void revokeNotificationAccessForPackage(@NonNull Context context,
- @NonNull String packageName) {
- setNotificationGrantStateForPackage(context, packageName, false);
+ public static void revokeNotificationAccessForPackageAsUser(@NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ setNotificationGrantStateForPackageAsUser(packageName, false, user, context);
}
- private static void setNotificationGrantStateForPackage(@NonNull Context context,
- @NonNull String packageName, boolean granted) {
+ private static void setNotificationGrantStateForPackageAsUser(@NonNull String packageName,
+ boolean granted, @NonNull UserHandle user, @NonNull Context context) {
List<ComponentName> notificationListenersForPackage =
- getNotificationListenersForPackage(packageName, context);
- NotificationManager notificationManager =
- context.getSystemService(NotificationManager.class);
+ getNotificationListenersForPackageAsUser(packageName, user, context);
+ Context userContext = UserUtils.getUserContext(context, user);
+ NotificationManager userNotificationManager =
+ userContext.getSystemService(NotificationManager.class);
for (ComponentName componentName : notificationListenersForPackage) {
- notificationManager.setNotificationListenerAccessGranted(
+ userNotificationManager.setNotificationListenerAccessGranted(
componentName, granted, false);
}
}
- private static List<ComponentName> getNotificationListenersForPackage(
- @NonNull String packageName, @NonNull Context context) {
- List<ResolveInfo> allListeners = context.getPackageManager().queryIntentServices(
+ private static List<ComponentName> getNotificationListenersForPackageAsUser(
+ @NonNull String packageName, @NonNull UserHandle user, @NonNull Context context) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ List<ResolveInfo> allListeners = userContext.getPackageManager().queryIntentServices(
new Intent(NotificationListenerService.SERVICE_INTERFACE).setPackage(packageName),
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
ArrayList<ComponentName> pkgListeners = new ArrayList<>();
diff --git a/PermissionController/role-controller/java/com/android/role/controller/util/PackageUtils.java b/PermissionController/role-controller/java/com/android/role/controller/util/PackageUtils.java
index 4b127ad10..cbffd451a 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/util/PackageUtils.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/util/PackageUtils.java
@@ -36,19 +36,21 @@ public final class PackageUtils {
* Retrieve the {@link PackageInfo} of an application.
*
* @param packageName the package name of the application
- * @param extraFlags the extra flags to pass to {@link PackageManager#getPackageInfo(String,
- * int)}
- * @param context the {@code Context} to retrieve system services
- *
+ * @param extraFlags the extra flags to pass to {@link PackageManager#getPackageInfo(String,
+ * int)}
+ * @param user the user of the application
+ * @param context the {@code Context} to retrieve system services
* @return the {@link PackageInfo} of the application, or {@code null} if not found
*/
@Nullable
- public static PackageInfo getPackageInfo(@NonNull String packageName, int extraFlags,
- @NonNull Context context) {
- PackageManager packageManager = context.getPackageManager();
+ public static PackageInfo getPackageInfoAsUser(@NonNull String packageName, int extraFlags,
+ @NonNull UserHandle user, @NonNull Context context) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ PackageManager userPackageManager = userContext.getPackageManager();
try {
- return packageManager.getPackageInfo(packageName, PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | extraFlags);
+ return userPackageManager.getPackageInfo(packageName,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | extraFlags);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
@@ -58,12 +60,15 @@ public final class PackageUtils {
* Retrieve if a package is a system package.
*
* @param packageName the name of the package
+ * @param user the user of the package
* @param context the {@code Context} to retrieve system services
*
* @return whether the package is a system package
*/
- public static boolean isSystemPackage(@NonNull String packageName, @NonNull Context context) {
- return getPackageInfo(packageName, PackageManager.MATCH_SYSTEM_ONLY, context) != null;
+ public static boolean isSystemPackageAsUser(@NonNull String packageName,
+ @NonNull UserHandle user, @NonNull Context context) {
+ return getPackageInfoAsUser(packageName, PackageManager.MATCH_SYSTEM_ONLY, user, context)
+ != null;
}
/**
diff --git a/PermissionController/role-controller/java/com/android/role/controller/util/ResourceUtils.java b/PermissionController/role-controller/java/com/android/role/controller/util/ResourceUtils.java
new file mode 100644
index 000000000..f8f12108a
--- /dev/null
+++ b/PermissionController/role-controller/java/com/android/role/controller/util/ResourceUtils.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.role.controller.util;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.permission.flags.Flags;
+
+import androidx.annotation.NonNull;
+
+import com.android.modules.utils.build.SdkLevel;
+
+public class ResourceUtils {
+
+ private ResourceUtils() {}
+
+ public static String RESOURCE_PACKAGE_NAME_PERMISSION_CONTROLLER =
+ "com.android.permissioncontroller";
+
+ /**
+ * Get a {@link Resources} object to be used to access PermissionController resources.
+ */
+ @NonNull
+ public static Resources getPermissionControllerResources(@NonNull Context context) {
+ return getPermissionControllerContext(context).getResources();
+ }
+
+ @NonNull
+ private static Context getPermissionControllerContext(@NonNull Context context) {
+ if (!SdkLevel.isAtLeastV() || !Flags.systemServerRoleControllerEnabled()) {
+ // We don't have the getPermissionControllerPackageName() API below V,
+ // but role controller always runs in PermissionController below V.
+ return context;
+ }
+ String packageName = context.getPackageManager().getPermissionControllerPackageName();
+ try {
+ return context.createPackageContext(packageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new RuntimeException("Cannot create PermissionController context", e);
+ }
+ }
+}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/util/RoleManagerCompat.java b/PermissionController/role-controller/java/com/android/role/controller/util/RoleManagerCompat.java
index 8a6fd579c..ec63528d1 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/util/RoleManagerCompat.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/util/RoleManagerCompat.java
@@ -18,8 +18,8 @@ package com.android.role.controller.util;
import android.app.role.RoleManager;
import android.content.Context;
-import android.content.SharedPreferences;
import android.os.UserHandle;
+import android.permission.flags.Flags;
import androidx.annotation.NonNull;
@@ -31,16 +31,7 @@ import com.android.role.controller.model.Role;
*/
public class RoleManagerCompat {
- /**
- * Key in the generic shared preferences that stores if the user manually selected the "none"
- * role holder for a role.
- */
- private static final String IS_NONE_ROLE_HOLDER_SELECTED_KEY = "is_none_role_holder_selected:";
- /**
- * Name of generic shared preferences file.
- */
- private static final String PREFERENCES_FILE = "preferences";
private RoleManagerCompat() {}
@@ -56,47 +47,34 @@ public class RoleManagerCompat {
}
/**
- * Get a device protected storage based shared preferences. Avoid storing sensitive data in it.
- *
- * @param context the context to get the shared preferences
- * @return a device protected storage based shared preferences
- */
- @NonNull
- private static SharedPreferences getDeviceProtectedSharedPreferences(@NonNull Context context) {
- if (!context.isDeviceProtectedStorage()) {
- context = context.createDeviceProtectedStorageContext();
- }
- return context.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE);
- }
-
- /**
* Check whether the role has the fallback holder enabled.
*
* @return whether the "none" role holder is not selected
*/
public static boolean isRoleFallbackEnabledAsUser(@NonNull Role role, @NonNull UserHandle user,
@NonNull Context context) {
- Context userContext = UserUtils.getUserContext(context, user);
- boolean isNoneHolderSelected = getDeviceProtectedSharedPreferences(userContext)
- .getBoolean(IS_NONE_ROLE_HOLDER_SELECTED_KEY + role.getName(), false);
- return !isNoneHolderSelected;
+ if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ RoleManager userRoleManager = userContext.getSystemService(RoleManager.class);
+ return userRoleManager.isRoleFallbackEnabled(role.getName());
+ } else {
+ return LegacyRoleFallbackEnabledUtils.isRoleFallbackEnabledAsUser(role.getName(), user,
+ context);
+ }
}
/**
* Set whether the role has fallback holder enabled.
- *
*/
public static void setRoleFallbackEnabledAsUser(@NonNull Role role,
boolean fallbackEnabled, @NonNull UserHandle user, @NonNull Context context) {
- Context userContext = UserUtils.getUserContext(context, user);
- if (fallbackEnabled) {
- getDeviceProtectedSharedPreferences(userContext).edit()
- .remove(IS_NONE_ROLE_HOLDER_SELECTED_KEY + role.getName())
- .apply();
+ if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ RoleManager userRoleManager = userContext.getSystemService(RoleManager.class);
+ userRoleManager.setRoleFallbackEnabled(role.getName(), fallbackEnabled);
} else {
- getDeviceProtectedSharedPreferences(userContext).edit()
- .putBoolean(IS_NONE_ROLE_HOLDER_SELECTED_KEY + role.getName(), true)
- .apply();
+ LegacyRoleFallbackEnabledUtils.setRoleFallbackEnabledAsUser(role.getName(),
+ fallbackEnabled, user, context);
}
}
}