Loading core/java/android/app/admin/DevicePolicyManager.java +6 −6 Original line number Diff line number Diff line Loading @@ -13401,11 +13401,10 @@ public class DevicePolicyManager { /** * Called by a device admin or holder of the permission * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE} to set the short * support message. This will be displayed to the user * in settings screens where funtionality has been disabled by the admin. The message should be * limited to a short statement such as "This setting is disabled by your administrator. Contact * someone@example.com for support." If the message is longer than 200 characters it may be * truncated. * support message. This will be displayed to the user in settings screens where functionality * has been disabled by the admin. The message should be limited to a short statement such as * "This setting is disabled by your administrator. Contact someone@example.com for support." * If the message is longer than 200 characters it may be truncated. * <p> * If the short support message needs to be localized, it is the responsibility of the * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast Loading Loading @@ -13460,7 +13459,8 @@ public class DevicePolicyManager { /** * Called by a device admin to set the long support message. This will be displayed to the user * in the device administators settings screen. * in the device administrators settings screen. If the message is longer than 20000 characters * it may be truncated. * <p> * If the long support message needs to be localized, it is the responsibility of the * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +94 −6 Original line number Diff line number Diff line Loading @@ -39,7 +39,6 @@ import static android.Manifest.permission.MANAGE_DEVICE_POLICY_DEFAULT_SMS; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_DISPLAY; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_FACTORY_RESET; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_FUN; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_INPUT_METHODS; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_KEYGUARD; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCALE; Loading Loading @@ -521,6 +520,7 @@ import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.text.DateFormat; import java.time.LocalDate; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; Loading @@ -533,6 +533,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Queue; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; Loading Loading @@ -568,7 +569,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final int REQUEST_PROFILE_OFF_DEADLINE = 5572; // Binary XML serializer doesn't support longer strings private static final int MAX_POLICY_STRING_LENGTH = 65535; // FrameworkParsingPackageUtils#MAX_FILE_NAME_SIZE, Android packages are used in dir names. private static final int MAX_PACKAGE_NAME_LENGTH = 223; private static final int MAX_PROFILE_NAME_LENGTH = 200; private static final int MAX_LONG_SUPPORT_MESSAGE_LENGTH = 20000; private static final int MAX_SHORT_SUPPORT_MESSAGE_LENGTH = 200; private static final int MAX_ORG_NAME_LENGTH = 200; private static final long MS_PER_DAY = TimeUnit.DAYS.toMillis(1); Loading Loading @@ -11730,7 +11739,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } Objects.requireNonNull(agent, "agent is null"); int userHandle = UserHandle.getCallingUserId(); enforceMaxPackageNameLength(agent.getPackageName()); final String agentAsString = agent.flattenToString(); enforceMaxStringLength(agentAsString, "agent name"); if (args != null) { enforceMaxStringLength(args, "args"); } int userHandle = mInjector.userHandleGetCallingUserId(); synchronized (getLockObject()) { ActiveAdmin ap; if (isPermissionCheckFlagEnabled()) { Loading @@ -11747,7 +11764,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { checkCanExecuteOrThrowUnsafe( DevicePolicyManager.OPERATION_SET_TRUST_AGENT_CONFIGURATION); ap.trustAgentInfos.put(agent.flattenToString(), new TrustAgentInfo(args)); ap.trustAgentInfos.put(agentAsString, new TrustAgentInfo(args)); saveSettingsLocked(userHandle); } } Loading Loading @@ -12017,6 +12034,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { isDeviceOwner(caller) || isProfileOwner(caller)); if (packageList != null) { for (String pkg : packageList) { enforceMaxPackageNameLength(pkg); } int userId = caller.getUserId(); final List<AccessibilityServiceInfo> enabledServices; long id = mInjector.binderClearCallingIdentity(); Loading Loading @@ -12198,6 +12219,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } if (packageList != null) { for (String pkg : packageList) { enforceMaxPackageNameLength(pkg); } List<InputMethodInfo> enabledImes = mInjector.binderWithCleanCallingIdentity(() -> InputMethodManagerInternal.get().getEnabledInputMethodListAsUser(userId)); if (enabledImes != null) { Loading Loading @@ -14082,6 +14107,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return; } enforceMaxStringLength(accountType, "account type"); CallerIdentity caller; if (isPermissionCheckFlagEnabled()) { caller = getCallerIdentity(who, callerPackageName); Loading Loading @@ -14772,6 +14800,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { public void setLockTaskPackages(ComponentName who, String callerPackageName, String[] packages) throws SecurityException { Objects.requireNonNull(packages, "packages is null"); for (String pkg : packages) { enforceMaxPackageNameLength(pkg); } CallerIdentity caller; if (isPolicyEngineForFinanceFlagEnabled()) { caller = getCallerIdentity(who, callerPackageName); Loading Loading @@ -17374,6 +17406,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { CallerIdentity caller; ActiveAdmin admin; message = truncateIfLonger(message, MAX_SHORT_SUPPORT_MESSAGE_LENGTH); if (isPermissionCheckFlagEnabled()) { caller = getCallerIdentity(who, callerPackageName); EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin( Loading Loading @@ -17434,6 +17468,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return; } message = truncateIfLonger(message, MAX_LONG_SUPPORT_MESSAGE_LENGTH); Objects.requireNonNull(who, "ComponentName is null"); final CallerIdentity caller = getCallerIdentity(who); synchronized (getLockObject()) { Loading Loading @@ -17598,6 +17635,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller)); } text = truncateIfLonger(text, MAX_ORG_NAME_LENGTH); synchronized (getLockObject()) { if (!isPermissionCheckFlagEnabled()) { admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()); Loading Loading @@ -17878,9 +17917,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { throw new IllegalArgumentException("ids must not be null"); } for (String id : ids) { if (TextUtils.isEmpty(id)) { throw new IllegalArgumentException("ids must not contain empty string"); } Preconditions.checkArgument(!TextUtils.isEmpty(id), "ids must not have empty string"); enforceMaxStringLength(id, "affiliation id"); } final Set<String> affiliationIds = new ArraySet<>(ids); Loading Loading @@ -19393,6 +19431,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { "Provided administrator and target are the same object."); Preconditions.checkArgument(!admin.getPackageName().equals(target.getPackageName()), "Provided administrator and target have the same package name."); if (bundle != null) { enforceMaxStringLength(bundle, "bundle"); } final CallerIdentity caller = getCallerIdentity(admin); Preconditions.checkCallAuthorization( Loading Loading @@ -24137,6 +24178,53 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { }); } /** * Truncates char sequence to maximum length, nulls are ignored. */ private static CharSequence truncateIfLonger(CharSequence input, int maxLength) { return input == null || input.length() <= maxLength ? input : input.subSequence(0, maxLength); } /** * Throw if string argument is too long to be serialized. */ private static void enforceMaxStringLength(String str, String argName) { Preconditions.checkArgument( str.length() <= MAX_POLICY_STRING_LENGTH, argName + " loo long"); } private static void enforceMaxPackageNameLength(String pkg) { Preconditions.checkArgument( pkg.length() <= MAX_PACKAGE_NAME_LENGTH, "Package name too long"); } /** * Throw if persistable bundle contains any string that we can't serialize. */ private static void enforceMaxStringLength(PersistableBundle bundle, String argName) { // Persistable bundles can have other persistable bundles as values, traverse with a queue. Queue<PersistableBundle> queue = new ArrayDeque<>(); queue.add(bundle); while (!queue.isEmpty()) { PersistableBundle current = queue.remove(); for (String key : current.keySet()) { enforceMaxStringLength(key, "key in " + argName); Object value = current.get(key); if (value instanceof String) { enforceMaxStringLength((String) value, "string value in " + argName); } else if (value instanceof String[]) { for (String str : (String[]) value) { enforceMaxStringLength(str, "string value in " + argName); } } else if (value instanceof PersistableBundle) { queue.add((PersistableBundle) value); } } } } private ActiveAdmin getActiveAdminForCaller(@Nullable ComponentName who, CallerIdentity caller) { synchronized (getLockObject()) { services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +41 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.IpcDataCache; import android.os.PersistableBundle; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; Loading Loading @@ -8526,6 +8527,46 @@ public class DevicePolicyManagerTest extends DpmTestBase { eq(FUSED_PROVIDER), any(), eq(getServices().executor), any()); } /** * Verifies that bundles with tons of moderately long strings are persisted correctly. * * Policy is serialized into binary XML and there is a limit on the max string length: 65535. * This test ensures that as long as each string in the trust agent configuration is below this * limit, the policy can be serialized and deserialized correctly, even when the total length * of the configuration is above that limit. This should be the case because PersistableBundle * contents are stored as XML subtrees rather than as strings. */ @Test public void testSetTrustAgentConfiguration_largeBundlePersisted() { setAsProfileOwner(admin1); ComponentName agent = new ComponentName("some.trust.agent", "some.trust.agent.Agent"); PersistableBundle configIn = new PersistableBundle(); String kilobyteString = new String(new char[1024]).replace('\0', 'A'); for (int i = 0; i < 1024; i++) { configIn.putString("key-" + i, kilobyteString); } runAsCaller(mAdmin1Context, dpms, dpm -> { dpm.setTrustAgentConfiguration(admin1, agent, configIn); }); // Re-read policies to see if they were serialized/deserialized correctly. initializeDpms(); List<PersistableBundle> configsOut = new ArrayList<>(); runAsCaller(mAdmin1Context, dpms, dpm -> { configsOut.addAll(dpm.getTrustAgentConfiguration(admin1, agent)); }); assertThat(configsOut.size()).isEqualTo(1); PersistableBundle configOut = configsOut.get(0); assertThat(configOut.size()).isEqualTo(1024); for (int i = 0; i < 1024; i++) { assertThat(configOut.getString("key-" + i, null)).isEqualTo(kilobyteString); } } private void setupVpnAuthorization(String userVpnPackage, int userVpnUid) { final AppOpsManager.PackageOps vpnOp = new AppOpsManager.PackageOps(userVpnPackage, userVpnUid, List.of(new AppOpsManager.OpEntry( Loading Loading
core/java/android/app/admin/DevicePolicyManager.java +6 −6 Original line number Diff line number Diff line Loading @@ -13401,11 +13401,10 @@ public class DevicePolicyManager { /** * Called by a device admin or holder of the permission * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE} to set the short * support message. This will be displayed to the user * in settings screens where funtionality has been disabled by the admin. The message should be * limited to a short statement such as "This setting is disabled by your administrator. Contact * someone@example.com for support." If the message is longer than 200 characters it may be * truncated. * support message. This will be displayed to the user in settings screens where functionality * has been disabled by the admin. The message should be limited to a short statement such as * "This setting is disabled by your administrator. Contact someone@example.com for support." * If the message is longer than 200 characters it may be truncated. * <p> * If the short support message needs to be localized, it is the responsibility of the * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast Loading Loading @@ -13460,7 +13459,8 @@ public class DevicePolicyManager { /** * Called by a device admin to set the long support message. This will be displayed to the user * in the device administators settings screen. * in the device administrators settings screen. If the message is longer than 20000 characters * it may be truncated. * <p> * If the long support message needs to be localized, it is the responsibility of the * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +94 −6 Original line number Diff line number Diff line Loading @@ -39,7 +39,6 @@ import static android.Manifest.permission.MANAGE_DEVICE_POLICY_DEFAULT_SMS; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_DISPLAY; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_FACTORY_RESET; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_FUN; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_INPUT_METHODS; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_KEYGUARD; import static android.Manifest.permission.MANAGE_DEVICE_POLICY_LOCALE; Loading Loading @@ -521,6 +520,7 @@ import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.text.DateFormat; import java.time.LocalDate; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; Loading @@ -533,6 +533,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Queue; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; Loading Loading @@ -568,7 +569,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final int REQUEST_PROFILE_OFF_DEADLINE = 5572; // Binary XML serializer doesn't support longer strings private static final int MAX_POLICY_STRING_LENGTH = 65535; // FrameworkParsingPackageUtils#MAX_FILE_NAME_SIZE, Android packages are used in dir names. private static final int MAX_PACKAGE_NAME_LENGTH = 223; private static final int MAX_PROFILE_NAME_LENGTH = 200; private static final int MAX_LONG_SUPPORT_MESSAGE_LENGTH = 20000; private static final int MAX_SHORT_SUPPORT_MESSAGE_LENGTH = 200; private static final int MAX_ORG_NAME_LENGTH = 200; private static final long MS_PER_DAY = TimeUnit.DAYS.toMillis(1); Loading Loading @@ -11730,7 +11739,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } Objects.requireNonNull(agent, "agent is null"); int userHandle = UserHandle.getCallingUserId(); enforceMaxPackageNameLength(agent.getPackageName()); final String agentAsString = agent.flattenToString(); enforceMaxStringLength(agentAsString, "agent name"); if (args != null) { enforceMaxStringLength(args, "args"); } int userHandle = mInjector.userHandleGetCallingUserId(); synchronized (getLockObject()) { ActiveAdmin ap; if (isPermissionCheckFlagEnabled()) { Loading @@ -11747,7 +11764,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { checkCanExecuteOrThrowUnsafe( DevicePolicyManager.OPERATION_SET_TRUST_AGENT_CONFIGURATION); ap.trustAgentInfos.put(agent.flattenToString(), new TrustAgentInfo(args)); ap.trustAgentInfos.put(agentAsString, new TrustAgentInfo(args)); saveSettingsLocked(userHandle); } } Loading Loading @@ -12017,6 +12034,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { isDeviceOwner(caller) || isProfileOwner(caller)); if (packageList != null) { for (String pkg : packageList) { enforceMaxPackageNameLength(pkg); } int userId = caller.getUserId(); final List<AccessibilityServiceInfo> enabledServices; long id = mInjector.binderClearCallingIdentity(); Loading Loading @@ -12198,6 +12219,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } if (packageList != null) { for (String pkg : packageList) { enforceMaxPackageNameLength(pkg); } List<InputMethodInfo> enabledImes = mInjector.binderWithCleanCallingIdentity(() -> InputMethodManagerInternal.get().getEnabledInputMethodListAsUser(userId)); if (enabledImes != null) { Loading Loading @@ -14082,6 +14107,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return; } enforceMaxStringLength(accountType, "account type"); CallerIdentity caller; if (isPermissionCheckFlagEnabled()) { caller = getCallerIdentity(who, callerPackageName); Loading Loading @@ -14772,6 +14800,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { public void setLockTaskPackages(ComponentName who, String callerPackageName, String[] packages) throws SecurityException { Objects.requireNonNull(packages, "packages is null"); for (String pkg : packages) { enforceMaxPackageNameLength(pkg); } CallerIdentity caller; if (isPolicyEngineForFinanceFlagEnabled()) { caller = getCallerIdentity(who, callerPackageName); Loading Loading @@ -17374,6 +17406,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { CallerIdentity caller; ActiveAdmin admin; message = truncateIfLonger(message, MAX_SHORT_SUPPORT_MESSAGE_LENGTH); if (isPermissionCheckFlagEnabled()) { caller = getCallerIdentity(who, callerPackageName); EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin( Loading Loading @@ -17434,6 +17468,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return; } message = truncateIfLonger(message, MAX_LONG_SUPPORT_MESSAGE_LENGTH); Objects.requireNonNull(who, "ComponentName is null"); final CallerIdentity caller = getCallerIdentity(who); synchronized (getLockObject()) { Loading Loading @@ -17598,6 +17635,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller)); } text = truncateIfLonger(text, MAX_ORG_NAME_LENGTH); synchronized (getLockObject()) { if (!isPermissionCheckFlagEnabled()) { admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()); Loading Loading @@ -17878,9 +17917,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { throw new IllegalArgumentException("ids must not be null"); } for (String id : ids) { if (TextUtils.isEmpty(id)) { throw new IllegalArgumentException("ids must not contain empty string"); } Preconditions.checkArgument(!TextUtils.isEmpty(id), "ids must not have empty string"); enforceMaxStringLength(id, "affiliation id"); } final Set<String> affiliationIds = new ArraySet<>(ids); Loading Loading @@ -19393,6 +19431,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { "Provided administrator and target are the same object."); Preconditions.checkArgument(!admin.getPackageName().equals(target.getPackageName()), "Provided administrator and target have the same package name."); if (bundle != null) { enforceMaxStringLength(bundle, "bundle"); } final CallerIdentity caller = getCallerIdentity(admin); Preconditions.checkCallAuthorization( Loading Loading @@ -24137,6 +24178,53 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { }); } /** * Truncates char sequence to maximum length, nulls are ignored. */ private static CharSequence truncateIfLonger(CharSequence input, int maxLength) { return input == null || input.length() <= maxLength ? input : input.subSequence(0, maxLength); } /** * Throw if string argument is too long to be serialized. */ private static void enforceMaxStringLength(String str, String argName) { Preconditions.checkArgument( str.length() <= MAX_POLICY_STRING_LENGTH, argName + " loo long"); } private static void enforceMaxPackageNameLength(String pkg) { Preconditions.checkArgument( pkg.length() <= MAX_PACKAGE_NAME_LENGTH, "Package name too long"); } /** * Throw if persistable bundle contains any string that we can't serialize. */ private static void enforceMaxStringLength(PersistableBundle bundle, String argName) { // Persistable bundles can have other persistable bundles as values, traverse with a queue. Queue<PersistableBundle> queue = new ArrayDeque<>(); queue.add(bundle); while (!queue.isEmpty()) { PersistableBundle current = queue.remove(); for (String key : current.keySet()) { enforceMaxStringLength(key, "key in " + argName); Object value = current.get(key); if (value instanceof String) { enforceMaxStringLength((String) value, "string value in " + argName); } else if (value instanceof String[]) { for (String str : (String[]) value) { enforceMaxStringLength(str, "string value in " + argName); } } else if (value instanceof PersistableBundle) { queue.add((PersistableBundle) value); } } } } private ActiveAdmin getActiveAdminForCaller(@Nullable ComponentName who, CallerIdentity caller) { synchronized (getLockObject()) {
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +41 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ import android.os.Build; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.IpcDataCache; import android.os.PersistableBundle; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; Loading Loading @@ -8526,6 +8527,46 @@ public class DevicePolicyManagerTest extends DpmTestBase { eq(FUSED_PROVIDER), any(), eq(getServices().executor), any()); } /** * Verifies that bundles with tons of moderately long strings are persisted correctly. * * Policy is serialized into binary XML and there is a limit on the max string length: 65535. * This test ensures that as long as each string in the trust agent configuration is below this * limit, the policy can be serialized and deserialized correctly, even when the total length * of the configuration is above that limit. This should be the case because PersistableBundle * contents are stored as XML subtrees rather than as strings. */ @Test public void testSetTrustAgentConfiguration_largeBundlePersisted() { setAsProfileOwner(admin1); ComponentName agent = new ComponentName("some.trust.agent", "some.trust.agent.Agent"); PersistableBundle configIn = new PersistableBundle(); String kilobyteString = new String(new char[1024]).replace('\0', 'A'); for (int i = 0; i < 1024; i++) { configIn.putString("key-" + i, kilobyteString); } runAsCaller(mAdmin1Context, dpms, dpm -> { dpm.setTrustAgentConfiguration(admin1, agent, configIn); }); // Re-read policies to see if they were serialized/deserialized correctly. initializeDpms(); List<PersistableBundle> configsOut = new ArrayList<>(); runAsCaller(mAdmin1Context, dpms, dpm -> { configsOut.addAll(dpm.getTrustAgentConfiguration(admin1, agent)); }); assertThat(configsOut.size()).isEqualTo(1); PersistableBundle configOut = configsOut.get(0); assertThat(configOut.size()).isEqualTo(1024); for (int i = 0; i < 1024; i++) { assertThat(configOut.getString("key-" + i, null)).isEqualTo(kilobyteString); } } private void setupVpnAuthorization(String userVpnPackage, int userVpnUid) { final AppOpsManager.PackageOps vpnOp = new AppOpsManager.PackageOps(userVpnPackage, userVpnUid, List.of(new AppOpsManager.OpEntry( Loading