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 
     26 import com.android.email.provider.ContentCache;
     27 import com.android.email.provider.EmailProvider;
     28 import com.android.email.provider.ProviderTestUtils;
     29 import com.android.emailcommon.provider.Account;
     30 import com.android.emailcommon.provider.EmailContent;
     31 import com.android.emailcommon.provider.EmailContent.Message;
     32 import com.android.emailcommon.provider.Mailbox;
     33 import com.android.emailcommon.provider.Policy;
     34 import com.android.emailcommon.service.LegacyPolicySet;
     35 
     36 /**
     37  * This is a series of unit tests for backup/restore of the SecurityPolicy class.
     38  *
     39  * You can run this entire test case with:
     40  *   runtest -c com.android.email.SecurityPolicyTests email
     41  */
     42 
     43 @MediumTest
     44 public class SecurityPolicyTests extends ProviderTestCase2<EmailProvider> {
     45 
     46     private Context mMockContext;
     47     private SecurityPolicy mSecurityPolicy;
     48 
     49     public SecurityPolicyTests() {
     50         super(EmailProvider.class, EmailContent.AUTHORITY);
     51     }
     52 
     53     private static final Policy EMPTY_POLICY = new Policy();
     54 
     55     @Override
     56     protected void setUp() throws Exception {
     57         super.setUp();
     58         mMockContext = new MockContext2(getMockContext(), mContext);
     59         // Invalidate all caches, since we reset the database for each test
     60         ContentCache.invalidateAllCaches();
     61         Controller.getInstance(mMockContext).markForTest(true);
     62     }
     63 
     64     /**
     65      * Delete any dummy accounts we set up for this test
     66      */
     67     @Override
     68     protected void tearDown() throws Exception {
     69         Controller.getInstance(mMockContext).markForTest(false);
     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         Policy.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         Policy.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         Policy.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         Policy.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         Policy.setAccountPolicy(mMockContext, accountId, 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         Policy.setAccountPolicy(mMockContext, accountId, updated, null);
    246         oldKey = assertAccountPolicyConsistent(account.mId, oldKey);
    247 
    248         // Remove the policy
    249         Policy.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 a1 = ProviderTestUtils.setupAccount("holdflag-1", false, mMockContext);
    279         a1.mFlags = Account.FLAGS_NOTIFY_NEW_MAIL;
    280         a1.save(mMockContext);
    281         Account a2 = ProviderTestUtils.setupAccount("holdflag-2", false, mMockContext);
    282         a2.mFlags = Account.FLAGS_VIBRATE_ALWAYS | Account.FLAGS_SECURITY_HOLD;
    283         a2.save(mMockContext);
    284 
    285         // confirm clear until set
    286         Account a1a = Account.restoreAccountWithId(mMockContext, a1.mId);
    287         assertEquals(Account.FLAGS_NOTIFY_NEW_MAIL, a1a.mFlags);
    288         SecurityPolicy.setAccountHoldFlag(mMockContext, a1, true);
    289         assertEquals(Account.FLAGS_NOTIFY_NEW_MAIL | Account.FLAGS_SECURITY_HOLD, a1.mFlags);
    290         Account a1b = Account.restoreAccountWithId(mMockContext, a1.mId);
    291         assertEquals(Account.FLAGS_NOTIFY_NEW_MAIL | Account.FLAGS_SECURITY_HOLD, a1b.mFlags);
    292 
    293         // confirm set until cleared
    294         Account a2a = Account.restoreAccountWithId(mMockContext, a2.mId);
    295         assertEquals(Account.FLAGS_VIBRATE_ALWAYS | Account.FLAGS_SECURITY_HOLD, a2a.mFlags);
    296         SecurityPolicy.setAccountHoldFlag(mMockContext, a2, false);
    297         assertEquals(Account.FLAGS_VIBRATE_ALWAYS, a2.mFlags);
    298         Account a2b = Account.restoreAccountWithId(mMockContext, a2.mId);
    299         assertEquals(Account.FLAGS_VIBRATE_ALWAYS, a2b.mFlags);
    300     }
    301 
    302     /**
    303      * Test the response to disabling DeviceAdmin status
    304      */
    305     public void testDisableAdmin() {
    306         Account a1 = ProviderTestUtils.setupAccount("disable-1", true, mMockContext);
    307         Policy p1 = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0,
    308                 false, false);
    309         Policy.setAccountPolicy(mMockContext, a1, p1, "security-sync-key-1");
    310 
    311         Account a2 = ProviderTestUtils.setupAccount("disable-2", true, mMockContext);
    312         Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0,
    313                 false, false);
    314         Policy.setAccountPolicy(mMockContext, a2, p2, "security-sync-key-2");
    315 
    316         Account a3 = ProviderTestUtils.setupAccount("disable-3", true, mMockContext);
    317         Policy.clearAccountPolicy(mMockContext, a3);
    318 
    319         mSecurityPolicy = SecurityPolicy.getInstance(mMockContext);
    320 
    321         // Confirm that "enabling" device admin does not change security status (policy & sync key)
    322         Policy before = mSecurityPolicy.getAggregatePolicy();
    323         mSecurityPolicy.onAdminEnabled(true);        // "enabled" should not change anything
    324         Policy after1 = mSecurityPolicy.getAggregatePolicy();
    325         assertEquals(before, after1);
    326         Account a1a = Account.restoreAccountWithId(mMockContext, a1.mId);
    327         assertNotNull(a1a.mSecuritySyncKey);
    328         assertTrue(a1a.mPolicyKey > 0);
    329         Account a2a = Account.restoreAccountWithId(mMockContext, a2.mId);
    330         assertNotNull(a2a.mSecuritySyncKey);
    331         assertTrue(a2a.mPolicyKey > 0);
    332         Account a3a = Account.restoreAccountWithId(mMockContext, a3.mId);
    333         assertNull(a3a.mSecuritySyncKey);
    334         assertTrue(a3a.mPolicyKey == 0);
    335 
    336         mSecurityPolicy.deleteSecuredAccounts(mMockContext);
    337         Policy after2 = mSecurityPolicy.getAggregatePolicy();
    338         assertEquals(EMPTY_POLICY, after2);
    339         Account a1b = Account.restoreAccountWithId(mMockContext, a1.mId);
    340         assertNull(a1b);
    341         Account a2b = Account.restoreAccountWithId(mMockContext, a2.mId);
    342         assertNull(a2b);
    343         Account a3b = Account.restoreAccountWithId(mMockContext, a3.mId);
    344         assertNull(a3b.mSecuritySyncKey);
    345     }
    346 
    347     /**
    348      * Test the scanner that finds expiring accounts
    349      */
    350     public void testFindExpiringAccount() {
    351         ProviderTestUtils.setupAccount("expiring-1", true, mMockContext);
    352 
    353         // With no expiring accounts, this should return null.
    354         long nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
    355         assertEquals(-1, nextExpiringAccountId);
    356 
    357         // Add a single expiring account
    358         Account a2 =
    359             ProviderTestUtils.setupAccount("expiring-2", true, mMockContext);
    360         Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0,
    361                 false, true);
    362         Policy.setAccountPolicy(mMockContext, a2, p2, null);
    363 
    364         // The expiring account should be returned
    365         nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
    366         assertEquals(a2.mId, nextExpiringAccountId);
    367 
    368         // Add an account with a longer expiration
    369         Account a3 = ProviderTestUtils.setupAccount("expiring-3", true, mMockContext);
    370         Policy p3 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 60, 0, 0,
    371                 false, true);
    372         Policy.setAccountPolicy(mMockContext, a3, p3, null);
    373 
    374         // The original expiring account (a2) should be returned
    375         nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
    376         assertEquals(a2.mId, nextExpiringAccountId);
    377 
    378         // Add an account with a shorter expiration
    379         Account a4 = ProviderTestUtils.setupAccount("expiring-4", true, mMockContext);
    380         Policy p4 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 15, 0, 0,
    381                 false, true);
    382         Policy.setAccountPolicy(mMockContext, a4, p4, null);
    383 
    384         // The new expiring account (a4) should be returned
    385         nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext);
    386         assertEquals(a4.mId, nextExpiringAccountId);
    387     }
    388 
    389     /**
    390      * Lightweight subclass of the Controller class allows injection of mock context
    391      */
    392     public static class TestController extends Controller {
    393         protected TestController(Context providerContext, Context systemContext) {
    394             super(systemContext);
    395             setProviderContext(providerContext);
    396             markForTest(true);
    397         }
    398     }
    399 
    400     /**
    401      * Test the scanner that wipes expiring accounts
    402      */
    403     public void testWipeExpiringAccounts() {
    404         mSecurityPolicy = SecurityPolicy.getInstance(mMockContext);
    405         TestController testController = new TestController(mMockContext, getContext());
    406 
    407         // Two accounts - a1 is normal, a2 has security (but no expiration)
    408         Account a1 = ProviderTestUtils.setupAccount("expired-1", true, mMockContext);
    409         Account a2 = ProviderTestUtils.setupAccount("expired-2", true, mMockContext);
    410         Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0,
    411                 false, true);
    412         Policy.setAccountPolicy(mMockContext, a2, p2, null);
    413 
    414         // Add a mailbox & messages to each account
    415         long account1Id = a1.mId;
    416         long account2Id = a2.mId;
    417         Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext);
    418         long box1Id = box1.mId;
    419         ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, true, mMockContext);
    420         ProviderTestUtils.setupMessage("message2", account1Id, box1Id, false, true, mMockContext);
    421         Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account2Id, true, mMockContext);
    422         long box2Id = box2.mId;
    423         ProviderTestUtils.setupMessage("message3", account2Id, box2Id, false, true, mMockContext);
    424         ProviderTestUtils.setupMessage("message4", account2Id, box2Id, false, true, mMockContext);
    425 
    426         // Run the expiration code - should do nothing
    427         boolean wiped = SecurityPolicy.wipeExpiredAccounts(mMockContext, testController);
    428         assertFalse(wiped);
    429         // check mailboxes & messages not wiped
    430         assertEquals(2, EmailContent.count(mMockContext, Account.CONTENT_URI));
    431         assertEquals(2, EmailContent.count(mMockContext, Mailbox.CONTENT_URI));
    432         assertEquals(4, EmailContent.count(mMockContext, Message.CONTENT_URI));
    433 
    434         // Add 3rd account that really expires
    435         Account a3 = ProviderTestUtils.setupAccount("expired-3", true, mMockContext);
    436         Policy p3 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0,
    437                 false, true);
    438         Policy.setAccountPolicy(mMockContext, a3, p3, null);
    439 
    440         // Add mailbox & messages to 3rd account
    441         long account3Id = a3.mId;
    442         Mailbox box3 = ProviderTestUtils.setupMailbox("box3", account3Id, true, mMockContext);
    443         long box3Id = box3.mId;
    444         ProviderTestUtils.setupMessage("message5", account3Id, box3Id, false, true, mMockContext);
    445         ProviderTestUtils.setupMessage("message6", account3Id, box3Id, false, true, mMockContext);
    446 
    447         // check new counts
    448         assertEquals(3, EmailContent.count(mMockContext, Account.CONTENT_URI));
    449         assertEquals(3, EmailContent.count(mMockContext, Mailbox.CONTENT_URI));
    450         assertEquals(6, EmailContent.count(mMockContext, Message.CONTENT_URI));
    451 
    452         // Run the expiration code - wipe acct #3
    453         wiped = SecurityPolicy.wipeExpiredAccounts(mMockContext, testController);
    454         assertTrue(wiped);
    455         // check new counts - account survives but data is wiped
    456         assertEquals(3, EmailContent.count(mMockContext, Account.CONTENT_URI));
    457         assertEquals(2, EmailContent.count(mMockContext, Mailbox.CONTENT_URI));
    458         assertEquals(4, EmailContent.count(mMockContext, Message.CONTENT_URI));
    459 
    460         // Check security hold states - only #3 should be in hold
    461         Account account = Account.restoreAccountWithId(mMockContext, account1Id);
    462         assertEquals(0, account.mFlags & Account.FLAGS_SECURITY_HOLD);
    463         account = Account.restoreAccountWithId(mMockContext, account2Id);
    464         assertEquals(0, account.mFlags & Account.FLAGS_SECURITY_HOLD);
    465         account = Account.restoreAccountWithId(mMockContext, account3Id);
    466         assertEquals(Account.FLAGS_SECURITY_HOLD, account.mFlags & Account.FLAGS_SECURITY_HOLD);
    467     }
    468 
    469     /**
    470      * Test the code that clears unsupported policies
    471      * TODO inject a mock DPM so we can directly control & test all cases, no matter what device
    472      */
    473     public void testClearUnsupportedPolicies() {
    474         Policy p1 =
    475             setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false);
    476         Policy p2 =
    477             setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, true, false);
    478 
    479         mSecurityPolicy = SecurityPolicy.getInstance(mMockContext);
    480         DevicePolicyManager dpm = mSecurityPolicy.getDPM();
    481         boolean hasEncryption =
    482             dpm.getStorageEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
    483 
    484         Policy p1Result = mSecurityPolicy.clearUnsupportedPolicies(p1);
    485         Policy p2Result = mSecurityPolicy.clearUnsupportedPolicies(p2);
    486 
    487         // No changes expected when encryptionRequested was false
    488         assertEquals(p1, p1Result);
    489         if (hasEncryption) {
    490             // No changes expected
    491             assertEquals(p2, p2Result);
    492         } else {
    493             // If encryption is unsupported, encryption policy bits are cleared
    494             Policy policyExpect =
    495                 setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false,
    496                         false);
    497             assertEquals(policyExpect, p2Result);
    498         }
    499     }
    500 
    501     /**
    502      * Test the code that converts from exchange-style quality to DPM/Lockscreen style quality.
    503      */
    504     public void testGetDPManagerPasswordQuality() {
    505         // Policy.PASSWORD_MODE_NONE -> DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
    506         Policy p1 = setupPolicy(0, Policy.PASSWORD_MODE_NONE,
    507                 0, 0, false, 0, 0, 0, false, false);
    508         assertEquals(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
    509                 p1.getDPManagerPasswordQuality());
    510 
    511         // PASSWORD_MODE_SIMPLE -> PASSWORD_QUALITY_NUMERIC
    512         Policy p2 = setupPolicy(4, Policy.PASSWORD_MODE_SIMPLE,
    513                 0, 0, false, 0, 0, 0, false, false);
    514         assertEquals(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
    515                 p2.getDPManagerPasswordQuality());
    516 
    517         // PASSWORD_MODE_STRONG -> PASSWORD_QUALITY_ALPHANUMERIC
    518         Policy p3 = setupPolicy(4, Policy.PASSWORD_MODE_STRONG,
    519                 0, 0, false, 0, 0, 0, false, false);
    520         assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC,
    521                 p3.getDPManagerPasswordQuality());
    522 
    523         // PASSWORD_MODE_STRONG + complex chars -> PASSWORD_QUALITY_COMPLEX
    524         Policy p4 = setupPolicy(4, Policy.PASSWORD_MODE_STRONG,
    525                 0, 0, false, 0, 0 , 2, false, false);
    526         assertEquals(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX,
    527                 p4.getDPManagerPasswordQuality());
    528     }
    529 
    530     private boolean policySetEqualsPolicy(PolicySet ps, Policy policy) {
    531         if ((ps.mPasswordMode >> LegacyPolicySet.PASSWORD_MODE_SHIFT) != policy.mPasswordMode) {
    532             return false;
    533         }
    534         if (ps.mMinPasswordLength != policy.mPasswordMinLength) return false;
    535         if (ps.mPasswordComplexChars != policy.mPasswordComplexChars) return false;
    536         if (ps.mPasswordHistory != policy.mPasswordHistory) return false;
    537         if (ps.mPasswordExpirationDays != policy.mPasswordExpirationDays) return false;
    538         if (ps.mMaxPasswordFails != policy.mPasswordMaxFails) return false;
    539         if (ps.mMaxScreenLockTime != policy.mMaxScreenLockTime) return false;
    540         if (ps.mRequireRemoteWipe != policy.mRequireRemoteWipe) return false;
    541         if (ps.mRequireEncryption != policy.mRequireEncryption) return false;
    542         if (ps.mRequireEncryptionExternal != policy.mRequireEncryptionExternal) return false;
    543         return true;
    544     }
    545 
    546     public void testPolicyFlagsToPolicy() {
    547         // Policy flags; the three sets included here correspond to policies for three test
    548         // accounts that, between them, use all of the possible policies
    549         long flags = 67096612L;
    550         PolicySet ps = new PolicySet(flags);
    551         Policy policy = LegacyPolicySet.flagsToPolicy(flags);
    552         assertTrue(policySetEqualsPolicy(ps, policy));
    553         flags = 52776591691846L;
    554         ps = new PolicySet(flags);
    555         policy = LegacyPolicySet.flagsToPolicy(flags);
    556         assertTrue(policySetEqualsPolicy(ps, policy));
    557         flags = 1689605957029924L;
    558         ps = new PolicySet(flags);
    559         policy = LegacyPolicySet.flagsToPolicy(flags);
    560         assertTrue(policySetEqualsPolicy(ps, policy));
    561     }
    562 
    563     /**
    564      * The old PolicySet class fields and constructor; we use this to test conversion to the
    565      * new Policy table scheme
    566      */
    567     private static class PolicySet {
    568         private final int mMinPasswordLength;
    569         private final int mPasswordMode;
    570         private final int mMaxPasswordFails;
    571         private final int mMaxScreenLockTime;
    572         private final boolean mRequireRemoteWipe;
    573         private final int mPasswordExpirationDays;
    574         private final int mPasswordHistory;
    575         private final int mPasswordComplexChars;
    576         private final boolean mRequireEncryption;
    577         private final boolean mRequireEncryptionExternal;
    578 
    579         /**
    580          * Create from values encoded in an account flags int
    581          */
    582         private PolicySet(long flags) {
    583             mMinPasswordLength = (int) ((flags & LegacyPolicySet.PASSWORD_LENGTH_MASK)
    584                     >> LegacyPolicySet.PASSWORD_LENGTH_SHIFT);
    585             mPasswordMode =
    586                 (int) (flags & LegacyPolicySet.PASSWORD_MODE_MASK);
    587             mMaxPasswordFails = (int) ((flags & LegacyPolicySet.PASSWORD_MAX_FAILS_MASK)
    588                     >> LegacyPolicySet.PASSWORD_MAX_FAILS_SHIFT);
    589             mMaxScreenLockTime = (int) ((flags & LegacyPolicySet.SCREEN_LOCK_TIME_MASK)
    590                     >> LegacyPolicySet.SCREEN_LOCK_TIME_SHIFT);
    591             mRequireRemoteWipe = 0 != (flags & LegacyPolicySet.REQUIRE_REMOTE_WIPE);
    592             mPasswordExpirationDays = (int) ((flags & LegacyPolicySet.PASSWORD_EXPIRATION_MASK)
    593                     >> LegacyPolicySet.PASSWORD_EXPIRATION_SHIFT);
    594             mPasswordHistory = (int) ((flags & LegacyPolicySet.PASSWORD_HISTORY_MASK)
    595                     >> LegacyPolicySet.PASSWORD_HISTORY_SHIFT);
    596             mPasswordComplexChars = (int) ((flags & LegacyPolicySet.PASSWORD_COMPLEX_CHARS_MASK)
    597                     >> LegacyPolicySet.PASSWORD_COMPLEX_CHARS_SHIFT);
    598             mRequireEncryption = 0 != (flags & LegacyPolicySet.REQUIRE_ENCRYPTION);
    599             mRequireEncryptionExternal = 0 != (flags & LegacyPolicySet.REQUIRE_ENCRYPTION_EXTERNAL);
    600         }
    601     }
    602 }
    603