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
17package com.android.email;
18
19import android.app.admin.DevicePolicyManager;
20import android.content.Context;
21import android.content.ContextWrapper;
22import android.test.ProviderTestCase2;
23import android.test.suitebuilder.annotation.MediumTest;
24import android.test.suitebuilder.annotation.SmallTest;
25import android.test.suitebuilder.annotation.Suppress;
26
27import com.android.email.provider.ContentCache;
28import com.android.email.provider.EmailProvider;
29import com.android.email.provider.ProviderTestUtils;
30import com.android.emailcommon.provider.Account;
31import com.android.emailcommon.provider.EmailContent;
32import com.android.emailcommon.provider.EmailContent.Message;
33import com.android.emailcommon.provider.Mailbox;
34import com.android.emailcommon.provider.Policy;
35import 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
47public 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