summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kholoud Mohamed <kholoudm@google.com> 2023-02-15 13:24:17 +0000
committer Kholoud Mohamed <kholoudm@google.com> 2023-02-15 21:49:27 +0000
commit17981fdc140ddf285c8988510335eb49b74b50e7 (patch)
treeb74df9bb85dc88930c24520198bfba51f2ab66e2
parentfa618d8f1205e604afd244911b65d8831ec0cf60 (diff)
Add a new RestrictionsManager API to get app restrictions per admin
And deprecated the existing API in UM that returns restrictions set for a single admin Bug: 232918480 Test: btest android.devicepolicy.cts.ApplicationRestrictionsTest#getApplicationRestrictionsPerAdmin_* Change-Id: I133ac8d53b651e171dbe46871691fb13e2addb3f
-rw-r--r--core/api/current.txt5
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java5
-rw-r--r--core/java/android/app/admin/DevicePolicyManagerInternal.java8
-rw-r--r--core/java/android/content/IRestrictionsManager.aidl1
-rw-r--r--core/java/android/content/RestrictionsManager.java52
-rw-r--r--core/java/android/os/UserManager.java14
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java10
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java40
-rw-r--r--services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java19
9 files changed, 135 insertions, 19 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index bc8907e25e63..6d38bf0cdc21 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -11356,7 +11356,8 @@ package android.content {
public class RestrictionsManager {
method public static android.os.Bundle convertRestrictionsToBundle(java.util.List<android.content.RestrictionEntry>);
method public android.content.Intent createLocalApprovalIntent();
- method public android.os.Bundle getApplicationRestrictions();
+ method @Deprecated public android.os.Bundle getApplicationRestrictions();
+ method @NonNull @WorkerThread public java.util.List<android.os.Bundle> getApplicationRestrictionsPerAdmin();
method public java.util.List<android.content.RestrictionEntry> getManifestRestrictions(String);
method public boolean hasRestrictionsProvider();
method public void notifyPermissionResponse(String, android.os.PersistableBundle);
@@ -33752,7 +33753,7 @@ package android.os {
public class UserManager {
method public static android.content.Intent createUserCreationIntent(@Nullable String, @Nullable String, @Nullable String, @Nullable android.os.PersistableBundle);
- method @WorkerThread public android.os.Bundle getApplicationRestrictions(String);
+ method @Deprecated @WorkerThread public android.os.Bundle getApplicationRestrictions(String);
method public long getSerialNumberForUser(android.os.UserHandle);
method @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.CREATE_USERS"}) public int getUserCount();
method public long getUserCreationTime(android.os.UserHandle);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index f9f06130b0f6..56f8351a5d64 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9983,6 +9983,11 @@ public class DevicePolicyManager {
* owner, and the application restrictions managing package via
* {@link #getApplicationRestrictions}.
*
+ * <p>Starting from Android Version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+ * multiple admins can set app restrictions for the same application, the target application can
+ * get the list of app restrictions set by each admin via
+ * {@link android.content.RestrictionsManager#getApplicationRestrictionsPerAdmin}.
+ *
* <p>NOTE: The method performs disk I/O and shouldn't be called on the main thread
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index eefadeafda93..eb38146a58be 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -25,7 +25,6 @@ import android.os.Bundle;
import android.os.UserHandle;
import java.util.List;
-import java.util.Map;
import java.util.Set;
/**
@@ -318,8 +317,9 @@ public abstract class DevicePolicyManagerInternal {
public abstract boolean isApplicationExemptionsFlagEnabled();
/**
- * Returns the application restrictions set by each admin for the given {@code packageName}.
+ * Returns a map of admin to {@link Bundle} map of restrictions set by the admins for the
+ * provided {@code packageName} in the provided {@code userId}
*/
- public abstract Map<String, Bundle> getApplicationRestrictionsPerAdmin(
- String packageName, int userId);
+ public abstract List<Bundle> getApplicationRestrictionsPerAdminForUser(
+ String packageName, @UserIdInt int userId);
}
diff --git a/core/java/android/content/IRestrictionsManager.aidl b/core/java/android/content/IRestrictionsManager.aidl
index db9146ffbae1..0fcd63fbfc94 100644
--- a/core/java/android/content/IRestrictionsManager.aidl
+++ b/core/java/android/content/IRestrictionsManager.aidl
@@ -26,6 +26,7 @@ import android.os.PersistableBundle;
*/
interface IRestrictionsManager {
Bundle getApplicationRestrictions(in String packageName);
+ List<Bundle> getApplicationRestrictionsPerAdminForUser(int userId, in String packageName);
boolean hasRestrictionsProvider();
void requestPermission(in String packageName, in String requestType, in String requestId,
in PersistableBundle requestData);
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index ffd80eabf6ca..8115292e5885 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -18,7 +18,10 @@ package android.content;
import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM;
+import android.annotation.NonNull;
import android.annotation.SystemService;
+import android.annotation.UserHandleAware;
+import android.annotation.WorkerThread;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.compat.annotation.UnsupportedAppUsage;
@@ -31,6 +34,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.RemoteException;
+import android.os.UserManager;
import android.service.restrictions.RestrictionsReceiver;
import android.util.AttributeSet;
import android.util.Log;
@@ -422,6 +426,14 @@ public class RestrictionsManager {
* to this application.
* @return the application restrictions as a Bundle. Returns null if there
* are no restrictions.
+ *
+ * @deprecated Use {@link #getApplicationRestrictionsPerAdmin} instead.
+ * Starting from Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, it is
+ * possible for there to be multiple managing agents on the device with the ability to set
+ * restrictions. This API will only to return the restrictions set by device policy controllers
+ * (DPCs)
+ *
+ * @see DevicePolicyManager
*/
public Bundle getApplicationRestrictions() {
try {
@@ -435,6 +447,46 @@ public class RestrictionsManager {
}
/**
+ * Returns a {@link List} containing a {@link Bundle} for each managing agent that has set
+ * restrictions for the current application, the bundle contains any application restrictions
+ * set for the current package. The order of the items in the list is not guaranteed to remain
+ * stable between multiple calls.
+ *
+ * <p>Starting from Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+ * it is possible for there to be multiple managing agents on the device with the ability to set
+ * restrictions, e.g. an Enterprise DPC and a Supervision admin.
+ *
+ * <p>Each {@link Bundle} consists of key-value pairs, as defined by the application,
+ * where the types of values may be:
+ * <ul>
+ * <li>{@code boolean}
+ * <li>{@code int}
+ * <li>{@code String} or {@code String[]}
+ * <li>From {@link android.os.Build.VERSION_CODES#M}, {@code Bundle} or {@code Bundle[]}
+ * </ul>
+ *
+ * <p>NOTE: The method performs disk I/O and shouldn't be called on the main thread
+ *
+ * @return a {@link List} of {@link Bundle} containing the restrictions set by admins for that
+ * package. Returns an empty {@link List} if there are no saved restrictions.
+ *
+ * @see UserManager#KEY_RESTRICTIONS_PENDING
+ */
+ @WorkerThread
+ @UserHandleAware
+ public @NonNull List<Bundle> getApplicationRestrictionsPerAdmin() {
+ try {
+ if (mService != null) {
+ return mService.getApplicationRestrictionsPerAdminForUser(
+ mContext.getUserId(), mContext.getPackageName());
+ }
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ return null;
+ }
+
+ /**
* Called by an application to check if there is an active Restrictions Provider. If
* there isn't, {@link #requestPermission(String, String, PersistableBundle)} is not available.
*
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index c3531bdd7d4c..9c55ad692f42 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -5587,7 +5587,17 @@ public class UserManager {
* if there are no saved restrictions.
*
* @see #KEY_RESTRICTIONS_PENDING
+ *
+ * @deprecated Use
+ * {@link android.content.RestrictionsManager#getApplicationRestrictionsPerAdmin} instead.
+ * Starting from Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, it is
+ * possible for there to be multiple managing agents on the device with the ability to set
+ * restrictions. This API will only to return the restrictions set by device policy controllers
+ * (DPCs)
+ *
+ * @see DevicePolicyManager
*/
+ @Deprecated
@WorkerThread
@UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.TIRAMISU)
public Bundle getApplicationRestrictions(String packageName) {
@@ -5600,8 +5610,12 @@ public class UserManager {
}
/**
+ * @deprecated Use
+ * {@link android.content.RestrictionsManager#getApplicationRestrictionsPerAdmin} instead.
+ *
* @hide
*/
+ @Deprecated
@WorkerThread
public Bundle getApplicationRestrictions(String packageName, UserHandle user) {
try {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 2ffae7fd865d..19a0e03a9329 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -5928,11 +5928,21 @@ public class UserManagerService extends IUserManager.Stub {
/* receiverPermission= */null);
}
+ /**
+ * @deprecated Use {@link
+ * android.content.RestrictionsManager#getApplicationRestrictionsPerAdmin} instead.
+ */
+ @Deprecated
@Override
public Bundle getApplicationRestrictions(String packageName) {
return getApplicationRestrictionsForUser(packageName, UserHandle.getCallingUserId());
}
+ /**
+ * @deprecated Use {@link
+ * android.content.RestrictionsManager#getApplicationRestrictionsPerAdmin} instead.
+ */
+ @Deprecated
@Override
public Bundle getApplicationRestrictionsForUser(String packageName, @UserIdInt int userId) {
if (UserHandle.getCallingUserId() != userId
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a44815ec7313..05876a1ea8cc 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -11021,6 +11021,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
? null : policies.entrySet().stream().findAny().get().getValue().getValue();
}
+ private int getUidForPackage(String packageName, int userId) {
+ return mInjector.binderWithCleanCallingIdentity(() -> {
+ try {
+ return mContext.getPackageManager().getApplicationInfoAsUser(
+ packageName, /* flags= */ 0, userId).uid;
+ } catch (NameNotFoundException exception) {
+ return -1;
+ }
+ });
+ }
+
@Override
public void setTrustAgentConfiguration(
ComponentName admin, String callerPackageName, ComponentName agent,
@@ -15010,33 +15021,38 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
- public Map<String, Bundle> getApplicationRestrictionsPerAdmin(
- String packageName, int userId) {
+ public List<Bundle> getApplicationRestrictionsPerAdminForUser(
+ String packageName, @UserIdInt int userId) {
+ if (UserHandle.getCallingUserId() != userId
+ || !UserHandle.isSameApp(
+ Binder.getCallingUid(), getUidForPackage(packageName, userId))) {
+ final int uid = Binder.getCallingUid();
+ if (!UserHandle.isSameApp(uid, Process.SYSTEM_UID) && uid != Process.ROOT_UID) {
+ throw new SecurityException("Only system may: get application restrictions for "
+ + "other user/app " + packageName);
+ }
+ }
LinkedHashMap<EnforcingAdmin, PolicyValue<Bundle>> policies =
mDevicePolicyEngine.getLocalPoliciesSetByAdmins(
PolicyDefinition.APPLICATION_RESTRICTIONS(packageName),
userId);
- Map<String, Bundle> restrictions = new HashMap<>();
+ List<Bundle> restrictions = new ArrayList<>();
for (EnforcingAdmin admin : policies.keySet()) {
- restrictions.put(admin.getPackageName(), policies.get(admin).getValue());
+ restrictions.add(policies.get(admin).getValue());
}
if (!restrictions.isEmpty()) {
return restrictions;
}
return mInjector.binderWithCleanCallingIdentity(() -> {
- // Could be a device that hasn't migrated yet, so just return any restrictions saved
- // in userManager.
+ // Could be a device that has a DPC that hasn't migrated yet, so just return any
+ // restrictions saved in userManager.
Bundle bundle = mUserManager.getApplicationRestrictions(
packageName, UserHandle.of(userId));
if (bundle == null || bundle.isEmpty()) {
- return new HashMap<>();
- }
- ActiveAdmin admin = getMostProbableDPCAdminForLocalPolicy(userId);
- if (admin == null) {
- return new HashMap<>();
+ return new ArrayList<>();
}
- return Map.of(admin.info.getPackageName(), bundle);
+ return List.of(bundle);
});
}
}
diff --git a/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java b/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
index 62dbd89c48cb..9f0e2f561582 100644
--- a/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
+++ b/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
@@ -16,12 +16,14 @@
package com.android.server.restrictions;
+import android.annotation.UserIdInt;
import android.app.AppGlobals;
+import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.IDevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
import android.content.IRestrictionsManager;
+import android.content.Intent;
import android.content.RestrictionsManager;
import android.content.pm.ResolveInfo;
import android.os.Binder;
@@ -35,6 +37,9 @@ import android.util.Log;
import com.android.internal.util.ArrayUtils;
import com.android.server.SystemService;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* SystemService wrapper for the RestrictionsManager implementation. Publishes the
* Context.RESTRICTIONS_SERVICE.
@@ -60,19 +65,31 @@ public final class RestrictionsManagerService extends SystemService {
final Context mContext;
private final IUserManager mUm;
private final IDevicePolicyManager mDpm;
+ private final DevicePolicyManagerInternal mDpmInternal;
public RestrictionsManagerImpl(Context context) {
mContext = context;
mUm = (IUserManager) getBinderService(Context.USER_SERVICE);
mDpm = (IDevicePolicyManager) getBinderService(Context.DEVICE_POLICY_SERVICE);
+ mDpmInternal = getLocalService(DevicePolicyManagerInternal.class);
}
@Override
+ @Deprecated
public Bundle getApplicationRestrictions(String packageName) throws RemoteException {
return mUm.getApplicationRestrictions(packageName);
}
@Override
+ public List<Bundle> getApplicationRestrictionsPerAdminForUser(
+ @UserIdInt int userId, String packageName) throws RemoteException {
+ if (mDpmInternal != null) {
+ return mDpmInternal.getApplicationRestrictionsPerAdminForUser(packageName, userId);
+ }
+ return new ArrayList<>();
+ }
+
+ @Override
public boolean hasRestrictionsProvider() throws RemoteException {
int userHandle = UserHandle.getCallingUserId();
if (mDpm != null) {