Home | History | Annotate | Download | only in email
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.email;
     18 
     19 import android.app.admin.DevicePolicyManager;
     20 import android.content.Context;
     21 import android.content.ContextWrapper;
     22 import android.test.ProviderTestCase2;
     23 import android.test.suitebuilder.annotation.MediumTest;
     24 import android.test.suitebuilder.annotation.SmallTest;
     25 import android.test.suitebuilder.annotation.Suppress;
     26 
     27 import com.android.email.provider.ContentCache;
     28 import com.android.email.provider.EmailProvider;
     29 import com.android.email.provider.ProviderTestUtils;
     30 import com.android.emailcommon.provider.Account;
     31 import com.android.emailcommon.provider.EmailContent;
     32 import com.android.emailcommon.provider.EmailContent.Message;
     33 import com.android.emailcommon.provider.Mailbox;
     34 import com.android.emailcommon.provider.Policy;
     35 import com.android.emailcommon.service.LegacyPolicySet;
     36 
     37 /**
     38  * This is a series of unit tests for backup/restore of the SecurityPolicy class.
     39  *
     40  * You can run this entire test case with:
     41  *   runtest -c com.android.email.SecurityPolicyTests email
     42  */
     43 
     44 // TODO: after b/12085240 gets fixed, we need to see if this test can be enabled
     45 @Suppress
     46 @MediumTest
     47 public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
     48     private Context mMockContext;
     49     private SecurityPolicy mSecurityPolicy;
     50 
     51     public SecurityPolicyTests() {
     52         super(EmailProvider.class, EmailContent.AUTHORITY);
     53     }
     54 
     55     private static final Policy EMPTY_POLICY = new Policy();
     56 
     57     @Override
     58     protected void setUp() throws Exception {
     59         super.setUp();
     60         mMockContext = new MockContext2(getMockContext(), mContext);
     61         // Invalidate all caches, since we reset the database for each test
     62         ContentCache.invalidateAllCaches();
     63     }
     64 
     65     /**
     66      * Delete any dummy accounts we set up for this test
     67      */
     68     @Override
     69     protected void tearDown() throws Exception {
     70         super.tearDown();
     71     }
     72 
     73     /**
     74      * Private context wrapper used to add back getPackageName() for these tests.
     75      *
     76      * This class also implements {@link Context} method(s) that are called during tests.
     77      */
     78     private static class MockContext2 extends ContextWrapper {
     79 
     80         private final Context mRealContext;
     81 
     82         public MockContext2(Context mockContext, Context realContext) {
     83             super(mockContext);
     84             mRealContext = realContext;
     85         }
     86 
     87         @Override
     88         public Context getApplicationContext() {
     89             return this;
     90         }
     91 
     92         @Override
     93         public String getPackageName() {
     94             return mRealContext.getPackageName();
     95         }
     96 
     97         @Override
     98         public Object getSystemService(String name) {
     99             return mRealContext.getSystemService(name);
    100         }
    101     }
    102 
    103     /**
    104      * Create a Policy using the arguments formerly used to create a PolicySet; this minimizes the
    105      * changes needed for re-using the PolicySet unit test logic
    106      */
    107     private Policy setupPolicy(int minPasswordLength, int passwordMode, int maxPasswordFails,
    108             int maxScreenLockTime, boolean requireRemoteWipe, int passwordExpirationDays,
    109             int passwordHistory, int passwordComplexChars, boolean requireEncryption,
    110             boolean dontAllowCamera)
    111             throws IllegalArgumentException {
    112         Policy policy = new Policy();
    113         policy.mPasswordMinLength = minPasswordLength;
    114         policy.mPasswordMode = passwordMode;
    115         policy.mPasswordMaxFails = maxPasswordFails;
    116         policy.mMaxScreenLockTime = maxScreenLockTime;
    117         policy.mRequireRemoteWipe = requireRemoteWipe;
    118         policy.mPasswordExpirationDays = passwordExpirationDays;
    119         policy.mPasswordHistory = passwordHistory;
    120         policy.mPasswordComplexChars = passwordComplexChars;
    121         policy.mRequireEncryption = requireEncryption;
    122         policy.mDontAllowCamera = dontAllowCamera;
    123         return policy;
    124     }
    125 
    126     /**
    127      * Test business logic of aggregating accounts with policies
    128      */
    129     public void testAggregator() {
    130         mSecurityPolicy = SecurityPolicy.getInstance(mMockContext);
    131 
    132         // with no accounts, should return empty set
    133         assertEquals(EMPTY_POLICY, mSecurityPolicy.computeAggregatePolicy());
    134 
    135         // with accounts having no security, empty set
    136         ProviderTestUtils.setupAccount("no-sec-1", true, mMockContext);
    137         ProviderTestUtils.setupAccount("no-sec-2", true, mMockContext);
    138         assertEquals(EMPTY_POLICY, mSecurityPolicy.computeAggregatePolicy());
    139 
    140         // with a single account in security mode, should return same security as in account
    141         // first test with partially-populated policies
    142         Account a3 = ProviderTestUtils.setupAccount("sec-3", true, mMockContext);
    143         Policy p3ain = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
    144                 false, false);
    145         SecurityPolicy.setAccountPolicy(mMockContext, a3, p3ain, null);
    146         Policy p3aout = mSecurityPolicy.computeAggregatePolicy();
    147         assertNotNull(p3aout);
    148         assertEquals(p3ain, p3aout);
    149 
    150         // Repeat that test with fully-populated policies
    151         Policy p3bin = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 15, 16, false, 6, 2, 3,
    152                 false, false);
    153         SecurityPolicy.setAccountPolicy(mMockContext, a3, p3bin, null);
    154         Policy p3bout = mSecurityPolicy.computeAggregatePolicy();
    155         assertNotNull(p3bout);
    156         assertEquals(p3bin, p3bout);
    157 
    158         // add another account which mixes it up (some fields will change, others will not)
    159         // pw length and pw mode - max logic - will change because larger #s here
    160         // fail count and lock timer - min logic - will *not* change because larger #s here
    161         // wipe required - OR logic - will *not* change here because false
    162         // expiration - will not change because 0 (unspecified)
    163         // max complex chars - max logic - will change
    164         // encryption required - OR logic - will *not* change here because false
    165         // don't allow camera - OR logic - will change here because it's true
    166         Policy p4in = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 5, 7,
    167                 false, true);
    168         Account a4 = ProviderTestUtils.setupAccount("sec-4", true, mMockContext);
    169         SecurityPolicy.setAccountPolicy(mMockContext, a4, p4in, null);
    170         Policy p4out = mSecurityPolicy.computeAggregatePolicy();
    171         assertNotNull(p4out);
    172         assertEquals(20, p4out.mPasswordMinLength);
    173         assertEquals(Policy.PASSWORD_MODE_STRONG, p4out.mPasswordMode);
    174         assertEquals(15, p4out.mPasswordMaxFails);
    175         assertEquals(16, p4out.mMaxScreenLockTime);
    176         assertEquals(6, p4out.mPasswordExpirationDays);
    177         assertEquals(5, p4out.mPasswordHistory);
    178         assertEquals(7, p4out.mPasswordComplexChars);
    179         assertFalse(p4out.mRequireRemoteWipe);
    180         assertFalse(p4out.mRequireEncryption);
    181         assertFalse(p4out.mRequireEncryptionExternal);
    182         assertTrue(p4out.mDontAllowCamera);
    183 
    184         // add another account which mixes it up (the remaining fields will change)
    185         // pw length and pw mode - max logic - will *not* change because smaller #s here
    186         // fail count and lock timer - min logic - will change because smaller #s here
    187         // wipe required - OR logic - will change here because true
    188         // expiration time - min logic - will change because lower here
    189         // history & complex chars - will not change because 0 (unspecified)
    190         // encryption required - OR logic - will change here because true
    191         // don't allow camera - OR logic - will *not* change here because it's already true
    192         Policy p5in = setupPolicy(4, Policy.PASSWORD_MODE_SIMPLE, 5, 6, true, 1, 0, 0,
    193                 true, false);
    194         Account a5 = ProviderTestUtils.setupAccount("sec-5", true, mMockContext);
    195         SecurityPolicy.setAccountPolicy(mMockContext, a5, p5in, null);
    196         Policy p5out = mSecurityPolicy.computeAggregatePolicy();
    197         assertNotNull(p5out);
    198         assertEquals(20, p5out.mPasswordMinLength);
    199         assertEquals(Policy.PASSWORD_MODE_STRONG, p5out.mPasswordMode);
    200         assertEquals(5, p5out.mPasswordMaxFails);
    201         assertEquals(6, p5out.mMaxScreenLockTime);
    202         assertEquals(1, p5out.mPasswordExpirationDays);
    203         assertEquals(5, p5out.mPasswordHistory);
    204         assertEquals(7, p5out.mPasswordComplexChars);
    205         assertTrue(p5out.mRequireRemoteWipe);
    206         assertFalse(p5out.mRequireEncryptionExternal);
    207         assertTrue(p5out.mDontAllowCamera);
    208     }
    209 
    210     private long assertAccountPolicyConsistent(long accountId, long oldKey) {
    211         Account account = Account.restoreAccountWithId(mMockContext, accountId);
    212         long policyKey = account.mPolicyKey;
    213 
    214         assertTrue(policyKey > 0);
    215 
    216         // Found a policy. Ensure it matches.
    217         Policy policy = Policy.restorePolicyWithId(mMockContext, policyKey);
    218         assertNotNull(policy);
    219         assertEquals(account.mPolicyKey, policy.mId);
    220         assertEquals(
    221                 accountId,
    222                 Policy.getAccountIdWithPolicyKey(mMockContext, policy.mId));
    223 
    224         // Assert the old one isn't there.
    225         if (oldKey > 0) {
    226             assertNull("old policy not cleaned up",
    227                     Policy.restorePolicyWithId(mMockContext, oldKey));
    228         }
    229 
    230         return policyKey;
    231     }
    232 
    233     @SmallTest
    234     public void testSettingAccountPolicy() {
    235         Account account = ProviderTestUtils.setupAccount("testaccount", true, mMockContext);
    236         long accountId = account.mId;
    237         Policy initial = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
    238                 false, false);
    239         SecurityPolicy.setAccountPolicy(mMockContext, account, initial, null);
    240 
    241         long oldKey = assertAccountPolicyConsistent(account.mId, 0);
    242 
    243         Policy updated = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
    244                 false, false);
    245         SecurityPolicy.setAccountPolicy(mMockContext, account, updated, null);
    246         oldKey = assertAccountPolicyConsistent(account.mId, oldKey);
    247 
    248         // Remove the policy
    249         SecurityPolicy.clearAccountPolicy(
    250                 mMockContext, Account.restoreAccountWithId(mMockContext, accountId));
    251         assertNull("old policy not cleaned up",
    252                 Policy.restorePolicyWithId(mMockContext, oldKey));
    253     }
    254 
    255     /**
    256      * Test equality.  Note, the tests for inequality are poor, as each field should
    257      * be tested individually.
    258      */
    259     @SmallTest
    260     public void testEquals() {
    261         Policy p1 =
    262             setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false);
    263         Policy p2 =
    264             setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false);
    265         Policy p3 =
    266             setupPolicy(2, Policy.PASSWORD_MODE_SIMPLE, 5, 6, true, 7, 8, 9, false, false);
    267         Policy p4 =
    268             setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, true);
    269         assertTrue(p1.equals(p2));
    270         assertFalse(p2.equals(p3));
    271         assertFalse(p1.equals(p4));
    272     }
    273 
    274     /**
    275      * Test the API to set/clear policy hold flags in an account
    276      */
    277     public void testSetClearHoldFlag() {
    278         Account a2 = ProviderTestUtils.setupAccount("holdflag-2", false, mMockContext);
    279         a2.mFlags = Account.FLAGS_SYNC_DISABLED | Account.FLAGS_SECURITY_HOLD;
    280         a2.save(mMockContext);
    281 
    282         // confirm set until cleared
    283         Account a2a = Account.restoreAccountWithId(mMockContext, a2.mId);
    284         assertEquals(Account.FLAGS_SYNC_DISABLED | Account.FLAGS_SECURITY_HOLD, a2a.mFlags);
    285 
    286         // set account hold flag off
    287         SecurityPolicy.setAccountHoldFlag(mMockContext, a2, false);
    288         assertEquals(Account.FLAGS_SYNC_DISABLED, a2.mFlags);
    289 
    290         // confirm account hold flag set
    291         Account a2b = Account.restoreAccountWithId(mMockContext, a2.mId);
    292         assertEquals(Account.FLAGS_SYNC_DISABLED, a2b.mFlags);
    293     }
    294 
    295     /**
    296      * Test the response to disabling DeviceAdmin status
    297      */
    298     public void testDisableAdmin() {
    299         Account a1 = ProviderTestUtils.setupAccount("disable-1", true, mMockContext);
    300         Policy p1 = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
    301                 false, false);
    302         SecurityPolicy.setAccountPolicy(mMockContext, a1, p1, "security-sync-key-1");
    303 
    304         Account a2 = ProviderTestUtils.setupAccount("disable-2", true, mMockContext);
    305         Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0,
    306                 false, false);
    307         SecurityPolicy.setAccountPolicy(mMockContext, a2, p2, "security-sync-key-2");
    308 
    309         Account a3 = ProviderTestUtils.setupAccount("disable-3", true, mMockContext);
    310         SecurityPolicy.clearAccountPolicy(mMockContext, a3);
    311 
    312         mSecurityPolicy = SecurityPolicy.getInstance(mMockContext);
    313 
    314         // Confirm that "enabling" device admin does not change security status (policy & sync key)
    315         Policy before = mSecurityPolicy.getAggregatePolicy();
    316         mSecurityPolicy.onAdminEnabled(true);        // "enabled" should not change anything
    317         Policy after1 = mSecurityPolicy.getAggregatePolicy();
    318         assertEquals(before, after1);
    319         Account a1a = Account.restoreAccountWithId(mMockContext, a1.mId);
    320         assertNotNull(a1a.mSecuritySyncKey);
    321         assertTrue(a1a.mPolicyKey > 0);
    322         Account a2a = Account.restoreAccountWithId(mMockContext, a2.mId);
    323         assertNotNull(a2a.mSecuritySyncKey);
    324         assertTrue(a2a.mPolicyKey > 0);
    325         Account a3a = Account.restoreAccountWithId(mMockContext, a3.mId);
    326         assertNull(a3a.mSecuritySyncKey);
    327         assertTrue(a3a.mPolicyKey == 0);
    328 
    329         mSecurityPolicy.deleteSecuredAccounts(mMockContext);
    330         Policy after2 = mSecurityPolicy.getAggregatePolicy();
    331         assertEquals(EMPTY_POLICY, after2);
    332         Account a1b = Account.restoreAccountWithId(mMockContext, a1.mId);
    333         assertNull(a1b);
    334         Account a2b = Account.restoreAccountWithId(mMockContext, a2.mId);
    335         assertNull(a2b);
    336         Account a3b = Account.restoreAccountWithId(mMockContext, a3.mId);
    337         assertNull(a3b.mSecuritySyncKey);
    338     }
    339 
    340     /**
    341      * Test the scanner that finds expiring accounts
    342      */
    343     public void testFindExpiringAccount() {
    344         ProviderTestUtils.setupAccount("expiring-1", true, mMockContext);
    345 
    346         // With no expiring accounts, this should return null.
    347         long nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
    348         assertEquals(-1, nextExpiringAccountId);
    349 
    350         // Add a single expiring account
    351         Account a2 =
    352             ProviderTestUtils.setupAccount("expiring-2", true, mMockContext);
    353         Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0,
    354                 false, true);
    355         SecurityPolicy.setAccountPolicy(mMockContext, a2, p2, null);
    356 
    357         // The expiring account should be returned
    358         nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
    359         assertEquals(a2.mId, nextExpiringAccountId);
    360 
    361         // Add an account with a longer expiration
    362         Account a3 = ProviderTestUtils.setupAccount("expiring-3", true, mMockContext);
    363         Policy p3 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 60, 0, 0,
    364                 false, true);
    365         SecurityPolicy.setAccountPolicy(mMockContext, a3, p3, null);
    366 
    367         // The original expiring account (a2) should be returned
    368         nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
    369         assertEquals(a2.mId, nextExpiringAccountId);
    370 
    371         // Add an account with a shorter expiration
    372         Account a4 = ProviderTestUtils.setupAccount("expiring-4", true, mMockContext);
    373         Policy p4 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 15, 0, 0,
    374                 false, true);
    375         SecurityPolicy.setAccountPolicy(mMockContext, a4, p4, null);
    376 
    377         // The new expiring account (a4) should be returned
    378         nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
    379         assertEquals(a4.mId, nextExpiringAccountId);
    380     }
    381 
    382     /**
    383      * Test the scanner that wipes expiring accounts
    384      */
    385     public void testWipeExpiringAccounts() {
    386         mSecurityPolicy = SecurityPolicy.getInstance(mMockContext);
    387 
    388         // Two accounts - a1 is normal, a2 has security (but no expiration)
    389         Account a1 = ProviderTestUtils.setupAccount("expired-1", true, mMockContext);
    390         Account a2 = ProviderTestUtils.setupAccount("expired-2", true, mMockContext);
    391         Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0,
    392                 false, true);
    393         SecurityPolicy.setAccountPolicy(mMockContext, a2, p2, null);
    394 
    395         // Add a mailbox & messages to each account
    396         long account1Id = a1.mId;
    397         long account2Id = a2.mId;
    398         Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext);
    399         long box1Id = box1.mId;
    400         ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, true, mMockContext);
    401         ProviderTestUtils.setupMessage("message2", account1Id, box1Id, false, true, mMockContext);
    402         Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account2Id, true, mMockContext);
    403         long box2Id = box2.mId;
    404         ProviderTestUtils.setupMessage("message3", account2Id, box2Id, false, true, mMockContext);
    405         ProviderTestUtils.setupMessage("message4", account2Id, box2Id, false, true, mMockContext);
    406 
    407         // Run the expiration code - should do nothing
    408         boolean wiped = SecurityPolicy.wipeExpiredAccounts(mMockContext);
    409         assertFalse(wiped);
    410         // check mailboxes & messages not wiped
    411         assertEquals(2, EmailContent.count(mMockContext, Account.CONTENT_URI));
    412         assertEquals(2, EmailContent.count(mMockContext, Mailbox.CONTENT_URI));
    413         assertEquals(4, EmailContent.count(mMockContext, Message.CONTENT_URI));
    414 
    415         // Add 3rd account that really expires
    416         Account a3 = ProviderTestUtils.setupAccount("expired-3", true, mMockContext);
    417         Policy p3 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0,
    418                 false, true);
    419         SecurityPolicy.setAccountPolicy(mMockContext, a3, p3, null);
    420 
    421         // Add mailbox & messages to 3rd account
    422         long account3Id = a3.mId;
    423         Mailbox box3 = ProviderTestUtils.setupMailbox("box3", account3Id, true, mMockContext);
    424         long box3Id = box3.mId;
    425         ProviderTestUtils.setupMessage("message5", account3Id, box3Id, false, true, mMockContext);
    426         ProviderTestUtils.setupMessage("message6", account3Id, box3Id, false, true, mMockContext);
    427 
    428         // check new counts
    429         assertEquals(3, EmailContent.count(mMockContext, Account.CONTENT_URI));
    430         assertEquals(3, EmailContent.count(mMockContext, Mailbox.CONTENT_URI));
    431         assertEquals(6, EmailContent.count(mMockContext, Message.CONTENT_URI));
    432 
    433         // Run the expiration code - wipe acct #3
    434         wiped = SecurityPolicy.wipeExpiredAccounts(mMockContext);
    435         assertTrue(wiped);
    436         // check new counts - account survives but data is wiped
    437         assertEquals(3, EmailContent.count(mMockContext, Account.CONTENT_URI));
    438         assertEquals(2, EmailContent.count(mMockContext, Mailbox.CONTENT_URI));
    439         assertEquals(4, EmailContent.count(mMockContext, Message.CONTENT_URI));
    440 
    441         // Check security hold states - only #3 should be in hold
    442         Account account = Account.restoreAccountWithId(mMockContext, account1Id);
    443         assertEquals(0, account.mFlags & Account.FLAGS_SECURITY_HOLD);
    444         account = Account.restoreAccountWithId(mMockContext, account2Id);
    445         assertEquals(0, account.mFlags & Account.FLAGS_SECURITY_HOLD);
    446         account = Account.restoreAccountWithId(mMockContext, account3Id);
    447         assertEquals(Account.FLAGS_SECURITY_HOLD, account.mFlags & Account.FLAGS_SECURITY_HOLD);
    448     }
    449 
    450     /**
    451      * Test the code that converts from exchange-style quality to DPM/Lockscreen style quality.
    452      */
    453     public void testGetDPManagerPasswordQuality() {
    454         // Policy.PASSWORD_MODE_NONE -> DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
    455         Policy p1 = setupPolicy(0, Policy.PASSWORD_MODE_NONE,
    456                 0, 0, false, 0, 0, 0, false, false);
    457         assertEquals(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
    458                 p1.getDPManagerPasswordQuality());
    459 
    460         // PASSWORD_MODE_SIMPLE -> PASSWORD_QUALITY_NUMERIC
    461         Policy p2 = setupPolicy(4, Policy.PASSWORD_MODE_SIMPLE,
    462                 0, 0, false, 0, 0, 0, false, false);
    463         assertEquals(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
    464                 p2.getDPManagerPasswordQuality());
    465 
    466         // PASSWORD_MODE_STRONG -> PASSWORD_QUALITY_ALPHANUMERIC
    467         Policy p3 = setupPolicy(4, Policy.PASSWORD_MODE_STRONG,
    468                 0, 0, false, 0, 0, 0, false, false);
    469         assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC,
    470                 p3.getDPManagerPasswordQuality());
    471 
    472         // PASSWORD_MODE_STRONG + complex chars -> PASSWORD_QUALITY_COMPLEX
    473         Policy p4 = setupPolicy(4, Policy.PASSWORD_MODE_STRONG,
    474                 0, 0, false, 0, 0 , 2, false, false);
    475         assertEquals(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX,
    476                 p4.getDPManagerPasswordQuality());
    477     }
    478 
    479     private boolean policySetEqualsPolicy(PolicySet ps, Policy policy) {
    480         if ((ps.mPasswordMode >> LegacyPolicySet.PASSWORD_MODE_SHIFT) != policy.mPasswordMode) {
    481             return false;
    482         }
    483         if (ps.mMinPasswordLength != policy.mPasswordMinLength) return false;
    484         if (ps.mPasswordComplexChars != policy.mPasswordComplexChars) return false;
    485         if (ps.mPasswordHistory != policy.mPasswordHistory) return false;
    486         if (ps.mPasswordExpirationDays != policy.mPasswordExpirationDays) return false;
    487         if (ps.mMaxPasswordFails != policy.mPasswordMaxFails) return false;
    488         if (ps.mMaxScreenLockTime != policy.mMaxScreenLockTime) return false;
    489         if (ps.mRequireRemoteWipe != policy.mRequireRemoteWipe) return false;
    490         if (ps.mRequireEncryption != policy.mRequireEncryption) return false;
    491         if (ps.mRequireEncryptionExternal != policy.mRequireEncryptionExternal) return false;
    492         return true;
    493     }
    494 
    495     public void testPolicyFlagsToPolicy() {
    496         // Policy flags; the three sets included here correspond to policies for three test
    497         // accounts that, between them, use all of the possible policies
    498         long flags = 67096612L;
    499         PolicySet ps = new PolicySet(flags);
    500         Policy policy = LegacyPolicySet.flagsToPolicy(flags);
    501         assertTrue(policySetEqualsPolicy(ps, policy));
    502         flags = 52776591691846L;
    503         ps = new PolicySet(flags);
    504         policy = LegacyPolicySet.flagsToPolicy(flags);
    505         assertTrue(policySetEqualsPolicy(ps, policy));
    506         flags = 1689605957029924L;
    507         ps = new PolicySet(flags);
    508         policy = LegacyPolicySet.flagsToPolicy(flags);
    509         assertTrue(policySetEqualsPolicy(ps, policy));
    510     }
    511 
    512     /**
    513      * The old PolicySet class fields and constructor; we use this to test conversion to the
    514      * new Policy table scheme
    515      */
    516     private static class PolicySet {
    517         private final int mMinPasswordLength;
    518         private final int mPasswordMode;
    519         private final int mMaxPasswordFails;
    520         private final int mMaxScreenLockTime;
    521         private final boolean mRequireRemoteWipe;
    522         private final int mPasswordExpirationDays;
    523         private final int mPasswordHistory;
    524         private final int mPasswordComplexChars;
    525         private final boolean mRequireEncryption;
    526         private final boolean mRequireEncryptionExternal;
    527 
    528         /**
    529          * Create from values encoded in an account flags int
    530          */
    531         private PolicySet(long flags) {
    532             mMinPasswordLength = (int) ((flags & LegacyPolicySet.PASSWORD_LENGTH_MASK)
    533                     >> LegacyPolicySet.PASSWORD_LENGTH_SHIFT);
    534             mPasswordMode =
    535                 (int) (flags & LegacyPolicySet.PASSWORD_MODE_MASK);
    536             mMaxPasswordFails = (int) ((flags & LegacyPolicySet.PASSWORD_MAX_FAILS_MASK)
    537                     >> LegacyPolicySet.PASSWORD_MAX_FAILS_SHIFT);
    538             mMaxScreenLockTime = (int) ((flags & LegacyPolicySet.SCREEN_LOCK_TIME_MASK)
    539                     >> LegacyPolicySet.SCREEN_LOCK_TIME_SHIFT);
    540             mRequireRemoteWipe = 0 != (flags & LegacyPolicySet.REQUIRE_REMOTE_WIPE);
    541             mPasswordExpirationDays = (int) ((flags & LegacyPolicySet.PASSWORD_EXPIRATION_MASK)
    542                     >> LegacyPolicySet.PASSWORD_EXPIRATION_SHIFT);
    543             mPasswordHistory = (int) ((flags & LegacyPolicySet.PASSWORD_HISTORY_MASK)
    544                     >> LegacyPolicySet.PASSWORD_HISTORY_SHIFT);
    545             mPasswordComplexChars = (int) ((flags & LegacyPolicySet.PASSWORD_COMPLEX_CHARS_MASK)
    546                     >> LegacyPolicySet.PASSWORD_COMPLEX_CHARS_SHIFT);
    547             mRequireEncryption = 0 != (flags & LegacyPolicySet.REQUIRE_ENCRYPTION);
    548             mRequireEncryptionExternal = 0 != (flags & LegacyPolicySet.REQUIRE_ENCRYPTION_EXTERNAL);
    549         }
    550     }
    551 }
    552