Save password history length when requested quality is unspecified.
Refactored code to remove duplication in writeToXml method in the DevicePolicyManagerService class.
Bug: 32907000
Test: Atest DevicePolicyManagerTest
manual testing
Change-Id: I2714b6a081dcaa0a07ce24a73cc97378a4b58808
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 478bc88..c05e01a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1113,142 +1113,107 @@
info.writePoliciesToXml(out);
out.endTag(null, TAG_POLICIES);
if (minimumPasswordMetrics.quality != PASSWORD_QUALITY_UNSPECIFIED) {
- out.startTag(null, TAG_PASSWORD_QUALITY);
- out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordMetrics.quality));
- out.endTag(null, TAG_PASSWORD_QUALITY);
+ writeAttributeValueToXml(
+ out, TAG_PASSWORD_QUALITY, minimumPasswordMetrics.quality);
if (minimumPasswordMetrics.length != DEF_MINIMUM_PASSWORD_LENGTH) {
- out.startTag(null, TAG_MIN_PASSWORD_LENGTH);
- out.attribute(
- null, ATTR_VALUE, Integer.toString(minimumPasswordMetrics.length));
- out.endTag(null, TAG_MIN_PASSWORD_LENGTH);
- }
- if(passwordHistoryLength != DEF_PASSWORD_HISTORY_LENGTH) {
- out.startTag(null, TAG_PASSWORD_HISTORY_LENGTH);
- out.attribute(null, ATTR_VALUE, Integer.toString(passwordHistoryLength));
- out.endTag(null, TAG_PASSWORD_HISTORY_LENGTH);
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_LENGTH, minimumPasswordMetrics.length);
}
if (minimumPasswordMetrics.upperCase != DEF_MINIMUM_PASSWORD_UPPER_CASE) {
- out.startTag(null, TAG_MIN_PASSWORD_UPPERCASE);
- out.attribute(
- null, ATTR_VALUE, Integer.toString(minimumPasswordMetrics.upperCase));
- out.endTag(null, TAG_MIN_PASSWORD_UPPERCASE);
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_UPPERCASE, minimumPasswordMetrics.upperCase);
}
if (minimumPasswordMetrics.lowerCase != DEF_MINIMUM_PASSWORD_LOWER_CASE) {
- out.startTag(null, TAG_MIN_PASSWORD_LOWERCASE);
- out.attribute(
- null, ATTR_VALUE, Integer.toString(minimumPasswordMetrics.lowerCase));
- out.endTag(null, TAG_MIN_PASSWORD_LOWERCASE);
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_LOWERCASE, minimumPasswordMetrics.lowerCase);
}
if (minimumPasswordMetrics.letters != DEF_MINIMUM_PASSWORD_LETTERS) {
- out.startTag(null, TAG_MIN_PASSWORD_LETTERS);
- out.attribute(
- null, ATTR_VALUE, Integer.toString(minimumPasswordMetrics.letters));
- out.endTag(null, TAG_MIN_PASSWORD_LETTERS);
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_LETTERS, minimumPasswordMetrics.letters);
}
if (minimumPasswordMetrics.numeric != DEF_MINIMUM_PASSWORD_NUMERIC) {
- out.startTag(null, TAG_MIN_PASSWORD_NUMERIC);
- out.attribute(
- null, ATTR_VALUE, Integer.toString(minimumPasswordMetrics.numeric));
- out.endTag(null, TAG_MIN_PASSWORD_NUMERIC);
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_NUMERIC, minimumPasswordMetrics.numeric);
}
if (minimumPasswordMetrics.symbols != DEF_MINIMUM_PASSWORD_SYMBOLS) {
- out.startTag(null, TAG_MIN_PASSWORD_SYMBOLS);
- out.attribute(
- null, ATTR_VALUE, Integer.toString(minimumPasswordMetrics.symbols));
- out.endTag(null, TAG_MIN_PASSWORD_SYMBOLS);
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_SYMBOLS, minimumPasswordMetrics.symbols);
}
if (minimumPasswordMetrics.nonLetter > DEF_MINIMUM_PASSWORD_NON_LETTER) {
- out.startTag(null, TAG_MIN_PASSWORD_NONLETTER);
- out.attribute(
- null, ATTR_VALUE, Integer.toString(minimumPasswordMetrics.nonLetter));
- out.endTag(null, TAG_MIN_PASSWORD_NONLETTER);
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_NONLETTER, minimumPasswordMetrics.nonLetter);
}
}
+ if (passwordHistoryLength != DEF_PASSWORD_HISTORY_LENGTH) {
+ writeAttributeValueToXml(
+ out, TAG_PASSWORD_HISTORY_LENGTH, passwordHistoryLength);
+ }
if (maximumTimeToUnlock != DEF_MAXIMUM_TIME_TO_UNLOCK) {
- out.startTag(null, TAG_MAX_TIME_TO_UNLOCK);
- out.attribute(null, ATTR_VALUE, Long.toString(maximumTimeToUnlock));
- out.endTag(null, TAG_MAX_TIME_TO_UNLOCK);
+ writeAttributeValueToXml(
+ out, TAG_MAX_TIME_TO_UNLOCK, maximumTimeToUnlock);
}
if (strongAuthUnlockTimeout != DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS) {
- out.startTag(null, TAG_STRONG_AUTH_UNLOCK_TIMEOUT);
- out.attribute(null, ATTR_VALUE, Long.toString(strongAuthUnlockTimeout));
- out.endTag(null, TAG_STRONG_AUTH_UNLOCK_TIMEOUT);
+ writeAttributeValueToXml(
+ out, TAG_STRONG_AUTH_UNLOCK_TIMEOUT, strongAuthUnlockTimeout);
}
if (maximumFailedPasswordsForWipe != DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
- out.startTag(null, TAG_MAX_FAILED_PASSWORD_WIPE);
- out.attribute(null, ATTR_VALUE, Integer.toString(maximumFailedPasswordsForWipe));
- out.endTag(null, TAG_MAX_FAILED_PASSWORD_WIPE);
+ writeAttributeValueToXml(
+ out, TAG_MAX_FAILED_PASSWORD_WIPE, maximumFailedPasswordsForWipe);
}
if (specifiesGlobalProxy) {
- out.startTag(null, TAG_SPECIFIES_GLOBAL_PROXY);
- out.attribute(null, ATTR_VALUE, Boolean.toString(specifiesGlobalProxy));
- out.endTag(null, TAG_SPECIFIES_GLOBAL_PROXY);
+ writeAttributeValueToXml(
+ out, TAG_SPECIFIES_GLOBAL_PROXY, specifiesGlobalProxy);
if (globalProxySpec != null) {
- out.startTag(null, TAG_GLOBAL_PROXY_SPEC);
- out.attribute(null, ATTR_VALUE, globalProxySpec);
- out.endTag(null, TAG_GLOBAL_PROXY_SPEC);
+ writeAttributeValueToXml(out, TAG_GLOBAL_PROXY_SPEC, globalProxySpec);
}
if (globalProxyExclusionList != null) {
- out.startTag(null, TAG_GLOBAL_PROXY_EXCLUSION_LIST);
- out.attribute(null, ATTR_VALUE, globalProxyExclusionList);
- out.endTag(null, TAG_GLOBAL_PROXY_EXCLUSION_LIST);
+ writeAttributeValueToXml(
+ out, TAG_GLOBAL_PROXY_EXCLUSION_LIST, globalProxyExclusionList);
}
}
if (passwordExpirationTimeout != DEF_PASSWORD_EXPIRATION_TIMEOUT) {
- out.startTag(null, TAG_PASSWORD_EXPIRATION_TIMEOUT);
- out.attribute(null, ATTR_VALUE, Long.toString(passwordExpirationTimeout));
- out.endTag(null, TAG_PASSWORD_EXPIRATION_TIMEOUT);
+ writeAttributeValueToXml(
+ out, TAG_PASSWORD_EXPIRATION_TIMEOUT, passwordExpirationTimeout);
}
if (passwordExpirationDate != DEF_PASSWORD_EXPIRATION_DATE) {
- out.startTag(null, TAG_PASSWORD_EXPIRATION_DATE);
- out.attribute(null, ATTR_VALUE, Long.toString(passwordExpirationDate));
- out.endTag(null, TAG_PASSWORD_EXPIRATION_DATE);
+ writeAttributeValueToXml(
+ out, TAG_PASSWORD_EXPIRATION_DATE, passwordExpirationDate);
}
if (encryptionRequested) {
- out.startTag(null, TAG_ENCRYPTION_REQUESTED);
- out.attribute(null, ATTR_VALUE, Boolean.toString(encryptionRequested));
- out.endTag(null, TAG_ENCRYPTION_REQUESTED);
+ writeAttributeValueToXml(
+ out, TAG_ENCRYPTION_REQUESTED, encryptionRequested);
}
if (testOnlyAdmin) {
- out.startTag(null, TAG_TEST_ONLY_ADMIN);
- out.attribute(null, ATTR_VALUE, Boolean.toString(testOnlyAdmin));
- out.endTag(null, TAG_TEST_ONLY_ADMIN);
+ writeAttributeValueToXml(
+ out, TAG_TEST_ONLY_ADMIN, testOnlyAdmin);
}
if (disableCamera) {
- out.startTag(null, TAG_DISABLE_CAMERA);
- out.attribute(null, ATTR_VALUE, Boolean.toString(disableCamera));
- out.endTag(null, TAG_DISABLE_CAMERA);
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_CAMERA, disableCamera);
}
if (disableCallerId) {
- out.startTag(null, TAG_DISABLE_CALLER_ID);
- out.attribute(null, ATTR_VALUE, Boolean.toString(disableCallerId));
- out.endTag(null, TAG_DISABLE_CALLER_ID);
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_CALLER_ID, disableCallerId);
}
if (disableContactsSearch) {
- out.startTag(null, TAG_DISABLE_CONTACTS_SEARCH);
- out.attribute(null, ATTR_VALUE, Boolean.toString(disableContactsSearch));
- out.endTag(null, TAG_DISABLE_CONTACTS_SEARCH);
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_CONTACTS_SEARCH, disableContactsSearch);
}
if (!disableBluetoothContactSharing) {
- out.startTag(null, TAG_DISABLE_BLUETOOTH_CONTACT_SHARING);
- out.attribute(null, ATTR_VALUE,
- Boolean.toString(disableBluetoothContactSharing));
- out.endTag(null, TAG_DISABLE_BLUETOOTH_CONTACT_SHARING);
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_BLUETOOTH_CONTACT_SHARING, disableBluetoothContactSharing);
}
if (disableScreenCapture) {
- out.startTag(null, TAG_DISABLE_SCREEN_CAPTURE);
- out.attribute(null, ATTR_VALUE, Boolean.toString(disableScreenCapture));
- out.endTag(null, TAG_DISABLE_SCREEN_CAPTURE);
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_SCREEN_CAPTURE, disableScreenCapture);
}
if (requireAutoTime) {
- out.startTag(null, TAG_REQUIRE_AUTO_TIME);
- out.attribute(null, ATTR_VALUE, Boolean.toString(requireAutoTime));
- out.endTag(null, TAG_REQUIRE_AUTO_TIME);
+ writeAttributeValueToXml(
+ out, TAG_REQUIRE_AUTO_TIME, requireAutoTime);
}
if (forceEphemeralUsers) {
- out.startTag(null, TAG_FORCE_EPHEMERAL_USERS);
- out.attribute(null, ATTR_VALUE, Boolean.toString(forceEphemeralUsers));
- out.endTag(null, TAG_FORCE_EPHEMERAL_USERS);
+ writeAttributeValueToXml(
+ out, TAG_FORCE_EPHEMERAL_USERS, forceEphemeralUsers);
}
if (isNetworkLoggingEnabled) {
out.startTag(null, TAG_IS_NETWORK_LOGGING_ENABLED);
@@ -1260,15 +1225,13 @@
out.endTag(null, TAG_IS_NETWORK_LOGGING_ENABLED);
}
if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
- out.startTag(null, TAG_DISABLE_KEYGUARD_FEATURES);
- out.attribute(null, ATTR_VALUE, Integer.toString(disabledKeyguardFeatures));
- out.endTag(null, TAG_DISABLE_KEYGUARD_FEATURES);
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_KEYGUARD_FEATURES, disabledKeyguardFeatures);
}
if (!accountTypesWithManagementDisabled.isEmpty()) {
- out.startTag(null, TAG_DISABLE_ACCOUNT_MANAGEMENT);
writeAttributeValuesToXml(
- out, TAG_ACCOUNT_TYPE, accountTypesWithManagementDisabled);
- out.endTag(null, TAG_DISABLE_ACCOUNT_MANAGEMENT);
+ out, TAG_DISABLE_ACCOUNT_MANAGEMENT, TAG_ACCOUNT_TYPE,
+ accountTypesWithManagementDisabled);
}
if (!trustAgentInfos.isEmpty()) {
Set<Entry<String, TrustAgentInfo>> set = trustAgentInfos.entrySet();
@@ -1291,9 +1254,9 @@
out.endTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
}
if (crossProfileWidgetProviders != null && !crossProfileWidgetProviders.isEmpty()) {
- out.startTag(null, TAG_CROSS_PROFILE_WIDGET_PROVIDERS);
- writeAttributeValuesToXml(out, TAG_PROVIDER, crossProfileWidgetProviders);
- out.endTag(null, TAG_CROSS_PROFILE_WIDGET_PROVIDERS);
+ writeAttributeValuesToXml(
+ out, TAG_CROSS_PROFILE_WIDGET_PROVIDERS, TAG_PROVIDER,
+ crossProfileWidgetProviders);
}
writePackageListToXml(out, TAG_PERMITTED_ACCESSIBILITY_SERVICES,
permittedAccessiblityServices);
@@ -1307,20 +1270,15 @@
out, userRestrictions, TAG_USER_RESTRICTIONS);
}
if (!defaultEnabledRestrictionsAlreadySet.isEmpty()) {
- out.startTag(null, TAG_DEFAULT_ENABLED_USER_RESTRICTIONS);
- writeAttributeValuesToXml(
- out, TAG_RESTRICTION, defaultEnabledRestrictionsAlreadySet);
- out.endTag(null, TAG_DEFAULT_ENABLED_USER_RESTRICTIONS);
+ writeAttributeValuesToXml(out, TAG_DEFAULT_ENABLED_USER_RESTRICTIONS,
+ TAG_RESTRICTION,
+ defaultEnabledRestrictionsAlreadySet);
}
if (!TextUtils.isEmpty(shortSupportMessage)) {
- out.startTag(null, TAG_SHORT_SUPPORT_MESSAGE);
- out.text(shortSupportMessage.toString());
- out.endTag(null, TAG_SHORT_SUPPORT_MESSAGE);
+ writeTextToXml(out, TAG_SHORT_SUPPORT_MESSAGE, shortSupportMessage.toString());
}
if (!TextUtils.isEmpty(longSupportMessage)) {
- out.startTag(null, TAG_LONG_SUPPORT_MESSAGE);
- out.text(longSupportMessage.toString());
- out.endTag(null, TAG_LONG_SUPPORT_MESSAGE);
+ writeTextToXml(out, TAG_LONG_SUPPORT_MESSAGE, longSupportMessage.toString());
}
if (parentAdmin != null) {
out.startTag(null, TAG_PARENT_ADMIN);
@@ -1328,29 +1286,20 @@
out.endTag(null, TAG_PARENT_ADMIN);
}
if (organizationColor != DEF_ORGANIZATION_COLOR) {
- out.startTag(null, TAG_ORGANIZATION_COLOR);
- out.attribute(null, ATTR_VALUE, Integer.toString(organizationColor));
- out.endTag(null, TAG_ORGANIZATION_COLOR);
+ writeAttributeValueToXml(out, TAG_ORGANIZATION_COLOR, organizationColor);
}
if (organizationName != null) {
- out.startTag(null, TAG_ORGANIZATION_NAME);
- out.text(organizationName);
- out.endTag(null, TAG_ORGANIZATION_NAME);
+ writeTextToXml(out, TAG_ORGANIZATION_NAME, organizationName);
}
if (isLogoutEnabled) {
- out.startTag(null, TAG_IS_LOGOUT_ENABLED);
- out.attribute(null, ATTR_VALUE, Boolean.toString(isLogoutEnabled));
- out.endTag(null, TAG_IS_LOGOUT_ENABLED);
+ writeAttributeValueToXml(
+ out, TAG_IS_LOGOUT_ENABLED, isLogoutEnabled);
}
if (startUserSessionMessage != null) {
- out.startTag(null, TAG_START_USER_SESSION_MESSAGE);
- out.text(startUserSessionMessage);
- out.endTag(null, TAG_START_USER_SESSION_MESSAGE);
+ writeTextToXml(out, TAG_START_USER_SESSION_MESSAGE, startUserSessionMessage);
}
if (endUserSessionMessage != null) {
- out.startTag(null, TAG_END_USER_SESSION_MESSAGE);
- out.text(endUserSessionMessage);
- out.endTag(null, TAG_END_USER_SESSION_MESSAGE);
+ writeTextToXml(out, TAG_END_USER_SESSION_MESSAGE, endUserSessionMessage);
}
if (mCrossProfileCalendarPackages == null) {
out.startTag(null, TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL);
@@ -1361,25 +1310,58 @@
}
}
+ void writeTextToXml(XmlSerializer out, String tag, String text) throws IOException {
+ out.startTag(null, tag);
+ out.text(text);
+ out.endTag(null, tag);
+ }
+
void writePackageListToXml(XmlSerializer out, String outerTag,
List<String> packageList)
throws IllegalArgumentException, IllegalStateException, IOException {
if (packageList == null) {
return;
}
-
- out.startTag(null, outerTag);
- writeAttributeValuesToXml(out, TAG_PACKAGE_LIST_ITEM, packageList);
- out.endTag(null, outerTag);
+ writeAttributeValuesToXml(out, outerTag, TAG_PACKAGE_LIST_ITEM, packageList);
}
- void writeAttributeValuesToXml(XmlSerializer out, String tag,
+ void writeAttributeValueToXml(XmlSerializer out, String tag, String value)
+ throws IOException {
+ out.startTag(null, tag);
+ out.attribute(null, ATTR_VALUE, value);
+ out.endTag(null, tag);
+ }
+
+ void writeAttributeValueToXml(XmlSerializer out, String tag, int value)
+ throws IOException {
+ out.startTag(null, tag);
+ out.attribute(null, ATTR_VALUE, Integer.toString(value));
+ out.endTag(null, tag);
+ }
+
+ void writeAttributeValueToXml(XmlSerializer out, String tag, long value)
+ throws IOException {
+ out.startTag(null, tag);
+ out.attribute(null, ATTR_VALUE, Long.toString(value));
+ out.endTag(null, tag);
+ }
+
+ void writeAttributeValueToXml(XmlSerializer out, String tag, boolean value)
+ throws IOException {
+ out.startTag(null, tag);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(value));
+ out.endTag(null, tag);
+ }
+
+ void writeAttributeValuesToXml(XmlSerializer out, String outerTag, String innerTag,
@NonNull Collection<String> values) throws IOException {
+ out.startTag(null, outerTag);
for (String value : values) {
- out.startTag(null, tag);
+ out.startTag(null, innerTag);
out.attribute(null, ATTR_VALUE, value);
- out.endTag(null, tag);
+ out.endTag(null, innerTag);
}
+ out.endTag(null, outerTag);
}
void readFromXml(XmlPullParser parser, boolean shouldOverridePolicies)
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 d6cb9826..d900910 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -765,7 +765,38 @@
}
/**
- * Test for: @{link DevicePolicyManager#reportPasswordChanged}
+ * Test for: {@link DevicePolicyManager#setPasswordHistoryLength(ComponentName, int)}
+ *
+ * Validates that when the password history length is set, it is persisted after rebooting
+ */
+ public void testSaveAndLoadPasswordHistoryLength_persistedAfterReboot() throws Exception {
+ int passwordHistoryLength = 2;
+
+ mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+
+ // Install admin1 on system user.
+ setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
+
+ // Set admin1 to active admin and device owner
+ dpm.setActiveAdmin(admin1, false);
+ dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM);
+
+ // Save password history length
+ dpm.setPasswordHistoryLength(admin1, passwordHistoryLength);
+
+ assertEquals(dpm.getPasswordHistoryLength(admin1), passwordHistoryLength);
+
+ initializeDpms();
+ reset(mContext.spiedContext);
+
+ // Password history length should persist after rebooted
+ assertEquals(dpm.getPasswordHistoryLength(admin1), passwordHistoryLength);
+ }
+
+ /**
+ * Test for: {@link DevicePolicyManager#reportPasswordChanged}
*
* Validates that when the password for a user changes, the notification broadcast intent
* {@link DeviceAdminReceiver#ACTION_PASSWORD_CHANGED} is sent to managed profile owners, in