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 
SecurityPolicyTests()51     public SecurityPolicyTests() {
52         super(EmailProvider.class, EmailContent.AUTHORITY);
53     }
54 
55     private static final Policy EMPTY_POLICY = new Policy();
56 
57     @Override
setUp()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
tearDown()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 
MockContext2(Context mockContext, Context realContext)82         public MockContext2(Context mockContext, Context realContext) {
83             super(mockContext);
84             mRealContext = realContext;
85         }
86 
87         @Override
getApplicationContext()88         public Context getApplicationContext() {
89             return this;
90         }
91 
92         @Override
getPackageName()93         public String getPackageName() {
94             return mRealContext.getPackageName();
95         }
96 
97         @Override
getSystemService(String name)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      */
setupPolicy(int minPasswordLength, int passwordMode, int maxPasswordFails, int maxScreenLockTime, boolean requireRemoteWipe, int passwordExpirationDays, int passwordHistory, int passwordComplexChars, boolean requireEncryption, boolean dontAllowCamera)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      */
testAggregator()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 
assertAccountPolicyConsistent(long accountId, long oldKey)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
testSettingAccountPolicy()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
testEquals()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      */
testSetClearHoldFlag()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      */
testDisableAdmin()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      */
testFindExpiringAccount()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      */
testWipeExpiringAccounts()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      */
testGetDPManagerPasswordQuality()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 
policySetEqualsPolicy(PolicySet ps, Policy policy)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 
testPolicyFlagsToPolicy()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          */
PolicySet(long flags)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