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