diff options
author | 2023-11-18 07:49:57 +0000 | |
---|---|---|
committer | 2023-11-18 07:49:57 +0000 | |
commit | 45ff302be0117b7e0c7ec04593f6d053d8d3d238 (patch) | |
tree | 37006585859ed54a639e5f9213518dd745cb7aa8 | |
parent | 11bef6356a598048d6b0cd207036ddc3a0744cec (diff) | |
parent | d188c50e8d9b019ef1e46b327e8cde34822d3952 (diff) |
Merge changes I41763726,Ifc024398,I535239c8,Ic6812e8a into main
* changes:
[Role Logic Move] Call SS, not PC
[Role Logic Move] Shim RoleControllerServiceImpl
[Role Logic Move] Migrate isVisible behavior
[Role Logic Move] Access Resources portably
35 files changed, 592 insertions, 228 deletions
diff --git a/PermissionController/AndroidManifest.xml b/PermissionController/AndroidManifest.xml index 288dc6c84..0d663bc05 100644 --- a/PermissionController/AndroidManifest.xml +++ b/PermissionController/AndroidManifest.xml @@ -521,7 +521,7 @@ </intent-filter> </service> - <service android:name="com.android.permissioncontroller.role.service.RoleControllerServiceImpl" + <service android:name="com.android.role.controller.service.RoleControllerServiceImpl" android:exported="true"> <intent-filter android:priority="1"> <action android:name="android.app.role.RoleControllerService"/> diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml index 1a60e783a..e6be02bde 100644 --- a/PermissionController/res/xml/roles.xml +++ b/PermissionController/res/xml/roles.xml @@ -164,8 +164,7 @@ overrideUserWhenGranting="true" requestDescription="@string/role_browser_request_description" requestTitle="@string/role_browser_request_title" - shortLabel="@string/role_browser_short_label" - uiBehavior="BrowserRoleUiBehavior"> + shortLabel="@string/role_browser_short_label"> <!-- ~ Required components matching is handled in BrowserRoleBehavior because it needs the ~ PackageManager.MATCH_ALL flag and other manual filtering, which cannot fit in our 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 7ab0b9bd2..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 @@ -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; @@ -193,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 f64c3bcf0..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 @@ -31,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; @@ -154,4 +155,10 @@ public class BrowserRoleBehavior implements RoleBehavior { } } } + + @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/DialerRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/DialerRoleBehavior.java index d0ee2d5bf..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; @@ -73,4 +74,10 @@ public class DialerRoleBehavior implements RoleBehavior { 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/EmergencyRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/EmergencyRoleBehavior.java index 5c23a996e..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 @@ -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.model.VisibilityMixin; import com.android.role.controller.util.PackageUtils; import java.util.List; @@ -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 5bdd5f682..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 @@ -35,6 +35,7 @@ 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; @@ -113,7 +114,7 @@ public class HomeRoleBehavior implements RoleBehavior { /** * Check if the application is a settings application */ - public static boolean isSettingsApplicationAsUser(@NonNull ApplicationInfo applicationInfo, + private static boolean isSettingsApplicationAsUser(@NonNull ApplicationInfo applicationInfo, @NonNull UserHandle user, @NonNull Context context) { Context userContext = UserUtils.getUserContext(context, user); PackageManager userPackageManager = userContext.getPackageManager(); @@ -213,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/SmsRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/SmsRoleBehavior.java index 6e5c5c920..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 @@ -30,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; @@ -129,4 +130,10 @@ public class SmsRoleBehavior implements RoleBehavior { 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/model/Role.java b/PermissionController/role-controller/java/com/android/role/controller/model/Role.java index e80ea1194..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 @@ -949,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 34d2282a7..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; @@ -112,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 4f59c7b31..3d89e12c0 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.roleControllerInSystemServer()) { + 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 { diff --git a/PermissionController/src/com/android/permissioncontroller/role/model/VisibilityMixin.java b/PermissionController/role-controller/java/com/android/role/controller/model/VisibilityMixin.java index 90cda72ca..fdfb45143 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/model/VisibilityMixin.java +++ b/PermissionController/role-controller/java/com/android/role/controller/model/VisibilityMixin.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.permissioncontroller.role.model; +package com.android.role.controller.model; import android.content.Context; import android.content.res.Resources; @@ -23,8 +23,7 @@ import android.util.Log; import androidx.annotation.NonNull; -import com.android.role.controller.model.Role; -import com.android.role.controller.model.RoleBehavior; +import com.android.role.controller.util.ResourceUtils; /** * Mixin for {@link RoleBehavior#isVisibleAsUser(Role, UserHandle, Context)} that returns whether @@ -37,11 +36,26 @@ public class VisibilityMixin { private VisibilityMixin() {} /** - * @see Role#isVisibleAsUser(UserHandle, Context) + * 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, @NonNull Context context) { - Resources resources = context.getResources(); - int resourceId = resources.getIdentifier(resourceName, "bool", "android"); + 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; diff --git a/PermissionController/src/com/android/permissioncontroller/role/service/RoleControllerServiceImpl.java b/PermissionController/role-controller/java/com/android/role/controller/service/RoleControllerServiceImpl.java index 45f1236bb..d3c099d5e 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/service/RoleControllerServiceImpl.java +++ b/PermissionController/role-controller/java/com/android/role/controller/service/RoleControllerServiceImpl.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.permissioncontroller.role.service; +package com.android.role.controller.service; import android.app.role.RoleControllerService; import android.app.role.RoleManager; @@ -29,11 +29,10 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; -import com.android.permissioncontroller.permission.utils.CollectionUtils; -import com.android.permissioncontroller.role.utils.PackageUtils; -import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils; 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.PackageUtils; import com.android.role.controller.util.UserUtils; import java.util.ArrayList; @@ -49,16 +48,28 @@ public class RoleControllerServiceImpl extends RoleControllerService { private static final boolean DEBUG = false; - private UserHandle mUser; + 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(); - mUser = Process.myUserHandle(); - Context userContext = UserUtils.getUserContext(this, mUser); + 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); } @@ -70,7 +81,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { } // Gather the available roles for current user. - ArrayMap<String, Role> roleMap = Roles.get(this); + ArrayMap<String, Role> roleMap = Roles.get(mContext); List<Role> roles = new ArrayList<>(); List<String> roleNames = new ArrayList<>(); ArraySet<String> addedRoleNames = new ArraySet<>(); @@ -78,7 +89,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { for (int i = 0; i < roleMapSize; i++) { Role role = roleMap.valueAt(i); - if (!role.isAvailableAsUser(mUser, this)) { + if (!role.isAvailableAsUser(mUser, mContext)) { continue; } roles.add(role); @@ -99,7 +110,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { String roleName = addedRoleNames.valueAt(i); Role role = roleMap.get(roleName); - role.onRoleAddedAsUser(mUser, this); + role.onRoleAddedAsUser(mUser, mContext); } // Go through the holders of all roles. @@ -118,7 +129,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { currentPackageNamesIndex++) { String packageName = currentPackageNames.get(currentPackageNamesIndex); - if (role.isPackageQualifiedAsUser(packageName, mUser, this)) { + 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. @@ -138,11 +149,11 @@ public class RoleControllerServiceImpl extends RoleControllerService { if (currentPackageNamesSize == 0 || isStaticRole) { List<String> packageNamesToAdd = null; if (addedRoleNames.contains(roleName) || isStaticRole) { - packageNamesToAdd = role.getDefaultHoldersAsUser(mUser, this); + packageNamesToAdd = role.getDefaultHoldersAsUser(mUser, mContext); } if (packageNamesToAdd == null || packageNamesToAdd.isEmpty()) { packageNamesToAdd = CollectionUtils.singletonOrEmpty( - role.getFallbackHolderAsUser(mUser, this)); + role.getFallbackHolderAsUser(mUser, mContext)); } int packageNamesToAddSize = packageNamesToAdd.size(); @@ -155,7 +166,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { // static roles. continue; } - if (!role.isPackageQualifiedAsUser(packageName, mUser, this)) { + 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; @@ -200,17 +211,17 @@ public class RoleControllerServiceImpl extends RoleControllerService { return false; } - Role role = Roles.get(this).get(roleName); + Role role = Roles.get(mContext).get(roleName); if (role == null) { Log.e(LOG_TAG, "Unknown role: " + roleName); return false; } - if (!role.isAvailableAsUser(mUser, this)) { + if (!role.isAvailableAsUser(mUser, mContext)) { Log.e(LOG_TAG, "Role is unavailable: " + roleName); return false; } - if (!role.isPackageQualifiedAsUser(packageName, mUser, this)) { + if (!role.isPackageQualifiedAsUser(packageName, mUser, mContext)) { Log.e(LOG_TAG, "Package does not qualify for the role, package: " + packageName + ", role: " + roleName); return false; @@ -245,8 +256,8 @@ public class RoleControllerServiceImpl extends RoleControllerService { return false; } - role.onHolderAddedAsUser(packageName, mUser, this); - role.onHolderChangedAsUser(mUser, this); + role.onHolderAddedAsUser(packageName, mUser, mContext); + role.onHolderChangedAsUser(mUser, mContext); return true; } @@ -259,12 +270,12 @@ public class RoleControllerServiceImpl extends RoleControllerService { return false; } - Role role = Roles.get(this).get(roleName); + Role role = Roles.get(mContext).get(roleName); if (role == null) { Log.e(LOG_TAG, "Unknown role: " + roleName); return false; } - if (!role.isAvailableAsUser(mUser, this)) { + if (!role.isAvailableAsUser(mUser, mContext)) { Log.e(LOG_TAG, "Role is unavailable: " + roleName); return false; } @@ -281,7 +292,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { return false; } - role.onHolderChangedAsUser(mUser, this); + role.onHolderChangedAsUser(mUser, mContext); return true; } @@ -293,12 +304,12 @@ public class RoleControllerServiceImpl extends RoleControllerService { return false; } - Role role = Roles.get(this).get(roleName); + Role role = Roles.get(mContext).get(roleName); if (role == null) { Log.e(LOG_TAG, "Unknown role: " + roleName); return false; } - if (!role.isAvailableAsUser(mUser, this)) { + if (!role.isAvailableAsUser(mUser, mContext)) { Log.e(LOG_TAG, "Role is unavailable: " + roleName); return false; } @@ -315,7 +326,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { return false; } - role.onHolderChangedAsUser(mUser, this); + role.onHolderChangedAsUser(mUser, mContext); return true; } @@ -329,7 +340,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { @WorkerThread private boolean addRoleHolderInternal(@NonNull Role role, @NonNull String packageName, boolean dontKillApp, boolean overrideUser, boolean added) { - role.grantAsUser(packageName, dontKillApp, overrideUser, mUser, this); + role.grantAsUser(packageName, dontKillApp, overrideUser, mUser, mContext); String roleName = role.getName(); if (!added) { @@ -346,13 +357,13 @@ public class RoleControllerServiceImpl extends RoleControllerService { private boolean removeRoleHolderInternal(@NonNull Role role, @NonNull String packageName, boolean dontKillApp) { ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName, - mUser, this); + mUser, mContext); if (applicationInfo == null) { Log.w(LOG_TAG, "Cannot get ApplicationInfo for package: " + packageName); } if (applicationInfo != null) { - role.revokeAsUser(packageName, dontKillApp, false, mUser, this); + role.revokeAsUser(packageName, dontKillApp, false, mUser, mContext); } String roleName = role.getName(); @@ -393,12 +404,12 @@ public class RoleControllerServiceImpl extends RoleControllerService { return true; } - String fallbackPackageName = role.getFallbackHolderAsUser(mUser, this); + String fallbackPackageName = role.getFallbackHolderAsUser(mUser, mContext); if (fallbackPackageName == null) { return true; } - if (!role.isPackageQualifiedAsUser(fallbackPackageName, mUser, this)) { + 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; @@ -425,20 +436,20 @@ public class RoleControllerServiceImpl extends RoleControllerService { @Override public boolean onIsApplicationVisibleForRole(@NonNull String roleName, @NonNull String packageName) { - Role role = Roles.get(this).get(roleName); + Role role = Roles.get(mContext).get(roleName); if (role == null) { return false; } - if (!role.isAvailableAsUser(mUser, this)) { + if (!role.isAvailableAsUser(mUser, mContext)) { return false; } - if (!role.isPackageQualifiedAsUser(packageName, mUser, this)) { + if (!role.isPackageQualifiedAsUser(packageName, mUser, mContext)) { return false; } ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName, - mUser, this); - if (applicationInfo == null || !RoleUiBehaviorUtils.isApplicationVisibleAsUser(role, - applicationInfo, mUser, this)) { + mUser, mContext); + if (applicationInfo == null || !role.isApplicationVisibleAsUser(applicationInfo, mUser, + mContext)) { return false; } return true; @@ -446,15 +457,15 @@ public class RoleControllerServiceImpl extends RoleControllerService { @Override public boolean onIsRoleVisible(@NonNull String roleName) { - Role role = Roles.get(this).get(roleName); + Role role = Roles.get(mContext).get(roleName); if (role == null) { return false; } - if (!role.isAvailableAsUser(mUser, this)) { + if (!role.isAvailableAsUser(mUser, mContext)) { return false; } - return RoleUiBehaviorUtils.isVisibleAsUser(role, mUser, this); + return role.isVisibleAsUser(mUser, mContext); } private static boolean checkFlags(int flags, int allowedFlags) { 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..2617b953a --- /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.roleControllerInSystemServer()) { + // 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/src/com/android/permissioncontroller/PermissionControllerApplication.java b/PermissionController/src/com/android/permissioncontroller/PermissionControllerApplication.java index 729a5ec43..50da28149 100644 --- a/PermissionController/src/com/android/permissioncontroller/PermissionControllerApplication.java +++ b/PermissionController/src/com/android/permissioncontroller/PermissionControllerApplication.java @@ -33,7 +33,6 @@ import com.android.permissioncontroller.permission.utils.Utils; import com.android.permissioncontroller.privacysources.SafetyCenterAccessibilityListener; import com.android.permissioncontroller.role.model.RoleParserInitializer; import com.android.permissioncontroller.role.ui.SpecialAppAccessListActivity; -import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils; import com.android.role.controller.model.Role; import com.android.role.controller.model.Roles; @@ -73,7 +72,7 @@ public final class PermissionControllerApplication extends Application { Role role = roles.valueAt(i); if (!role.isAvailableAsUser(Process.myUserHandle(), this) - || !RoleUiBehaviorUtils.isVisible(role, this)) { + || !role.isVisibleAsUser(Process.myUserHandle(), this)) { continue; } if (!role.isExclusive()) { diff --git a/PermissionController/src/com/android/permissioncontroller/role/service/RoleSearchIndexablesProvider.java b/PermissionController/src/com/android/permissioncontroller/role/service/RoleSearchIndexablesProvider.java index 9a0067dbf..870e2c03a 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/service/RoleSearchIndexablesProvider.java +++ b/PermissionController/src/com/android/permissioncontroller/role/service/RoleSearchIndexablesProvider.java @@ -29,7 +29,6 @@ import androidx.annotation.Nullable; import com.android.permissioncontroller.R; import com.android.permissioncontroller.permission.service.BaseSearchIndexablesProvider; import com.android.permissioncontroller.role.model.RoleParserInitializer; -import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils; import com.android.role.controller.model.Role; import com.android.role.controller.model.Roles; @@ -63,7 +62,7 @@ public class RoleSearchIndexablesProvider extends BaseSearchIndexablesProvider { long token = Binder.clearCallingIdentity(); try { if (!role.isAvailableAsUser(Process.myUserHandle(), context) - || !RoleUiBehaviorUtils.isVisible(role, context)) { + || !role.isVisibleAsUser(Process.myUserHandle(), context)) { continue; } } finally { diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppActivity.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppActivity.java index 0e7e51a02..41f1a06a9 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppActivity.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppActivity.java @@ -32,7 +32,6 @@ import com.android.permissioncontroller.R; import com.android.permissioncontroller.role.ui.auto.AutoDefaultAppFragment; import com.android.permissioncontroller.role.ui.handheld.HandheldDefaultAppFragment; import com.android.permissioncontroller.role.ui.wear.WearDefaultAppFragment; -import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils; import com.android.role.controller.model.Role; import com.android.role.controller.model.Roles; @@ -89,7 +88,7 @@ public class DefaultAppActivity extends SettingsActivity { return; } - if (!RoleUiBehaviorUtils.isVisibleAsUser(role, user, this)) { + if (!role.isVisibleAsUser(user, this)) { Log.e(LOG_TAG, "Role is invisible: " + roleName); finish(); return; diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleActivity.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleActivity.java index 856416fbb..279e55266 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleActivity.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleActivity.java @@ -39,7 +39,6 @@ import com.android.permissioncontroller.permission.utils.CollectionUtils; import com.android.permissioncontroller.role.model.UserDeniedManager; import com.android.permissioncontroller.role.ui.wear.WearRequestRoleFragment; import com.android.permissioncontroller.role.utils.PackageUtils; -import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils; import com.android.role.controller.model.Role; import com.android.role.controller.model.Roles; @@ -113,7 +112,7 @@ public class RequestRoleActivity extends FragmentActivity { return; } - if (!RoleUiBehaviorUtils.isVisible(role, this)) { + if (!role.isVisibleAsUser(Process.myUserHandle(), this)) { Log.e(LOG_TAG, "Role is invisible: " + mRoleName); reportRequestResult( PermissionControllerStatsLog.ROLE_REQUEST_RESULT_REPORTED__RESULT__IGNORED); diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListLiveData.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListLiveData.java index b9011bd78..e6df3ed8a 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListLiveData.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListLiveData.java @@ -30,7 +30,6 @@ import androidx.lifecycle.LiveData; import com.android.permissioncontroller.AsyncTaskLiveData; import com.android.permissioncontroller.role.utils.PackageUtils; -import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils; import com.android.role.controller.model.Role; import com.android.role.controller.model.Roles; @@ -97,7 +96,7 @@ public class RoleListLiveData extends AsyncTaskLiveData<List<RoleItem>> continue; } - if (!RoleUiBehaviorUtils.isVisibleAsUser(role, mUser, mContext)) { + if (!role.isVisibleAsUser(mUser, mContext)) { continue; } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleLiveData.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleLiveData.java index 3ccb1d8bc..bb492f76d 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleLiveData.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleLiveData.java @@ -30,7 +30,6 @@ import androidx.lifecycle.LiveData; import com.android.permissioncontroller.AsyncTaskLiveData; import com.android.permissioncontroller.role.utils.PackageUtils; -import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils; import com.android.role.controller.model.Role; import java.util.ArrayList; @@ -95,8 +94,7 @@ public class RoleLiveData extends AsyncTaskLiveData<List<Pair<ApplicationInfo, B + qualifyingPackageName); continue; } - if (!RoleUiBehaviorUtils.isApplicationVisibleAsUser(mRole, qualifyingApplicationInfo, - mUser, mContext)) { + if (!mRole.isApplicationVisibleAsUser(qualifyingApplicationInfo, mUser, mContext)) { continue; } boolean isHolderApplication = holderPackageNames.contains(qualifyingPackageName); diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/AssistantRoleUiBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/AssistantRoleUiBehavior.java index 40bd7a33e..4df3ccf99 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/AssistantRoleUiBehavior.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/AssistantRoleUiBehavior.java @@ -26,7 +26,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.permissioncontroller.R; -import com.android.permissioncontroller.role.model.VisibilityMixin; import com.android.role.controller.model.Role; /*** @@ -34,12 +33,6 @@ import com.android.role.controller.model.Role; */ public class AssistantRoleUiBehavior implements RoleUiBehavior { - @Override - public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user, - @NonNull Context context) { - return VisibilityMixin.isVisible("config_showDefaultAssistant", context); - } - @Nullable @Override public Intent getManageIntentAsUser(@NonNull Role role, @NonNull UserHandle user, diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/BrowserRoleUiBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/BrowserRoleUiBehavior.java deleted file mode 100644 index 018b0db41..000000000 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/BrowserRoleUiBehavior.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2022 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.permissioncontroller.role.ui.behavior; - -import android.content.Context; -import android.os.UserHandle; - -import androidx.annotation.NonNull; - -import com.android.permissioncontroller.R; -import com.android.role.controller.model.Role; - -/*** - * Class for UI behavior of Browser role - */ -public class BrowserRoleUiBehavior implements RoleUiBehavior { - - @Override - public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user, - @NonNull Context context) { - return context.getResources().getBoolean(R.bool.config_showBrowserRole); - } -} diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/DialerRoleUiBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/DialerRoleUiBehavior.java index e6b8dabe1..ab87e24cf 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/DialerRoleUiBehavior.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/DialerRoleUiBehavior.java @@ -49,12 +49,6 @@ public class DialerRoleUiBehavior implements RoleUiBehavior { } } - @Override - public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user, - @NonNull Context context) { - return context.getResources().getBoolean(R.bool.config_showDialerRole); - } - @Nullable @Override public CharSequence getConfirmationMessage(@NonNull Role role, @NonNull String packageName, diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/EmergencyRoleUiBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/EmergencyRoleUiBehavior.java index 8a62ee7eb..f891bb3ed 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/EmergencyRoleUiBehavior.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/EmergencyRoleUiBehavior.java @@ -17,13 +17,11 @@ package com.android.permissioncontroller.role.ui.behavior; import android.content.Context; -import android.os.UserHandle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.permissioncontroller.role.model.EncryptionUnawareConfirmationMixin; -import com.android.permissioncontroller.role.model.VisibilityMixin; import com.android.role.controller.model.Role; /*** @@ -31,12 +29,6 @@ import com.android.role.controller.model.Role; */ public class EmergencyRoleUiBehavior implements RoleUiBehavior { - @Override - public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user, - @NonNull Context context) { - return VisibilityMixin.isVisible("config_showDefaultEmergency", context); - } - @Nullable @Override public CharSequence getConfirmationMessage(@NonNull Role role, @NonNull String packageName, diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/HomeRoleUiBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/HomeRoleUiBehavior.java index e49fc0d3d..323325d0b 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/HomeRoleUiBehavior.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/HomeRoleUiBehavior.java @@ -34,10 +34,8 @@ import androidx.preference.Preference; import com.android.permissioncontroller.R; import com.android.permissioncontroller.permission.utils.CollectionUtils; import com.android.permissioncontroller.permission.utils.Utils; -import com.android.permissioncontroller.role.model.VisibilityMixin; import com.android.permissioncontroller.role.ui.TwoTargetPreference; import com.android.permissioncontroller.role.utils.UserUtils; -import com.android.role.controller.behavior.HomeRoleBehavior; import com.android.role.controller.model.Role; /*** @@ -48,12 +46,6 @@ public class HomeRoleUiBehavior implements RoleUiBehavior { private static final String LOG_TAG = HomeRoleUiBehavior.class.getSimpleName(); @Override - public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user, - @NonNull Context context) { - return VisibilityMixin.isVisible("config_showDefaultHome", context); - } - - @Override public void preparePreferenceAsUser(@NonNull Role role, @NonNull TwoTargetPreference preference, @NonNull UserHandle user, @NonNull Context context) { TwoTargetPreference.OnSecondTargetClickListener listener = null; @@ -82,14 +74,6 @@ public class HomeRoleUiBehavior implements RoleUiBehavior { } @Override - public boolean isApplicationVisibleAsUser(@NonNull Role role, - @NonNull ApplicationInfo applicationInfo, @NonNull UserHandle user, - @NonNull Context context) { - // Home is not available for work profile, so we can just use the current user. - return !HomeRoleBehavior.isSettingsApplicationAsUser(applicationInfo, user, context); - } - - @Override public void prepareApplicationPreferenceAsUser(@NonNull Role role, @NonNull Preference preference, @NonNull ApplicationInfo applicationInfo, @NonNull UserHandle user, @NonNull Context context) { diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/RoleUiBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/RoleUiBehavior.java index 6e3b47fba..29dc5d2fc 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/RoleUiBehavior.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/RoleUiBehavior.java @@ -34,20 +34,6 @@ import com.android.role.controller.model.Role; public interface RoleUiBehavior { /** - * 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; - } - - /** * Get the {@link Intent} to manage this role, or {@code null} to use the default UI. * * @param role the role to get the intent for @@ -76,21 +62,6 @@ public interface RoleUiBehavior { @NonNull Context 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 - */ - default boolean isApplicationVisibleAsUser(@NonNull Role role, - @NonNull ApplicationInfo applicationInfo, @NonNull UserHandle user, - @NonNull Context context) { - return true; - } - - /** * Prepare a {@link Preference} for this role. * * @param role the role to prepare the preference for diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/SmsRoleUiBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/SmsRoleUiBehavior.java index 9fc9be3d4..e27bc1a30 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/SmsRoleUiBehavior.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/SmsRoleUiBehavior.java @@ -17,12 +17,10 @@ package com.android.permissioncontroller.role.ui.behavior; import android.content.Context; -import android.os.UserHandle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.android.permissioncontroller.R; import com.android.permissioncontroller.role.model.EncryptionUnawareConfirmationMixin; import com.android.role.controller.model.Role; @@ -31,12 +29,6 @@ import com.android.role.controller.model.Role; */ public class SmsRoleUiBehavior implements RoleUiBehavior { - @Override - public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user, - @NonNull Context context) { - return context.getResources().getBoolean(R.bool.config_showSmsRole); - } - @Nullable @Override public CharSequence getConfirmationMessage(@NonNull Role role, @NonNull String packageName, diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessActivity.java b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessActivity.java index 1616d9f93..472464061 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessActivity.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessActivity.java @@ -31,7 +31,6 @@ import com.android.permissioncontroller.R; import com.android.permissioncontroller.role.ui.SettingsActivity; import com.android.permissioncontroller.role.ui.auto.AutoSpecialAppAccessFragment; import com.android.permissioncontroller.role.ui.specialappaccess.handheld.HandheldSpecialAppAccessFragment; -import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils; import com.android.role.controller.model.Role; import com.android.role.controller.model.Roles; @@ -78,7 +77,7 @@ public class SpecialAppAccessActivity extends SettingsActivity { return; } - if (!RoleUiBehaviorUtils.isVisible(role, this)) { + if (!role.isVisibleAsUser(Process.myUserHandle(), this)) { Log.e(LOG_TAG, "Role is invisible: " + roleName); finish(); return; diff --git a/PermissionController/src/com/android/permissioncontroller/role/utils/RoleUiBehaviorUtils.java b/PermissionController/src/com/android/permissioncontroller/role/utils/RoleUiBehaviorUtils.java index 6081695b5..7ebc1ebd1 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/utils/RoleUiBehaviorUtils.java +++ b/PermissionController/src/com/android/permissioncontroller/role/utils/RoleUiBehaviorUtils.java @@ -19,7 +19,6 @@ package com.android.permissioncontroller.role.utils; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; -import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; @@ -63,30 +62,6 @@ public final class RoleUiBehaviorUtils { } /** - * @see RoleUiBehavior#isVisibleAsUser - */ - public static boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user, - @NonNull Context context) { - RoleUiBehavior uiBehavior = getUiBehavior(role); - if (uiBehavior == null) { - return role.isVisible(); - } - return role.isVisible() && uiBehavior.isVisibleAsUser(role, user, context); - } - - /** - * Check whether this role should be visible to user, for current user. - * - * @param context the `Context` to retrieve system services - * - * @return whether this role should be visible to user. - */ - public static boolean isVisible(@NonNull Role role, @NonNull Context context) { - return isVisibleAsUser(role, Process.myUserHandle(), context); - } - - - /** * @see RoleUiBehavior#getManageIntentAsUser */ @Nullable @@ -115,19 +90,6 @@ public final class RoleUiBehaviorUtils { } /** - * @see RoleUiBehavior#isApplicationVisibleAsUser - */ - public static boolean isApplicationVisibleAsUser(@NonNull Role role, - @NonNull ApplicationInfo applicationInfo, @NonNull UserHandle user, - @NonNull Context context) { - RoleUiBehavior uiBehavior = getUiBehavior(role); - if (uiBehavior == null) { - return true; - } - return uiBehavior.isApplicationVisibleAsUser(role, applicationInfo, user, context); - } - - /** * @see RoleUiBehavior#prepareApplicationPreferenceAsUser */ public static void prepareApplicationPreferenceAsUser(@NonNull Role role, diff --git a/framework-s/java/android/app/role/IRoleManager.aidl b/framework-s/java/android/app/role/IRoleManager.aidl index 581bb20fa..0aef871e6 100644 --- a/framework-s/java/android/app/role/IRoleManager.aidl +++ b/framework-s/java/android/app/role/IRoleManager.aidl @@ -73,4 +73,9 @@ interface IRoleManager { boolean setBrowserRoleHolder(String packageName, int userId); String getSmsRoleHolder(int userId); + + boolean isRoleVisibleAsUser(in String roleName, int userId); + + boolean isApplicationVisibleForRoleAsUser(in String roleName, in String packageName, + int userId); } diff --git a/framework-s/java/android/app/role/RoleManager.java b/framework-s/java/android/app/role/RoleManager.java index c441d72b6..231c72c2c 100644 --- a/framework-s/java/android/app/role/RoleManager.java +++ b/framework-s/java/android/app/role/RoleManager.java @@ -47,6 +47,7 @@ import androidx.annotation.RequiresApi; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; +import com.android.modules.utils.build.SdkLevel; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -975,10 +976,29 @@ public final class RoleManager { */ @RequiresApi(Build.VERSION_CODES.S) @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) + @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) @SystemApi public void isRoleVisible(@NonNull String roleName, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { - getRoleControllerManager().isRoleVisible(roleName, executor, callback); + if (SdkLevel.isAtLeastV() && Flags.roleControllerInSystemServer()) { + int userId = getContextUserIfAppropriate().getIdentifier(); + boolean visible; + try { + visible = mService.isRoleVisibleAsUser(roleName, userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + executor.execute(() -> { + final long token = Binder.clearCallingIdentity(); + try { + callback.accept(visible); + } finally { + Binder.restoreCallingIdentity(token); + } + }); + } else { + getRoleControllerManager().isRoleVisible(roleName, executor, callback); + } } /** @@ -997,11 +1017,21 @@ public final class RoleManager { */ @RequiresApi(Build.VERSION_CODES.S) @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) + @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) @SystemApi public void isApplicationVisibleForRole(@NonNull String roleName, @NonNull String packageName, @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { - getRoleControllerManager().isApplicationVisibleForRole(roleName, packageName, executor, - callback); + if (SdkLevel.isAtLeastV() && Flags.roleControllerInSystemServer()) { + int userId = getContextUserIfAppropriate().getIdentifier(); + try { + mService.isApplicationVisibleForRoleAsUser(roleName, packageName, userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } else { + getRoleControllerManager().isApplicationVisibleForRole(roleName, packageName, executor, + callback); + } } @NonNull diff --git a/service/java/com/android/role/LocalRoleController.java b/service/java/com/android/role/LocalRoleController.java new file mode 100644 index 000000000..6548aaa03 --- /dev/null +++ b/service/java/com/android/role/LocalRoleController.java @@ -0,0 +1,96 @@ +/* + * 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; + +import android.app.role.RoleControllerService; +import android.app.role.RoleManager; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.RemoteCallback; +import android.os.UserHandle; + +import androidx.annotation.NonNull; + +import com.android.role.controller.service.RoleControllerServiceImpl; + +import java.util.concurrent.Executor; +import java.util.function.Consumer; + +public class LocalRoleController implements RoleController { + + @NonNull + private final RoleControllerServiceImpl mService; + @NonNull + private final HandlerThread mWorkerThread; + @NonNull + private final Handler mWorkerHandler; + + public LocalRoleController(@NonNull UserHandle user, @NonNull Context context) { + mService = new RoleControllerServiceImpl(user, context); + mWorkerThread = new HandlerThread(RoleControllerService.class.getSimpleName()); + mWorkerThread.start(); + mWorkerHandler = new Handler(mWorkerThread.getLooper()); + } + + @Override + public void grantDefaultRoles(@NonNull Executor executor, @NonNull Consumer<Boolean> callback) { + mWorkerHandler.post(() -> { + boolean successful = mService.onGrantDefaultRoles(); + executor.execute(() -> callback.accept(successful)); + }); + } + + @Override + public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { + mWorkerHandler.post(() -> { + boolean successful = mService.onAddRoleHolder(roleName, packageName, flags); + callback.sendResult(successful ? Bundle.EMPTY : null); + }); + } + + @Override + public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { + mWorkerHandler.post(() -> { + boolean successful = mService.onRemoveRoleHolder(roleName, packageName, flags); + callback.sendResult(successful ? Bundle.EMPTY : null); + }); + } + + @Override + public void onClearRoleHolders(@NonNull String roleName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { + mWorkerHandler.post(() -> { + boolean successful = mService.onClearRoleHolders(roleName, flags); + callback.sendResult(successful ? Bundle.EMPTY : null); + }); + } + + @Override + public boolean isRoleVisible(@NonNull String roleName) { + return mService.onIsRoleVisible(roleName); + } + + @Override + public boolean isApplicationVisibleForRole(@NonNull String roleName, + @NonNull String packageName) { + return mService.onIsApplicationVisibleForRole(roleName, packageName); + } +} diff --git a/service/java/com/android/role/RemoteRoleController.java b/service/java/com/android/role/RemoteRoleController.java new file mode 100644 index 000000000..cbf164d6d --- /dev/null +++ b/service/java/com/android/role/RemoteRoleController.java @@ -0,0 +1,76 @@ +/* + * 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; + +import android.app.role.RoleControllerManager; +import android.app.role.RoleManager; +import android.content.Context; +import android.os.RemoteCallback; +import android.os.UserHandle; + +import androidx.annotation.NonNull; + +import com.android.permission.util.ForegroundThread; + +import java.util.concurrent.Executor; +import java.util.function.Consumer; + +public class RemoteRoleController implements RoleController { + @NonNull + private final RoleControllerManager mRoleControllerManager; + + public RemoteRoleController(@NonNull UserHandle user, @NonNull Context context) { + Context userContext = context.createContextAsUser(user, 0); + mRoleControllerManager = + RoleControllerManager.createWithInitializedRemoteServiceComponentName( + ForegroundThread.getHandler(), userContext); + } + + @Override + public void grantDefaultRoles(@NonNull Executor executor, @NonNull Consumer<Boolean> callback) { + mRoleControllerManager.grantDefaultRoles(executor, callback); + } + + @Override + public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { + mRoleControllerManager.onAddRoleHolder(roleName, packageName, flags, callback); + } + + @Override + public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { + mRoleControllerManager.onRemoveRoleHolder(roleName, packageName, flags, callback); + } + + @Override + public void onClearRoleHolders(@NonNull String roleName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { + mRoleControllerManager.onClearRoleHolders(roleName, flags, callback); + } + + @Override + public boolean isRoleVisible(@NonNull String roleName) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isApplicationVisibleForRole(@NonNull String roleName, + @NonNull String packageName) { + throw new UnsupportedOperationException(); + } +} diff --git a/service/java/com/android/role/RoleController.java b/service/java/com/android/role/RoleController.java new file mode 100644 index 000000000..8a7ef8646 --- /dev/null +++ b/service/java/com/android/role/RoleController.java @@ -0,0 +1,61 @@ +/* + * 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; + +import android.annotation.CallbackExecutor; +import android.annotation.NonNull; +import android.app.role.RoleManager; +import android.os.RemoteCallback; + +import java.util.concurrent.Executor; +import java.util.function.Consumer; + +public interface RoleController { + /** + * @see android.app.role.RoleControllerManager#grantDefaultRoles + */ + void grantDefaultRoles(@NonNull @CallbackExecutor Executor executor, + @NonNull Consumer<Boolean> callback); + + /** + * @see android.app.role.RoleControllerManager#onAddRoleHolder + */ + void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback); + + /** + * @see android.app.role.RoleControllerManager#onRemoveRoleHolder + */ + void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback); + + /** + * @see android.app.role.RoleControllerManager#onClearRoleHolders + */ + void onClearRoleHolders(@NonNull String roleName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback); + + /** + * @see android.app.role.RoleControllerManager#isRoleVisible + */ + boolean isRoleVisible(@NonNull String roleName); + + /** + * @see android.app.role.RoleControllerManager#isApplicationVisibleForRole + */ + boolean isApplicationVisibleForRole(@NonNull String roleName, @NonNull String packageName); +} diff --git a/service/java/com/android/role/RoleService.java b/service/java/com/android/role/RoleService.java index 189b61f3e..a282e67cf 100644 --- a/service/java/com/android/role/RoleService.java +++ b/service/java/com/android/role/RoleService.java @@ -45,6 +45,7 @@ import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; +import android.permission.flags.Flags; import android.provider.Settings; import android.text.TextUtils; import android.util.ArraySet; @@ -130,7 +131,7 @@ public class RoleService extends SystemService implements RoleUserState.Callback */ @GuardedBy("mLock") @NonNull - private final SparseArray<RoleControllerManager> mControllers = new SparseArray<>(); + private final SparseArray<RoleController> mControllers = new SparseArray<>(); /** * Maps user id to its list of listeners. @@ -321,14 +322,17 @@ public class RoleService extends SystemService implements RoleUserState.Callback } @NonNull - private RoleControllerManager getOrCreateController(@UserIdInt int userId) { + private RoleController getOrCreateController(@UserIdInt int userId) { synchronized (mLock) { - RoleControllerManager controller = mControllers.get(userId); + RoleController controller = mControllers.get(userId); if (controller == null) { - Context systemContext = getContext(); - Context userContext = systemContext.createContextAsUser(UserHandle.of(userId), 0); - controller = RoleControllerManager.createWithInitializedRemoteServiceComponentName( - ForegroundThread.getHandler(), userContext); + UserHandle user = UserHandle.of(userId); + Context context = getContext(); + if (SdkLevel.isAtLeastV() && Flags.roleControllerInSystemServer()) { + controller = new LocalRoleController(user, context); + } else { + controller = new RemoteRoleController(user, context); + } mControllers.put(userId, controller); } return controller; @@ -577,11 +581,11 @@ public class RoleService extends SystemService implements RoleUserState.Callback Preconditions.checkArgumentIsSupported(DEFAULT_APPLICATION_ROLES, roleName); Objects.requireNonNull(callback, "callback cannot be null"); - RoleControllerManager roleControllerManager = getOrCreateController(userId); + RoleController roleController = getOrCreateController(userId); if (packageName != null) { - roleControllerManager.onAddRoleHolder(roleName, packageName, flags, callback); + roleController.onAddRoleHolder(roleName, packageName, flags, callback); } else { - roleControllerManager.onClearRoleHolders(roleName, flags, callback); + roleController.onClearRoleHolders(roleName, flags, callback); } } @@ -889,6 +893,42 @@ public class RoleService extends SystemService implements RoleUserState.Callback } @Override + public boolean isRoleVisibleAsUser(@NonNull String roleName, @UserIdInt int userId) { + UserUtils.enforceCrossUserPermission(userId, false, "isRoleVisibleAsUser", + getContext()); + if (!UserUtils.isUserExistent(userId, getContext())) { + Log.e(LOG_TAG, "user " + userId + " does not exist"); + return false; + } + + getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, + "isRoleVisibleAsUser"); + + Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + + return getOrCreateController(userId).isRoleVisible(roleName); + } + + @Override + public boolean isApplicationVisibleForRoleAsUser(@NonNull String roleName, + @NonNull String packageName, @UserIdInt int userId) { + UserUtils.enforceCrossUserPermission(userId, false, + "isApplicationVisibleForRoleAsUser", getContext()); + if (!UserUtils.isUserExistent(userId, getContext())) { + Log.e(LOG_TAG, "user " + userId + " does not exist"); + return false; + } + + getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, + "isApplicationVisibleForRoleAsUser"); + + Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty"); + + return getOrCreateController(userId).isApplicationVisibleForRole(roleName, packageName); + } + + @Override protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout, @Nullable String[] args) { if (!checkDumpPermission("role", fout)) { |