diff options
7 files changed, 123 insertions, 3 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 3b4511e4e0e3..131abb5e4664 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -8261,7 +8261,7 @@ public class DevicePolicyManager { } /** - * 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 @@ public class DevicePolicyManager { /** * 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 @@ public class DevicePolicyManager { } /** + * 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 7fc31b1a639d..cba9311ff68b 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -413,4 +413,6 @@ interface IDevicePolicyManager { 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 fce5dd9cb828..7728f667ea51 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java @@ -363,6 +363,26 @@ public class RestrictedLockUtils { } /** + * 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 5c73d5485e2a..3a0ae9f532bb 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.RemoteException; 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 @@ public class ApplicationsState { // 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 552942614db7..d1cc5de821c7 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 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { 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 7d1b38be532e..dae760576b4f 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } + @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 6b87ea965686..00a85a539538 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 @@ public class DevicePolicyManagerTest extends DpmTestBase { () -> 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; |