| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.email; |
| |
| import android.app.admin.DevicePolicyManager; |
| import android.content.Context; |
| import android.content.ContextWrapper; |
| import android.test.ProviderTestCase2; |
| import android.test.suitebuilder.annotation.MediumTest; |
| import android.test.suitebuilder.annotation.SmallTest; |
| |
| import com.android.email.provider.ContentCache; |
| import com.android.email.provider.EmailProvider; |
| import com.android.email.provider.ProviderTestUtils; |
| import com.android.emailcommon.provider.Account; |
| import com.android.emailcommon.provider.EmailContent; |
| import com.android.emailcommon.provider.EmailContent.Message; |
| import com.android.emailcommon.provider.Mailbox; |
| import com.android.emailcommon.provider.Policy; |
| import com.android.emailcommon.service.LegacyPolicySet; |
| |
| /** |
| * This is a series of unit tests for backup/restore of the SecurityPolicy class. |
| * |
| * You can run this entire test case with: |
| * runtest -c com.android.email.SecurityPolicyTests email |
| */ |
| |
| @MediumTest |
| public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> { |
| |
| private Context mMockContext; |
| private SecurityPolicy mSecurityPolicy; |
| |
| public SecurityPolicyTests() { |
| super(EmailProvider.class, EmailContent.AUTHORITY); |
| } |
| |
| private static final Policy EMPTY_POLICY = new Policy(); |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| mMockContext = new MockContext2(getMockContext(), mContext); |
| // Invalidate all caches, since we reset the database for each test |
| ContentCache.invalidateAllCaches(); |
| Controller.getInstance(mMockContext).markForTest(true); |
| } |
| |
| /** |
| * Delete any dummy accounts we set up for this test |
| */ |
| @Override |
| protected void tearDown() throws Exception { |
| Controller.getInstance(mMockContext).markForTest(false); |
| super.tearDown(); |
| } |
| |
| /** |
| * Private context wrapper used to add back getPackageName() for these tests. |
| * |
| * This class also implements {@link Context} method(s) that are called during tests. |
| */ |
| private static class MockContext2 extends ContextWrapper { |
| |
| private final Context mRealContext; |
| |
| public MockContext2(Context mockContext, Context realContext) { |
| super(mockContext); |
| mRealContext = realContext; |
| } |
| |
| @Override |
| public Context getApplicationContext() { |
| return this; |
| } |
| |
| @Override |
| public String getPackageName() { |
| return mRealContext.getPackageName(); |
| } |
| |
| @Override |
| public Object getSystemService(String name) { |
| return mRealContext.getSystemService(name); |
| } |
| } |
| |
| /** |
| * Create a Policy using the arguments formerly used to create a PolicySet; this minimizes the |
| * changes needed for re-using the PolicySet unit test logic |
| */ |
| private Policy setupPolicy(int minPasswordLength, int passwordMode, int maxPasswordFails, |
| int maxScreenLockTime, boolean requireRemoteWipe, int passwordExpirationDays, |
| int passwordHistory, int passwordComplexChars, boolean requireEncryption, |
| boolean dontAllowCamera) |
| throws IllegalArgumentException { |
| Policy policy = new Policy(); |
| policy.mPasswordMinLength = minPasswordLength; |
| policy.mPasswordMode = passwordMode; |
| policy.mPasswordMaxFails = maxPasswordFails; |
| policy.mMaxScreenLockTime = maxScreenLockTime; |
| policy.mRequireRemoteWipe = requireRemoteWipe; |
| policy.mPasswordExpirationDays = passwordExpirationDays; |
| policy.mPasswordHistory = passwordHistory; |
| policy.mPasswordComplexChars = passwordComplexChars; |
| policy.mRequireEncryption = requireEncryption; |
| policy.mDontAllowCamera = dontAllowCamera; |
| return policy; |
| } |
| |
| /** |
| * Test business logic of aggregating accounts with policies |
| */ |
| public void testAggregator() { |
| mSecurityPolicy = SecurityPolicy.getInstance(mMockContext); |
| |
| // with no accounts, should return empty set |
| assertEquals(EMPTY_POLICY, mSecurityPolicy.computeAggregatePolicy()); |
| |
| // with accounts having no security, empty set |
| ProviderTestUtils.setupAccount("no-sec-1", true, mMockContext); |
| ProviderTestUtils.setupAccount("no-sec-2", true, mMockContext); |
| assertEquals(EMPTY_POLICY, mSecurityPolicy.computeAggregatePolicy()); |
| |
| // with a single account in security mode, should return same security as in account |
| // first test with partially-populated policies |
| Account a3 = ProviderTestUtils.setupAccount("sec-3", true, mMockContext); |
| Policy p3ain = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0, |
| false, false); |
| Policy.setAccountPolicy(mMockContext, a3, p3ain, null); |
| Policy p3aout = mSecurityPolicy.computeAggregatePolicy(); |
| assertNotNull(p3aout); |
| assertEquals(p3ain, p3aout); |
| |
| // Repeat that test with fully-populated policies |
| Policy p3bin = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 15, 16, false, 6, 2, 3, |
| false, false); |
| Policy.setAccountPolicy(mMockContext, a3, p3bin, null); |
| Policy p3bout = mSecurityPolicy.computeAggregatePolicy(); |
| assertNotNull(p3bout); |
| assertEquals(p3bin, p3bout); |
| |
| // add another account which mixes it up (some fields will change, others will not) |
| // pw length and pw mode - max logic - will change because larger #s here |
| // fail count and lock timer - min logic - will *not* change because larger #s here |
| // wipe required - OR logic - will *not* change here because false |
| // expiration - will not change because 0 (unspecified) |
| // max complex chars - max logic - will change |
| // encryption required - OR logic - will *not* change here because false |
| // don't allow camera - OR logic - will change here because it's true |
| Policy p4in = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 5, 7, |
| false, true); |
| Account a4 = ProviderTestUtils.setupAccount("sec-4", true, mMockContext); |
| Policy.setAccountPolicy(mMockContext, a4, p4in, null); |
| Policy p4out = mSecurityPolicy.computeAggregatePolicy(); |
| assertNotNull(p4out); |
| assertEquals(20, p4out.mPasswordMinLength); |
| assertEquals(Policy.PASSWORD_MODE_STRONG, p4out.mPasswordMode); |
| assertEquals(15, p4out.mPasswordMaxFails); |
| assertEquals(16, p4out.mMaxScreenLockTime); |
| assertEquals(6, p4out.mPasswordExpirationDays); |
| assertEquals(5, p4out.mPasswordHistory); |
| assertEquals(7, p4out.mPasswordComplexChars); |
| assertFalse(p4out.mRequireRemoteWipe); |
| assertFalse(p4out.mRequireEncryption); |
| assertFalse(p4out.mRequireEncryptionExternal); |
| assertTrue(p4out.mDontAllowCamera); |
| |
| // add another account which mixes it up (the remaining fields will change) |
| // pw length and pw mode - max logic - will *not* change because smaller #s here |
| // fail count and lock timer - min logic - will change because smaller #s here |
| // wipe required - OR logic - will change here because true |
| // expiration time - min logic - will change because lower here |
| // history & complex chars - will not change because 0 (unspecified) |
| // encryption required - OR logic - will change here because true |
| // don't allow camera - OR logic - will *not* change here because it's already true |
| Policy p5in = setupPolicy(4, Policy.PASSWORD_MODE_SIMPLE, 5, 6, true, 1, 0, 0, |
| true, false); |
| Account a5 = ProviderTestUtils.setupAccount("sec-5", true, mMockContext); |
| Policy.setAccountPolicy(mMockContext, a5, p5in, null); |
| Policy p5out = mSecurityPolicy.computeAggregatePolicy(); |
| assertNotNull(p5out); |
| assertEquals(20, p5out.mPasswordMinLength); |
| assertEquals(Policy.PASSWORD_MODE_STRONG, p5out.mPasswordMode); |
| assertEquals(5, p5out.mPasswordMaxFails); |
| assertEquals(6, p5out.mMaxScreenLockTime); |
| assertEquals(1, p5out.mPasswordExpirationDays); |
| assertEquals(5, p5out.mPasswordHistory); |
| assertEquals(7, p5out.mPasswordComplexChars); |
| assertTrue(p5out.mRequireRemoteWipe); |
| assertFalse(p5out.mRequireEncryptionExternal); |
| assertTrue(p5out.mDontAllowCamera); |
| } |
| |
| private long assertAccountPolicyConsistent(long accountId, long oldKey) { |
| Account account = Account.restoreAccountWithId(mMockContext, accountId); |
| long policyKey = account.mPolicyKey; |
| |
| assertTrue(policyKey > 0); |
| |
| // Found a policy. Ensure it matches. |
| Policy policy = Policy.restorePolicyWithId(mMockContext, policyKey); |
| assertNotNull(policy); |
| assertEquals(account.mPolicyKey, policy.mId); |
| assertEquals( |
| accountId, |
| Policy.getAccountIdWithPolicyKey(mMockContext, policy.mId)); |
| |
| // Assert the old one isn't there. |
| if (oldKey > 0) { |
| assertNull("old policy not cleaned up", |
| Policy.restorePolicyWithId(mMockContext, oldKey)); |
| } |
| |
| return policyKey; |
| } |
| |
| @SmallTest |
| public void testSettingAccountPolicy() { |
| Account account = ProviderTestUtils.setupAccount("testaccount", true, mMockContext); |
| long accountId = account.mId; |
| Policy initial = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0, |
| false, false); |
| Policy.setAccountPolicy(mMockContext, accountId, initial, null); |
| |
| long oldKey = assertAccountPolicyConsistent(account.mId, 0); |
| |
| Policy updated = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0, |
| false, false); |
| Policy.setAccountPolicy(mMockContext, accountId, updated, null); |
| oldKey = assertAccountPolicyConsistent(account.mId, oldKey); |
| |
| // Remove the policy |
| Policy.clearAccountPolicy( |
| mMockContext, Account.restoreAccountWithId(mMockContext, accountId)); |
| assertNull("old policy not cleaned up", |
| Policy.restorePolicyWithId(mMockContext, oldKey)); |
| } |
| |
| /** |
| * Test equality. Note, the tests for inequality are poor, as each field should |
| * be tested individually. |
| */ |
| @SmallTest |
| public void testEquals() { |
| Policy p1 = |
| setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false); |
| Policy p2 = |
| setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false); |
| Policy p3 = |
| setupPolicy(2, Policy.PASSWORD_MODE_SIMPLE, 5, 6, true, 7, 8, 9, false, false); |
| Policy p4 = |
| setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, true); |
| assertTrue(p1.equals(p2)); |
| assertFalse(p2.equals(p3)); |
| assertFalse(p1.equals(p4)); |
| } |
| |
| /** |
| * Test the API to set/clear policy hold flags in an account |
| */ |
| public void testSetClearHoldFlag() { |
| Account a1 = ProviderTestUtils.setupAccount("holdflag-1", false, mMockContext); |
| a1.mFlags = Account.FLAGS_NOTIFY_NEW_MAIL; |
| a1.save(mMockContext); |
| Account a2 = ProviderTestUtils.setupAccount("holdflag-2", false, mMockContext); |
| a2.mFlags = Account.FLAGS_VIBRATE_ALWAYS | Account.FLAGS_SECURITY_HOLD; |
| a2.save(mMockContext); |
| |
| // confirm clear until set |
| Account a1a = Account.restoreAccountWithId(mMockContext, a1.mId); |
| assertEquals(Account.FLAGS_NOTIFY_NEW_MAIL, a1a.mFlags); |
| SecurityPolicy.setAccountHoldFlag(mMockContext, a1, true); |
| assertEquals(Account.FLAGS_NOTIFY_NEW_MAIL | Account.FLAGS_SECURITY_HOLD, a1.mFlags); |
| Account a1b = Account.restoreAccountWithId(mMockContext, a1.mId); |
| assertEquals(Account.FLAGS_NOTIFY_NEW_MAIL | Account.FLAGS_SECURITY_HOLD, a1b.mFlags); |
| |
| // confirm set until cleared |
| Account a2a = Account.restoreAccountWithId(mMockContext, a2.mId); |
| assertEquals(Account.FLAGS_VIBRATE_ALWAYS | Account.FLAGS_SECURITY_HOLD, a2a.mFlags); |
| SecurityPolicy.setAccountHoldFlag(mMockContext, a2, false); |
| assertEquals(Account.FLAGS_VIBRATE_ALWAYS, a2.mFlags); |
| Account a2b = Account.restoreAccountWithId(mMockContext, a2.mId); |
| assertEquals(Account.FLAGS_VIBRATE_ALWAYS, a2b.mFlags); |
| } |
| |
| /** |
| * Test the response to disabling DeviceAdmin status |
| */ |
| public void testDisableAdmin() { |
| Account a1 = ProviderTestUtils.setupAccount("disable-1", true, mMockContext); |
| Policy p1 = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0, |
| false, false); |
| Policy.setAccountPolicy(mMockContext, a1, p1, "security-sync-key-1"); |
| |
| Account a2 = ProviderTestUtils.setupAccount("disable-2", true, mMockContext); |
| Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0, |
| false, false); |
| Policy.setAccountPolicy(mMockContext, a2, p2, "security-sync-key-2"); |
| |
| Account a3 = ProviderTestUtils.setupAccount("disable-3", true, mMockContext); |
| Policy.clearAccountPolicy(mMockContext, a3); |
| |
| mSecurityPolicy = SecurityPolicy.getInstance(mMockContext); |
| |
| // Confirm that "enabling" device admin does not change security status (policy & sync key) |
| Policy before = mSecurityPolicy.getAggregatePolicy(); |
| mSecurityPolicy.onAdminEnabled(true); // "enabled" should not change anything |
| Policy after1 = mSecurityPolicy.getAggregatePolicy(); |
| assertEquals(before, after1); |
| Account a1a = Account.restoreAccountWithId(mMockContext, a1.mId); |
| assertNotNull(a1a.mSecuritySyncKey); |
| assertTrue(a1a.mPolicyKey > 0); |
| Account a2a = Account.restoreAccountWithId(mMockContext, a2.mId); |
| assertNotNull(a2a.mSecuritySyncKey); |
| assertTrue(a2a.mPolicyKey > 0); |
| Account a3a = Account.restoreAccountWithId(mMockContext, a3.mId); |
| assertNull(a3a.mSecuritySyncKey); |
| assertTrue(a3a.mPolicyKey == 0); |
| |
| mSecurityPolicy.deleteSecuredAccounts(mMockContext); |
| Policy after2 = mSecurityPolicy.getAggregatePolicy(); |
| assertEquals(EMPTY_POLICY, after2); |
| Account a1b = Account.restoreAccountWithId(mMockContext, a1.mId); |
| assertNull(a1b); |
| Account a2b = Account.restoreAccountWithId(mMockContext, a2.mId); |
| assertNull(a2b); |
| Account a3b = Account.restoreAccountWithId(mMockContext, a3.mId); |
| assertNull(a3b.mSecuritySyncKey); |
| } |
| |
| /** |
| * Test the scanner that finds expiring accounts |
| */ |
| public void testFindExpiringAccount() { |
| ProviderTestUtils.setupAccount("expiring-1", true, mMockContext); |
| |
| // With no expiring accounts, this should return null. |
| long nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext); |
| assertEquals(-1, nextExpiringAccountId); |
| |
| // Add a single expiring account |
| Account a2 = |
| ProviderTestUtils.setupAccount("expiring-2", true, mMockContext); |
| Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0, |
| false, true); |
| Policy.setAccountPolicy(mMockContext, a2, p2, null); |
| |
| // The expiring account should be returned |
| nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext); |
| assertEquals(a2.mId, nextExpiringAccountId); |
| |
| // Add an account with a longer expiration |
| Account a3 = ProviderTestUtils.setupAccount("expiring-3", true, mMockContext); |
| Policy p3 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 60, 0, 0, |
| false, true); |
| Policy.setAccountPolicy(mMockContext, a3, p3, null); |
| |
| // The original expiring account (a2) should be returned |
| nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext); |
| assertEquals(a2.mId, nextExpiringAccountId); |
| |
| // Add an account with a shorter expiration |
| Account a4 = ProviderTestUtils.setupAccount("expiring-4", true, mMockContext); |
| Policy p4 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 15, 0, 0, |
| false, true); |
| Policy.setAccountPolicy(mMockContext, a4, p4, null); |
| |
| // The new expiring account (a4) should be returned |
| nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext); |
| assertEquals(a4.mId, nextExpiringAccountId); |
| } |
| |
| /** |
| * Lightweight subclass of the Controller class allows injection of mock context |
| */ |
| public static class TestController extends Controller { |
| protected TestController(Context providerContext, Context systemContext) { |
| super(systemContext); |
| setProviderContext(providerContext); |
| markForTest(true); |
| } |
| } |
| |
| /** |
| * Test the scanner that wipes expiring accounts |
| */ |
| public void testWipeExpiringAccounts() { |
| mSecurityPolicy = SecurityPolicy.getInstance(mMockContext); |
| TestController testController = new TestController(mMockContext, getContext()); |
| |
| // Two accounts - a1 is normal, a2 has security (but no expiration) |
| Account a1 = ProviderTestUtils.setupAccount("expired-1", true, mMockContext); |
| Account a2 = ProviderTestUtils.setupAccount("expired-2", true, mMockContext); |
| Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0, |
| false, true); |
| Policy.setAccountPolicy(mMockContext, a2, p2, null); |
| |
| // Add a mailbox & messages to each account |
| long account1Id = a1.mId; |
| long account2Id = a2.mId; |
| Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); |
| long box1Id = box1.mId; |
| ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, true, mMockContext); |
| ProviderTestUtils.setupMessage("message2", account1Id, box1Id, false, true, mMockContext); |
| Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account2Id, true, mMockContext); |
| long box2Id = box2.mId; |
| ProviderTestUtils.setupMessage("message3", account2Id, box2Id, false, true, mMockContext); |
| ProviderTestUtils.setupMessage("message4", account2Id, box2Id, false, true, mMockContext); |
| |
| // Run the expiration code - should do nothing |
| boolean wiped = SecurityPolicy.wipeExpiredAccounts(mMockContext, testController); |
| assertFalse(wiped); |
| // check mailboxes & messages not wiped |
| assertEquals(2, EmailContent.count(mMockContext, Account.CONTENT_URI)); |
| assertEquals(2, EmailContent.count(mMockContext, Mailbox.CONTENT_URI)); |
| assertEquals(4, EmailContent.count(mMockContext, Message.CONTENT_URI)); |
| |
| // Add 3rd account that really expires |
| Account a3 = ProviderTestUtils.setupAccount("expired-3", true, mMockContext); |
| Policy p3 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0, |
| false, true); |
| Policy.setAccountPolicy(mMockContext, a3, p3, null); |
| |
| // Add mailbox & messages to 3rd account |
| long account3Id = a3.mId; |
| Mailbox box3 = ProviderTestUtils.setupMailbox("box3", account3Id, true, mMockContext); |
| long box3Id = box3.mId; |
| ProviderTestUtils.setupMessage("message5", account3Id, box3Id, false, true, mMockContext); |
| ProviderTestUtils.setupMessage("message6", account3Id, box3Id, false, true, mMockContext); |
| |
| // check new counts |
| assertEquals(3, EmailContent.count(mMockContext, Account.CONTENT_URI)); |
| assertEquals(3, EmailContent.count(mMockContext, Mailbox.CONTENT_URI)); |
| assertEquals(6, EmailContent.count(mMockContext, Message.CONTENT_URI)); |
| |
| // Run the expiration code - wipe acct #3 |
| wiped = SecurityPolicy.wipeExpiredAccounts(mMockContext, testController); |
| assertTrue(wiped); |
| // check new counts - account survives but data is wiped |
| assertEquals(3, EmailContent.count(mMockContext, Account.CONTENT_URI)); |
| assertEquals(2, EmailContent.count(mMockContext, Mailbox.CONTENT_URI)); |
| assertEquals(4, EmailContent.count(mMockContext, Message.CONTENT_URI)); |
| |
| // Check security hold states - only #3 should be in hold |
| Account account = Account.restoreAccountWithId(mMockContext, account1Id); |
| assertEquals(0, account.mFlags & Account.FLAGS_SECURITY_HOLD); |
| account = Account.restoreAccountWithId(mMockContext, account2Id); |
| assertEquals(0, account.mFlags & Account.FLAGS_SECURITY_HOLD); |
| account = Account.restoreAccountWithId(mMockContext, account3Id); |
| assertEquals(Account.FLAGS_SECURITY_HOLD, account.mFlags & Account.FLAGS_SECURITY_HOLD); |
| } |
| |
| /** |
| * Test the code that clears unsupported policies |
| * TODO inject a mock DPM so we can directly control & test all cases, no matter what device |
| */ |
| public void testClearUnsupportedPolicies() { |
| Policy p1 = |
| setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false); |
| Policy p2 = |
| setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, true, false); |
| |
| mSecurityPolicy = SecurityPolicy.getInstance(mMockContext); |
| DevicePolicyManager dpm = mSecurityPolicy.getDPM(); |
| boolean hasEncryption = |
| dpm.getStorageEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED; |
| |
| Policy p1Result = mSecurityPolicy.clearUnsupportedPolicies(p1); |
| Policy p2Result = mSecurityPolicy.clearUnsupportedPolicies(p2); |
| |
| // No changes expected when encryptionRequested was false |
| assertEquals(p1, p1Result); |
| if (hasEncryption) { |
| // No changes expected |
| assertEquals(p2, p2Result); |
| } else { |
| // If encryption is unsupported, encryption policy bits are cleared |
| Policy policyExpect = |
| setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, |
| false); |
| assertEquals(policyExpect, p2Result); |
| } |
| } |
| |
| /** |
| * Test the code that converts from exchange-style quality to DPM/Lockscreen style quality. |
| */ |
| public void testGetDPManagerPasswordQuality() { |
| // Policy.PASSWORD_MODE_NONE -> DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED |
| Policy p1 = setupPolicy(0, Policy.PASSWORD_MODE_NONE, |
| 0, 0, false, 0, 0, 0, false, false); |
| assertEquals(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, |
| p1.getDPManagerPasswordQuality()); |
| |
| // PASSWORD_MODE_SIMPLE -> PASSWORD_QUALITY_NUMERIC |
| Policy p2 = setupPolicy(4, Policy.PASSWORD_MODE_SIMPLE, |
| 0, 0, false, 0, 0, 0, false, false); |
| assertEquals(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC, |
| p2.getDPManagerPasswordQuality()); |
| |
| // PASSWORD_MODE_STRONG -> PASSWORD_QUALITY_ALPHANUMERIC |
| Policy p3 = setupPolicy(4, Policy.PASSWORD_MODE_STRONG, |
| 0, 0, false, 0, 0, 0, false, false); |
| assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, |
| p3.getDPManagerPasswordQuality()); |
| |
| // PASSWORD_MODE_STRONG + complex chars -> PASSWORD_QUALITY_COMPLEX |
| Policy p4 = setupPolicy(4, Policy.PASSWORD_MODE_STRONG, |
| 0, 0, false, 0, 0 , 2, false, false); |
| assertEquals(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX, |
| p4.getDPManagerPasswordQuality()); |
| } |
| |
| private boolean policySetEqualsPolicy(PolicySet ps, Policy policy) { |
| if ((ps.mPasswordMode >> LegacyPolicySet.PASSWORD_MODE_SHIFT) != policy.mPasswordMode) { |
| return false; |
| } |
| if (ps.mMinPasswordLength != policy.mPasswordMinLength) return false; |
| if (ps.mPasswordComplexChars != policy.mPasswordComplexChars) return false; |
| if (ps.mPasswordHistory != policy.mPasswordHistory) return false; |
| if (ps.mPasswordExpirationDays != policy.mPasswordExpirationDays) return false; |
| if (ps.mMaxPasswordFails != policy.mPasswordMaxFails) return false; |
| if (ps.mMaxScreenLockTime != policy.mMaxScreenLockTime) return false; |
| if (ps.mRequireRemoteWipe != policy.mRequireRemoteWipe) return false; |
| if (ps.mRequireEncryption != policy.mRequireEncryption) return false; |
| if (ps.mRequireEncryptionExternal != policy.mRequireEncryptionExternal) return false; |
| return true; |
| } |
| |
| public void testPolicyFlagsToPolicy() { |
| // Policy flags; the three sets included here correspond to policies for three test |
| // accounts that, between them, use all of the possible policies |
| long flags = 67096612L; |
| PolicySet ps = new PolicySet(flags); |
| Policy policy = LegacyPolicySet.flagsToPolicy(flags); |
| assertTrue(policySetEqualsPolicy(ps, policy)); |
| flags = 52776591691846L; |
| ps = new PolicySet(flags); |
| policy = LegacyPolicySet.flagsToPolicy(flags); |
| assertTrue(policySetEqualsPolicy(ps, policy)); |
| flags = 1689605957029924L; |
| ps = new PolicySet(flags); |
| policy = LegacyPolicySet.flagsToPolicy(flags); |
| assertTrue(policySetEqualsPolicy(ps, policy)); |
| } |
| |
| /** |
| * The old PolicySet class fields and constructor; we use this to test conversion to the |
| * new Policy table scheme |
| */ |
| private static class PolicySet { |
| private final int mMinPasswordLength; |
| private final int mPasswordMode; |
| private final int mMaxPasswordFails; |
| private final int mMaxScreenLockTime; |
| private final boolean mRequireRemoteWipe; |
| private final int mPasswordExpirationDays; |
| private final int mPasswordHistory; |
| private final int mPasswordComplexChars; |
| private final boolean mRequireEncryption; |
| private final boolean mRequireEncryptionExternal; |
| |
| /** |
| * Create from values encoded in an account flags int |
| */ |
| private PolicySet(long flags) { |
| mMinPasswordLength = (int) ((flags & LegacyPolicySet.PASSWORD_LENGTH_MASK) |
| >> LegacyPolicySet.PASSWORD_LENGTH_SHIFT); |
| mPasswordMode = |
| (int) (flags & LegacyPolicySet.PASSWORD_MODE_MASK); |
| mMaxPasswordFails = (int) ((flags & LegacyPolicySet.PASSWORD_MAX_FAILS_MASK) |
| >> LegacyPolicySet.PASSWORD_MAX_FAILS_SHIFT); |
| mMaxScreenLockTime = (int) ((flags & LegacyPolicySet.SCREEN_LOCK_TIME_MASK) |
| >> LegacyPolicySet.SCREEN_LOCK_TIME_SHIFT); |
| mRequireRemoteWipe = 0 != (flags & LegacyPolicySet.REQUIRE_REMOTE_WIPE); |
| mPasswordExpirationDays = (int) ((flags & LegacyPolicySet.PASSWORD_EXPIRATION_MASK) |
| >> LegacyPolicySet.PASSWORD_EXPIRATION_SHIFT); |
| mPasswordHistory = (int) ((flags & LegacyPolicySet.PASSWORD_HISTORY_MASK) |
| >> LegacyPolicySet.PASSWORD_HISTORY_SHIFT); |
| mPasswordComplexChars = (int) ((flags & LegacyPolicySet.PASSWORD_COMPLEX_CHARS_MASK) |
| >> LegacyPolicySet.PASSWORD_COMPLEX_CHARS_SHIFT); |
| mRequireEncryption = 0 != (flags & LegacyPolicySet.REQUIRE_ENCRYPTION); |
| mRequireEncryptionExternal = 0 != (flags & LegacyPolicySet.REQUIRE_ENCRYPTION_EXTERNAL); |
| } |
| } |
| } |