SecurityPolicyTests.java revision f5418f1f93b02e7fab9f15eb201800b65510998e
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 com.android.email.provider.ContentCache; 20import com.android.email.provider.EmailProvider; 21import com.android.email.provider.ProviderTestUtils; 22import com.android.emailcommon.provider.Account; 23import com.android.emailcommon.provider.EmailContent; 24import com.android.emailcommon.provider.EmailContent.Message; 25import com.android.emailcommon.provider.Mailbox; 26import com.android.emailcommon.provider.Policy; 27import com.android.emailcommon.service.LegacyPolicySet; 28 29import android.app.admin.DevicePolicyManager; 30import android.content.Context; 31import android.content.ContextWrapper; 32import android.test.ProviderTestCase2; 33import android.test.suitebuilder.annotation.MediumTest; 34import android.test.suitebuilder.annotation.SmallTest; 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 44public 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.invalidateAllCachesForTest(); 61 } 62 63 /** 64 * Delete any dummy accounts we set up for this test 65 */ 66 @Override 67 protected void tearDown() throws Exception { 68 super.tearDown(); 69 } 70 71 /** 72 * Private context wrapper used to add back getPackageName() for these tests. 73 * 74 * This class also implements {@link Context} method(s) that are called during tests. 75 */ 76 private static class MockContext2 extends ContextWrapper { 77 78 private final Context mRealContext; 79 80 public MockContext2(Context mockContext, Context realContext) { 81 super(mockContext); 82 mRealContext = realContext; 83 } 84 85 @Override 86 public Context getApplicationContext() { 87 return this; 88 } 89 90 @Override 91 public String getPackageName() { 92 return mRealContext.getPackageName(); 93 } 94 95 @Override 96 public Object getSystemService(String name) { 97 return mRealContext.getSystemService(name); 98 } 99 } 100 101 /** 102 * Create a Policy using the arguments formerly used to create a PolicySet; this minimizes the 103 * changes needed for re-using the PolicySet unit test logic 104 */ 105 private Policy setupPolicy(int minPasswordLength, int passwordMode, int maxPasswordFails, 106 int maxScreenLockTime, boolean requireRemoteWipe, int passwordExpirationDays, 107 int passwordHistory, int passwordComplexChars, boolean requireEncryption, 108 boolean requireEncryptionExternal) throws IllegalArgumentException { 109 Policy policy = new Policy(); 110 policy.mPasswordMinLength = minPasswordLength; 111 policy.mPasswordMode = passwordMode; 112 policy.mPasswordMaxFails = maxPasswordFails; 113 policy.mMaxScreenLockTime = maxScreenLockTime; 114 policy.mRequireRemoteWipe = requireRemoteWipe; 115 policy.mPasswordExpirationDays = passwordExpirationDays; 116 policy.mPasswordHistory = passwordHistory; 117 policy.mPasswordComplexChars = passwordComplexChars; 118 policy.mRequireEncryption = requireEncryption; 119 policy.mRequireEncryptionExternal = requireEncryptionExternal; 120 return policy; 121 } 122 123 /** 124 * Test business logic of aggregating accounts with policies 125 */ 126 public void testAggregator() { 127 mSecurityPolicy = SecurityPolicy.getInstance(mMockContext); 128 129 // with no accounts, should return empty set 130 assertEquals(EMPTY_POLICY, mSecurityPolicy.computeAggregatePolicy()); 131 132 // with accounts having no security, empty set 133 ProviderTestUtils.setupAccount("no-sec-1", true, mMockContext); 134 ProviderTestUtils.setupAccount("no-sec-2", true, mMockContext); 135 assertEquals(EMPTY_POLICY, mSecurityPolicy.computeAggregatePolicy()); 136 137 // with a single account in security mode, should return same security as in account 138 // first test with partially-populated policies 139 Account a3 = ProviderTestUtils.setupAccount("sec-3", true, mMockContext); 140 Policy p3ain = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0, 141 false, false); 142 Policy.setAccountPolicy(mMockContext, a3, p3ain, null); 143 Policy p3aout = mSecurityPolicy.computeAggregatePolicy(); 144 assertNotNull(p3aout); 145 assertEquals(p3ain, p3aout); 146 147 // Repeat that test with fully-populated policies 148 Policy p3bin = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 15, 16, false, 6, 2, 3, 149 false, false); 150 Policy.setAccountPolicy(mMockContext, a3, p3bin, null); 151 Policy p3bout = mSecurityPolicy.computeAggregatePolicy(); 152 assertNotNull(p3bout); 153 assertEquals(p3bin, p3bout); 154 155 // add another account which mixes it up (some fields will change, others will not) 156 // pw length and pw mode - max logic - will change because larger #s here 157 // fail count and lock timer - min logic - will *not* change because larger #s here 158 // wipe required - OR logic - will *not* change here because false 159 // expiration - will not change because 0 (unspecified) 160 // max complex chars - max logic - will change 161 // encryption required - OR logic - will *not* change here because false 162 // encryption external req'd - OR logic - will *not* change here because false 163 Policy p4in = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 5, 7, 164 false, false); 165 Account a4 = ProviderTestUtils.setupAccount("sec-4", true, mMockContext); 166 Policy.setAccountPolicy(mMockContext, a4, p4in, null); 167 Policy p4out = mSecurityPolicy.computeAggregatePolicy(); 168 assertNotNull(p4out); 169 assertEquals(20, p4out.mPasswordMinLength); 170 assertEquals(Policy.PASSWORD_MODE_STRONG, p4out.mPasswordMode); 171 assertEquals(15, p4out.mPasswordMaxFails); 172 assertEquals(16, p4out.mMaxScreenLockTime); 173 assertEquals(6, p4out.mPasswordExpirationDays); 174 assertEquals(5, p4out.mPasswordHistory); 175 assertEquals(7, p4out.mPasswordComplexChars); 176 assertFalse(p4out.mRequireRemoteWipe); 177 assertFalse(p4out.mRequireEncryption); 178 assertFalse(p4out.mRequireEncryptionExternal); 179 180 // add another account which mixes it up (the remaining fields will change) 181 // pw length and pw mode - max logic - will *not* change because smaller #s here 182 // fail count and lock timer - min logic - will change because smaller #s here 183 // wipe required - OR logic - will change here because true 184 // expiration time - min logic - will change because lower here 185 // history & complex chars - will not change because 0 (unspecified) 186 // encryption required - OR logic - will change here because true 187 // encryption external req'd - OR logic - will *not* change here because false 188 Policy p5in = setupPolicy(4, Policy.PASSWORD_MODE_SIMPLE, 5, 6, true, 1, 0, 0, 189 true, false); 190 Account a5 = ProviderTestUtils.setupAccount("sec-5", true, mMockContext); 191 Policy.setAccountPolicy(mMockContext, a5, p5in, null); 192 Policy p5out = mSecurityPolicy.computeAggregatePolicy(); 193 assertNotNull(p5out); 194 assertEquals(20, p5out.mPasswordMinLength); 195 assertEquals(Policy.PASSWORD_MODE_STRONG, p5out.mPasswordMode); 196 assertEquals(5, p5out.mPasswordMaxFails); 197 assertEquals(6, p5out.mMaxScreenLockTime); 198 assertEquals(1, p5out.mPasswordExpirationDays); 199 assertEquals(5, p5out.mPasswordHistory); 200 assertEquals(7, p5out.mPasswordComplexChars); 201 assertTrue(p5out.mRequireRemoteWipe); 202 assertFalse(p5out.mRequireEncryptionExternal); 203 204 // add another account that continues to mutate fields 205 // encryption external req'd - OR logic - will change here because true 206 Policy p6in = setupPolicy(0, Policy.PASSWORD_MODE_NONE, 0, 0, false, 0, 0, 0, 207 false, true); 208 Account a6 = ProviderTestUtils.setupAccount("sec-6", true, mMockContext); 209 Policy.setAccountPolicy(mMockContext, a6, p6in, null); 210 Policy p6out = mSecurityPolicy.computeAggregatePolicy(); 211 assertNotNull(p6out); 212 assertTrue(p6out.mRequireEncryptionExternal); 213 } 214 215 /** 216 * Test equality. Note, the tests for inequality are poor, as each field should 217 * be tested individually. 218 */ 219 @SmallTest 220 public void testEquals() { 221 Policy p1 = 222 setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false); 223 Policy p2 = 224 setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false); 225 Policy p3 = 226 setupPolicy(2, Policy.PASSWORD_MODE_SIMPLE, 5, 6, true, 7, 8, 9, false, false); 227 assertTrue(p1.equals(p2)); 228 assertFalse(p2.equals(p3)); 229 } 230 231 /** 232 * Test the API to set/clear policy hold flags in an account 233 */ 234 public void testSetClearHoldFlag() { 235 Account a1 = ProviderTestUtils.setupAccount("holdflag-1", false, mMockContext); 236 a1.mFlags = Account.FLAGS_NOTIFY_NEW_MAIL; 237 a1.save(mMockContext); 238 Account a2 = ProviderTestUtils.setupAccount("holdflag-2", false, mMockContext); 239 a2.mFlags = Account.FLAGS_VIBRATE_ALWAYS | Account.FLAGS_SECURITY_HOLD; 240 a2.save(mMockContext); 241 242 // confirm clear until set 243 Account a1a = Account.restoreAccountWithId(mMockContext, a1.mId); 244 assertEquals(Account.FLAGS_NOTIFY_NEW_MAIL, a1a.mFlags); 245 SecurityPolicy.setAccountHoldFlag(mMockContext, a1, true); 246 assertEquals(Account.FLAGS_NOTIFY_NEW_MAIL | Account.FLAGS_SECURITY_HOLD, a1.mFlags); 247 Account a1b = Account.restoreAccountWithId(mMockContext, a1.mId); 248 assertEquals(Account.FLAGS_NOTIFY_NEW_MAIL | Account.FLAGS_SECURITY_HOLD, a1b.mFlags); 249 250 // confirm set until cleared 251 Account a2a = Account.restoreAccountWithId(mMockContext, a2.mId); 252 assertEquals(Account.FLAGS_VIBRATE_ALWAYS | Account.FLAGS_SECURITY_HOLD, a2a.mFlags); 253 SecurityPolicy.setAccountHoldFlag(mMockContext, a2, false); 254 assertEquals(Account.FLAGS_VIBRATE_ALWAYS, a2.mFlags); 255 Account a2b = Account.restoreAccountWithId(mMockContext, a2.mId); 256 assertEquals(Account.FLAGS_VIBRATE_ALWAYS, a2b.mFlags); 257 } 258 259 private static class MockController extends Controller { 260 protected MockController(Context context) { 261 super(context); 262 } 263 264 protected void backupAccounts(Context context) { 265 // For testing, we don't want to back up our accounts 266 } 267 } 268 269 /** 270 * Test the response to disabling DeviceAdmin status 271 */ 272 public void testDisableAdmin() { 273 Account a1 = ProviderTestUtils.setupAccount("disable-1", true, mMockContext); 274 Policy p1 = setupPolicy(10, Policy.PASSWORD_MODE_SIMPLE, 0, 0, false, 0, 0, 0, 275 false, false); 276 Policy.setAccountPolicy(mMockContext, a1, p1, "security-sync-key-1"); 277 278 Account a2 = ProviderTestUtils.setupAccount("disable-2", true, mMockContext); 279 Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0, 280 false, false); 281 Policy.setAccountPolicy(mMockContext, a2, p2, "security-sync-key-2"); 282 283 Account a3 = ProviderTestUtils.setupAccount("disable-3", true, mMockContext); 284 Policy.clearAccountPolicy(mMockContext, a3); 285 286 mSecurityPolicy = SecurityPolicy.getInstance(mMockContext); 287 288 // Confirm that "enabling" device admin does not change security status (policy & sync key) 289 Policy before = mSecurityPolicy.getAggregatePolicy(); 290 mSecurityPolicy.onAdminEnabled(true); // "enabled" should not change anything 291 Policy after1 = mSecurityPolicy.getAggregatePolicy(); 292 assertEquals(before, after1); 293 Account a1a = Account.restoreAccountWithId(mMockContext, a1.mId); 294 assertNotNull(a1a.mSecuritySyncKey); 295 assertTrue(a1a.mPolicyKey > 0); 296 Account a2a = Account.restoreAccountWithId(mMockContext, a2.mId); 297 assertNotNull(a2a.mSecuritySyncKey); 298 assertTrue(a2a.mPolicyKey > 0); 299 Account a3a = Account.restoreAccountWithId(mMockContext, a3.mId); 300 assertNull(a3a.mSecuritySyncKey); 301 assertTrue(a3a.mPolicyKey == 0); 302 303 // Simulate revoke of device admin; directly call deleteSecuredAccounts, which is normally 304 // called from a background thread 305 MockController mockController = new MockController(mMockContext); 306 Controller.injectMockControllerForTest(mockController); 307 try { 308 mSecurityPolicy.deleteSecuredAccounts(mMockContext); 309 Policy after2 = mSecurityPolicy.getAggregatePolicy(); 310 assertEquals(EMPTY_POLICY, after2); 311 Account a1b = Account.restoreAccountWithId(mMockContext, a1.mId); 312 assertNull(a1b); 313 Account a2b = Account.restoreAccountWithId(mMockContext, a2.mId); 314 assertNull(a2b); 315 Account a3b = Account.restoreAccountWithId(mMockContext, a3.mId); 316 assertNull(a3b.mSecuritySyncKey); 317 } finally { 318 Controller.injectMockControllerForTest(null); 319 } 320 } 321 322 /** 323 * Test the scanner that finds expiring accounts 324 */ 325 public void testFindExpiringAccount() { 326 ProviderTestUtils.setupAccount("expiring-1", true, mMockContext); 327 328 // With no expiring accounts, this should return null. 329 long nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext); 330 assertEquals(-1, nextExpiringAccountId); 331 332 // Add a single expiring account 333 Account a2 = 334 ProviderTestUtils.setupAccount("expiring-2", true, mMockContext); 335 Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0, 336 false, false); 337 Policy.setAccountPolicy(mMockContext, a2, p2, null); 338 339 // The expiring account should be returned 340 nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext); 341 assertEquals(a2.mId, nextExpiringAccountId); 342 343 // Add an account with a longer expiration 344 Account a3 = ProviderTestUtils.setupAccount("expiring-3", true, mMockContext); 345 Policy p3 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 60, 0, 0, 346 false, false); 347 Policy.setAccountPolicy(mMockContext, a3, p3, null); 348 349 // The original expiring account (a2) should be returned 350 nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext); 351 assertEquals(a2.mId, nextExpiringAccountId); 352 353 // Add an account with a shorter expiration 354 Account a4 = ProviderTestUtils.setupAccount("expiring-4", true, mMockContext); 355 Policy p4 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 15, 0, 0, 356 false, false); 357 Policy.setAccountPolicy(mMockContext, a4, p4, null); 358 359 // The new expiring account (a4) should be returned 360 nextExpiringAccountId = SecurityPolicy.findShortestExpiration(mMockContext); 361 assertEquals(a4.mId, nextExpiringAccountId); 362 } 363 364 /** 365 * Lightweight subclass of the Controller class allows injection of mock context 366 */ 367 public static class TestController extends Controller { 368 369 protected TestController(Context providerContext, Context systemContext) { 370 super(systemContext); 371 setProviderContext(providerContext); 372 } 373 } 374 375 /** 376 * Test the scanner that wipes expiring accounts 377 */ 378 public void testWipeExpiringAccounts() { 379 mSecurityPolicy = SecurityPolicy.getInstance(mMockContext); 380 TestController testController = new TestController(mMockContext, getContext()); 381 382 // Two accounts - a1 is normal, a2 has security (but no expiration) 383 Account a1 = ProviderTestUtils.setupAccount("expired-1", true, mMockContext); 384 Account a2 = ProviderTestUtils.setupAccount("expired-2", true, mMockContext); 385 Policy p2 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 0, 0, 0, 386 false, false); 387 Policy.setAccountPolicy(mMockContext, a2, p2, null); 388 389 // Add a mailbox & messages to each account 390 long account1Id = a1.mId; 391 long account2Id = a2.mId; 392 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 393 long box1Id = box1.mId; 394 ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, true, mMockContext); 395 ProviderTestUtils.setupMessage("message2", account1Id, box1Id, false, true, mMockContext); 396 Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account2Id, true, mMockContext); 397 long box2Id = box2.mId; 398 ProviderTestUtils.setupMessage("message3", account2Id, box2Id, false, true, mMockContext); 399 ProviderTestUtils.setupMessage("message4", account2Id, box2Id, false, true, mMockContext); 400 401 // Run the expiration code - should do nothing 402 boolean wiped = SecurityPolicy.wipeExpiredAccounts(mMockContext, testController); 403 assertFalse(wiped); 404 // check mailboxes & messages not wiped 405 assertEquals(2, EmailContent.count(mMockContext, Account.CONTENT_URI)); 406 assertEquals(2, EmailContent.count(mMockContext, Mailbox.CONTENT_URI)); 407 assertEquals(4, EmailContent.count(mMockContext, Message.CONTENT_URI)); 408 409 // Add 3rd account that really expires 410 Account a3 = ProviderTestUtils.setupAccount("expired-3", true, mMockContext); 411 Policy p3 = setupPolicy(20, Policy.PASSWORD_MODE_STRONG, 25, 26, false, 30, 0, 0, 412 false, false); 413 Policy.setAccountPolicy(mMockContext, a3, p3, null); 414 415 // Add mailbox & messages to 3rd account 416 long account3Id = a3.mId; 417 Mailbox box3 = ProviderTestUtils.setupMailbox("box3", account3Id, true, mMockContext); 418 long box3Id = box3.mId; 419 ProviderTestUtils.setupMessage("message5", account3Id, box3Id, false, true, mMockContext); 420 ProviderTestUtils.setupMessage("message6", account3Id, box3Id, false, true, mMockContext); 421 422 // check new counts 423 assertEquals(3, EmailContent.count(mMockContext, Account.CONTENT_URI)); 424 assertEquals(3, EmailContent.count(mMockContext, Mailbox.CONTENT_URI)); 425 assertEquals(6, EmailContent.count(mMockContext, Message.CONTENT_URI)); 426 427 // Run the expiration code - wipe acct #3 428 wiped = SecurityPolicy.wipeExpiredAccounts(mMockContext, testController); 429 assertTrue(wiped); 430 // check new counts - account survives but data is wiped 431 assertEquals(3, EmailContent.count(mMockContext, Account.CONTENT_URI)); 432 assertEquals(2, EmailContent.count(mMockContext, Mailbox.CONTENT_URI)); 433 assertEquals(4, EmailContent.count(mMockContext, Message.CONTENT_URI)); 434 435 // Check security hold states - only #3 should be in hold 436 Account account = Account.restoreAccountWithId(mMockContext, account1Id); 437 assertEquals(0, account.mFlags & Account.FLAGS_SECURITY_HOLD); 438 account = Account.restoreAccountWithId(mMockContext, account2Id); 439 assertEquals(0, account.mFlags & Account.FLAGS_SECURITY_HOLD); 440 account = Account.restoreAccountWithId(mMockContext, account3Id); 441 assertEquals(Account.FLAGS_SECURITY_HOLD, account.mFlags & Account.FLAGS_SECURITY_HOLD); 442 } 443 444 /** 445 * Test the code that clears unsupported policies 446 * TODO inject a mock DPM so we can directly control & test all cases, no matter what device 447 */ 448 public void testClearUnsupportedPolicies() { 449 Policy p1 = 450 setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, false); 451 Policy p2 = 452 setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, true, false); 453 Policy p3 = 454 setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, true); 455 456 mSecurityPolicy = SecurityPolicy.getInstance(mMockContext); 457 DevicePolicyManager dpm = mSecurityPolicy.getDPM(); 458 boolean hasEncryption = 459 dpm.getStorageEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED; 460 461 Policy p1Result = mSecurityPolicy.clearUnsupportedPolicies(p1); 462 Policy p2Result = mSecurityPolicy.clearUnsupportedPolicies(p2); 463 Policy p3Result = mSecurityPolicy.clearUnsupportedPolicies(p3); 464 465 // No changes expected when encryptionRequested bits were false 466 assertEquals(p1, p1Result); 467 if (hasEncryption) { 468 // No changes expected 469 // NOTE: TODO: Modify to check for external encryption cleared on devices that 470 // won't support it (e.g. having only unencrypted, removable storage.) 471 assertEquals(p2, p2Result); 472 assertEquals(p3, p3Result); 473 } else { 474 // If encryption is unsupported, encryption policy bits are cleared 475 Policy policyExpect = 476 setupPolicy(1, Policy.PASSWORD_MODE_STRONG, 3, 4, true, 7, 8, 9, false, 477 false); 478 assertEquals(policyExpect, p2Result); 479 assertEquals(policyExpect, p3Result); 480 } 481 } 482 483 /** 484 * Test the code that converts from exchange-style quality to DPM/Lockscreen style quality. 485 */ 486 public void testGetDPManagerPasswordQuality() { 487 // Policy.PASSWORD_MODE_NONE -> DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED 488 Policy p1 = setupPolicy(0, Policy.PASSWORD_MODE_NONE, 489 0, 0, false, 0, 0, 0, false, false); 490 assertEquals(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 491 p1.getDPManagerPasswordQuality()); 492 493 // PASSWORD_MODE_SIMPLE -> PASSWORD_QUALITY_NUMERIC 494 Policy p2 = setupPolicy(4, Policy.PASSWORD_MODE_SIMPLE, 495 0, 0, false, 0, 0, 0, false, false); 496 assertEquals(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC, 497 p2.getDPManagerPasswordQuality()); 498 499 // PASSWORD_MODE_STRONG -> PASSWORD_QUALITY_ALPHANUMERIC 500 Policy p3 = setupPolicy(4, Policy.PASSWORD_MODE_STRONG, 501 0, 0, false, 0, 0, 0, false, false); 502 assertEquals(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, 503 p3.getDPManagerPasswordQuality()); 504 505 // PASSWORD_MODE_STRONG + complex chars -> PASSWORD_QUALITY_COMPLEX 506 Policy p4 = setupPolicy(4, Policy.PASSWORD_MODE_STRONG, 507 0, 0, false, 0, 0 , 2, false, false); 508 assertEquals(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX, 509 p4.getDPManagerPasswordQuality()); 510 } 511 512 private boolean policySetEqualsPolicy(PolicySet ps, Policy policy) { 513 if ((ps.mPasswordMode >> LegacyPolicySet.PASSWORD_MODE_SHIFT) != policy.mPasswordMode) { 514 return false; 515 } 516 if (ps.mMinPasswordLength != policy.mPasswordMinLength) return false; 517 if (ps.mPasswordComplexChars != policy.mPasswordComplexChars) return false; 518 if (ps.mPasswordHistory != policy.mPasswordHistory) return false; 519 if (ps.mPasswordExpirationDays != policy.mPasswordExpirationDays) return false; 520 if (ps.mMaxPasswordFails != policy.mPasswordMaxFails) return false; 521 if (ps.mMaxScreenLockTime != policy.mMaxScreenLockTime) return false; 522 if (ps.mRequireRemoteWipe != policy.mRequireRemoteWipe) return false; 523 if (ps.mRequireEncryption != policy.mRequireEncryption) return false; 524 if (ps.mRequireEncryptionExternal != policy.mRequireEncryptionExternal) return false; 525 return true; 526 } 527 528 public void testPolicyFlagsToPolicy() { 529 // Policy flags; the three sets included here correspond to policies for three test 530 // accounts that, between them, use all of the possible policies 531 long flags = 67096612L; 532 PolicySet ps = new PolicySet(flags); 533 Policy policy = LegacyPolicySet.flagsToPolicy(flags); 534 assertTrue(policySetEqualsPolicy(ps, policy)); 535 flags = 52776591691846L; 536 ps = new PolicySet(flags); 537 policy = LegacyPolicySet.flagsToPolicy(flags); 538 assertTrue(policySetEqualsPolicy(ps, policy)); 539 flags = 1689605957029924L; 540 ps = new PolicySet(flags); 541 policy = LegacyPolicySet.flagsToPolicy(flags); 542 assertTrue(policySetEqualsPolicy(ps, policy)); 543 } 544 545 /** 546 * The old PolicySet class fields and constructor; we use this to test conversion to the 547 * new Policy table scheme 548 */ 549 private static class PolicySet { 550 private final int mMinPasswordLength; 551 private final int mPasswordMode; 552 private final int mMaxPasswordFails; 553 private final int mMaxScreenLockTime; 554 private final boolean mRequireRemoteWipe; 555 private final int mPasswordExpirationDays; 556 private final int mPasswordHistory; 557 private final int mPasswordComplexChars; 558 private final boolean mRequireEncryption; 559 private final boolean mRequireEncryptionExternal; 560 561 /** 562 * Create from values encoded in an account flags int 563 */ 564 private PolicySet(long flags) { 565 mMinPasswordLength = (int) ((flags & LegacyPolicySet.PASSWORD_LENGTH_MASK) 566 >> LegacyPolicySet.PASSWORD_LENGTH_SHIFT); 567 mPasswordMode = 568 (int) (flags & LegacyPolicySet.PASSWORD_MODE_MASK); 569 mMaxPasswordFails = (int) ((flags & LegacyPolicySet.PASSWORD_MAX_FAILS_MASK) 570 >> LegacyPolicySet.PASSWORD_MAX_FAILS_SHIFT); 571 mMaxScreenLockTime = (int) ((flags & LegacyPolicySet.SCREEN_LOCK_TIME_MASK) 572 >> LegacyPolicySet.SCREEN_LOCK_TIME_SHIFT); 573 mRequireRemoteWipe = 0 != (flags & LegacyPolicySet.REQUIRE_REMOTE_WIPE); 574 mPasswordExpirationDays = (int) ((flags & LegacyPolicySet.PASSWORD_EXPIRATION_MASK) 575 >> LegacyPolicySet.PASSWORD_EXPIRATION_SHIFT); 576 mPasswordHistory = (int) ((flags & LegacyPolicySet.PASSWORD_HISTORY_MASK) 577 >> LegacyPolicySet.PASSWORD_HISTORY_SHIFT); 578 mPasswordComplexChars = (int) ((flags & LegacyPolicySet.PASSWORD_COMPLEX_CHARS_MASK) 579 >> LegacyPolicySet.PASSWORD_COMPLEX_CHARS_SHIFT); 580 mRequireEncryption = 0 != (flags & LegacyPolicySet.REQUIRE_ENCRYPTION); 581 mRequireEncryptionExternal = 0 != (flags & LegacyPolicySet.REQUIRE_ENCRYPTION_EXTERNAL); 582 } 583 } 584} 585