Merge "Add a DPM api to check if a pkg is restricted to use metered data."
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3b4511e..131abb5 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -8261,7 +8261,7 @@
}
/**
- * Called by a device or profile owner to restrict packages from accessing metered data.
+ * Called by a device or profile owner to restrict packages from using metered data.
*
* @param admin which {@link DeviceAdminReceiver} this request is associated with.
* @param packageNames the list of package names to be restricted.
@@ -8283,7 +8283,7 @@
/**
* Called by a device or profile owner to retrieve the list of packages which are restricted
- * by the admin from accessing metered data.
+ * by the admin from using metered data.
*
* @param admin which {@link DeviceAdminReceiver} this request is associated with.
* @return the list of restricted package names.
@@ -8302,6 +8302,30 @@
}
/**
+ * Called by the system to check if a package is restricted from using metered data
+ * by {@param admin}.
+ *
+ * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+ * @param packageName the package whose restricted status is needed.
+ * @param userId the user to which {@param packageName} belongs.
+ * @return {@code true} if the package is restricted by admin, otherwise {@code false}
+ * @throws SecurityException if the caller doesn't run with {@link Process#SYSTEM_UID}
+ * @hide
+ */
+ public boolean isMeteredDataDisabledForUser(@NonNull ComponentName admin, String packageName,
+ @UserIdInt int userId) {
+ throwIfParentInstance("getMeteredDataDisabledForUser");
+ if (mService != null) {
+ try {
+ return mService.isMeteredDataDisabledForUser(admin, packageName, userId);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ return false;
+ }
+
+ /**
* Called by device owners to retrieve device logs from before the device's last reboot.
* <p>
* <strong> This API is not supported on all devices. Calling this API on unsupported devices
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 7fc31b1..cba9311 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -413,4 +413,6 @@
List<ApnSetting> getOverrideApns(in ComponentName admin);
void setOverrideApnsEnabled(in ComponentName admin, boolean enabled);
boolean isOverrideApnEnabled(in ComponentName admin);
+
+ boolean isMeteredDataDisabledForUser(in ComponentName admin, String packageName, int userId);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index fce5dd9..7728f66 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -363,6 +363,26 @@
}
/**
+ * Check if {@param packageName} is restricted by the profile or device owner from using
+ * metered data.
+ *
+ * @return EnforcedAdmin object containing the enforced admin component and admin user details,
+ * or {@code null} if the {@param packageName} is not restricted.
+ */
+ public static EnforcedAdmin checkIfMeteredDataRestricted(Context context,
+ String packageName, int userId) {
+ final EnforcedAdmin enforcedAdmin = getProfileOrDeviceOwner(context, userId);
+ if (enforcedAdmin == null) {
+ return null;
+ }
+
+ final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ return dpm.isMeteredDataDisabledForUser(enforcedAdmin.component, packageName, userId)
+ ? enforcedAdmin : null;
+ }
+
+ /**
* Checks if {@link android.app.admin.DevicePolicyManager#setAutoTimeRequired} is enforced
* on the device.
*
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 5c73d54..3a0ae9f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -48,6 +48,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
import android.text.format.Formatter;
import android.util.IconDrawableFactory;
import android.util.Log;
@@ -1282,7 +1283,8 @@
// A location where extra info can be placed to be used by custom filters.
public Object extraInfo;
- AppEntry(Context context, ApplicationInfo info, long id) {
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+ public AppEntry(Context context, ApplicationInfo info, long id) {
apkFile = new File(info.sourceDir);
this.id = id;
this.info = info;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 5529426..d1cc5de 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -178,4 +178,10 @@
public void clearSystemUpdatePolicyFreezePeriodRecord() {
}
+
+ @Override
+ public boolean isMeteredDataDisabledForUser(ComponentName admin,
+ String packageName, int userId) {
+ return false;
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 7d1b38b..dae7605 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -11410,6 +11410,27 @@
}
}
+ @Override
+ public boolean isMeteredDataDisabledForUser(ComponentName who,
+ String packageName, int userId) {
+ Preconditions.checkNotNull(who);
+
+ if (!mHasFeature) {
+ return false;
+ }
+ if (!isCallerWithSystemUid()) {
+ throw new SecurityException(
+ "Only the system can query restricted pkgs for a specific user");
+ }
+ synchronized (this) {
+ final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userId);
+ if (admin != null && admin.meteredDisabledPackages != null) {
+ return admin.meteredDisabledPackages.contains(packageName);
+ }
+ }
+ return false;
+ }
+
private void pushMeteredDisabledPackagesLocked(int userId) {
mInjector.getNetworkPolicyManagerInternal().setMeteredRestrictedPackages(
getMeteredDisabledPackagesLocked(userId), userId);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 6b87ea9..00a85a5 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -2160,6 +2160,51 @@
() -> dpm.getMeteredDataDisabled(admin1));
}
+ public void testGetMeteredDataDisabledForUser() throws Exception {
+ setAsProfileOwner(admin1);
+
+ // Setup
+ final ArrayList<String> emptyList = new ArrayList<>();
+ final ArrayList<String> pkgsToRestrict = new ArrayList<>();
+ final String package1 = "com.example.one";
+ final String package2 = "com.example.two";
+ final String package3 = "com.example.three";
+ pkgsToRestrict.add(package1);
+ pkgsToRestrict.add(package2);
+ setupPackageInPackageManager(package1, DpmMockContext.CALLER_USER_HANDLE, 123, 0);
+ setupPackageInPackageManager(package2, DpmMockContext.CALLER_USER_HANDLE, 456, 0);
+ List<String> excludedPkgs = dpm.setMeteredDataDisabled(admin1, pkgsToRestrict);
+
+ // Verify
+ assertEquals(emptyList, excludedPkgs);
+ mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
+ assertTrue(package1 + "should be restricted",
+ dpm.isMeteredDataDisabledForUser(admin1, package1,
+ DpmMockContext.CALLER_USER_HANDLE));
+ assertTrue(package2 + "should be restricted",
+ dpm.isMeteredDataDisabledForUser(admin1, package2,
+ DpmMockContext.CALLER_USER_HANDLE));
+ assertFalse(package3 + "should not be restricted",
+ dpm.isMeteredDataDisabledForUser(admin1, package3,
+ DpmMockContext.CALLER_USER_HANDLE));
+ }
+
+ public void testGetMeteredDataDisabledForUser_nonSystemUidCaller() throws Exception {
+ setAsProfileOwner(admin1);
+ assertExpectException(SecurityException.class,
+ /* messageRegex= */ "Only the system can query restricted pkgs",
+ () -> dpm.isMeteredDataDisabledForUser(
+ admin1, "com.example.one", DpmMockContext.CALLER_USER_HANDLE));
+ dpm.clearProfileOwner(admin1);
+
+ setDeviceOwner();
+ assertExpectException(SecurityException.class,
+ /* messageRegex= */ "Only the system can query restricted pkgs",
+ () -> dpm.isMeteredDataDisabledForUser(
+ admin1, "com.example.one", DpmMockContext.CALLER_USER_HANDLE));
+ clearDeviceOwner();
+ }
+
public void testCreateAdminSupportIntent() throws Exception {
// Setup device owner.
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;