1/* 2 * Copyright (C) 2016 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 */ 16package com.android.managedprovisioning.preprovisioning; 17 18import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; 19import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE; 20import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE; 21import static android.app.admin.DevicePolicyManager.CODE_MANAGED_USERS_NOT_SUPPORTED; 22import static android.app.admin.DevicePolicyManager.CODE_OK; 23import static android.nfc.NfcAdapter.ACTION_NDEF_DISCOVERED; 24 25import static com.android.managedprovisioning.common.Globals.ACTION_RESUME_PROVISIONING; 26 27import static org.mockito.Mockito.any; 28import static org.mockito.Mockito.anyInt; 29import static org.mockito.Mockito.anyString; 30import static org.mockito.Mockito.eq; 31import static org.mockito.Mockito.never; 32import static org.mockito.Mockito.verify; 33import static org.mockito.Mockito.verifyNoMoreInteractions; 34import static org.mockito.Mockito.verifyZeroInteractions; 35import static org.mockito.Mockito.when; 36 37import static java.util.Collections.emptyList; 38 39import android.app.ActivityManager; 40import android.app.KeyguardManager; 41import android.app.admin.DevicePolicyManager; 42import android.content.ComponentName; 43import android.content.Context; 44import android.content.Intent; 45import android.content.pm.ApplicationInfo; 46import android.content.pm.PackageInfo; 47import android.content.pm.PackageManager; 48import android.content.res.Resources; 49import android.graphics.drawable.VectorDrawable; 50import android.os.UserHandle; 51import android.os.UserManager; 52import android.service.persistentdata.PersistentDataBlockManager; 53import android.support.test.InstrumentationRegistry; 54import android.support.test.filters.SmallTest; 55import android.test.AndroidTestCase; 56import android.text.TextUtils; 57 58import com.android.managedprovisioning.R; 59import com.android.managedprovisioning.analytics.TimeLogger; 60import com.android.managedprovisioning.common.IllegalProvisioningArgumentException; 61import com.android.managedprovisioning.common.SettingsFacade; 62import com.android.managedprovisioning.common.Utils; 63import com.android.managedprovisioning.model.ProvisioningParams; 64import com.android.managedprovisioning.model.WifiInfo; 65import com.android.managedprovisioning.parser.MessageParser; 66 67import org.mockito.Mock; 68import org.mockito.MockitoAnnotations; 69 70@SmallTest 71public class PreProvisioningControllerTest extends AndroidTestCase { 72 private static final String TEST_MDM_PACKAGE = "com.test.mdm"; 73 private static final String TEST_MDM_PACKAGE_LABEL = "Test MDM"; 74 private static final ComponentName TEST_MDM_COMPONENT_NAME = new ComponentName(TEST_MDM_PACKAGE, 75 "com.test.mdm.DeviceAdmin"); 76 private static final String TEST_BOGUS_PACKAGE = "com.test.bogus"; 77 private static final String TEST_WIFI_SSID = "TestNet"; 78 private static final String MP_PACKAGE_NAME = "com.android.managedprovisioning"; 79 private static final int TEST_USER_ID = 10; 80 81 @Mock 82 private Context mContext; 83 @Mock 84 Resources mResources; 85 @Mock 86 private DevicePolicyManager mDevicePolicyManager; 87 @Mock 88 private UserManager mUserManager; 89 @Mock 90 private PackageManager mPackageManager; 91 @Mock 92 private ActivityManager mActivityManager; 93 @Mock 94 private KeyguardManager mKeyguardManager; 95 @Mock 96 private PersistentDataBlockManager mPdbManager; 97 @Mock 98 private PreProvisioningController.Ui mUi; 99 @Mock 100 private MessageParser mMessageParser; 101 @Mock 102 private Utils mUtils; 103 @Mock 104 private SettingsFacade mSettingsFacade; 105 @Mock 106 private Intent mIntent; 107 @Mock 108 private EncryptionController mEncryptionController; 109 @Mock 110 private TimeLogger mTimeLogger; 111 112 private ProvisioningParams mParams; 113 114 private PreProvisioningController mController; 115 116 @Override 117 public void setUp() throws PackageManager.NameNotFoundException { 118 // this is necessary for mockito to work 119 System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString()); 120 121 MockitoAnnotations.initMocks(this); 122 123 when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)) 124 .thenReturn(mDevicePolicyManager); 125 when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); 126 when(mContext.getPackageManager()).thenReturn(mPackageManager); 127 when(mContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(mActivityManager); 128 when(mContext.getSystemService(Context.KEYGUARD_SERVICE)).thenReturn(mKeyguardManager); 129 when(mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE)) 130 .thenReturn(mPdbManager); 131 when(mContext.getPackageName()).thenReturn(MP_PACKAGE_NAME); 132 when(mContext.getResources()).thenReturn( 133 InstrumentationRegistry.getTargetContext().getResources()); 134 135 when(mUserManager.getUserHandle()).thenReturn(TEST_USER_ID); 136 137 when(mUtils.isSplitSystemUser()).thenReturn(false); 138 when(mUtils.isEncryptionRequired()).thenReturn(false); 139 when(mUtils.currentLauncherSupportsManagedProfiles(mContext)).thenReturn(true); 140 when(mUtils.alreadyHasManagedProfile(mContext)).thenReturn(-1); 141 142 when(mPackageManager.getApplicationIcon(anyString())).thenReturn(new VectorDrawable()); 143 when(mPackageManager.getApplicationLabel(any())).thenReturn(TEST_MDM_PACKAGE_LABEL); 144 145 when(mKeyguardManager.inKeyguardRestrictedInputMode()).thenReturn(false); 146 when(mDevicePolicyManager.getStorageEncryptionStatus()) 147 .thenReturn(DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE); 148 mController = new PreProvisioningController(mContext, mUi, mTimeLogger, mMessageParser, 149 mUtils, mSettingsFacade, mEncryptionController); 150 } 151 152 public void testManagedProfile() throws Exception { 153 // GIVEN an intent to provision a managed profile 154 prepareMocksForManagedProfileIntent(false); 155 // WHEN initiating provisioning 156 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 157 // THEN the UI elements should be updated accordingly 158 verifyInitiateProfileOwnerUi(); 159 // WHEN the user consents 160 mController.continueProvisioningAfterUserConsent(); 161 // THEN start profile provisioning 162 verify(mUi).startProvisioning(mUserManager.getUserHandle(), mParams); 163 verify(mEncryptionController).cancelEncryptionReminder(); 164 verifyNoMoreInteractions(mUi); 165 } 166 167 public void testManagedProfile_provisioningNotAllowed() throws Exception { 168 // GIVEN an intent to provision a managed profile, but provisioning mode is not allowed 169 prepareMocksForManagedProfileIntent(false); 170 when(mDevicePolicyManager.checkProvisioningPreCondition( 171 ACTION_PROVISION_MANAGED_PROFILE, TEST_MDM_PACKAGE)) 172 .thenReturn(CODE_MANAGED_USERS_NOT_SUPPORTED); 173 // WHEN initiating provisioning 174 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 175 // THEN show an error dialog 176 verify(mUi).showErrorAndClose(eq(R.string.cant_add_work_profile), 177 eq(R.string.work_profile_cant_be_added_contact_admin), any()); 178 verifyNoMoreInteractions(mUi); 179 } 180 181 public void testManagedProfile_nullCallingPackage() throws Exception { 182 // GIVEN a device that is not currently encrypted 183 prepareMocksForManagedProfileIntent(false); 184 // WHEN initiating provisioning 185 mController.initiateProvisioning(mIntent, null, null); 186 // THEN error is shown 187 verify(mUi).showErrorAndClose(eq(R.string.cant_set_up_device), 188 eq(R.string.contact_your_admin_for_help), any(String.class)); 189 verifyNoMoreInteractions(mUi); 190 } 191 192 public void testManagedProfile_invalidCallingPackage() throws Exception { 193 // GIVEN a device that is not currently encrypted 194 prepareMocksForManagedProfileIntent(false); 195 // WHEN initiating provisioning 196 mController.initiateProvisioning(mIntent, null, "com.android.invalid.dpc"); 197 // THEN error is shown 198 verify(mUi).showErrorAndClose(eq(R.string.cant_set_up_device), 199 eq(R.string.contact_your_admin_for_help), any(String.class)); 200 verifyNoMoreInteractions(mUi); 201 } 202 203 public void testManagedProfile_withEncryption() throws Exception { 204 // GIVEN a device that is not currently encrypted 205 prepareMocksForManagedProfileIntent(false); 206 when(mUtils.isEncryptionRequired()).thenReturn(true); 207 // WHEN initiating managed profile provisioning 208 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 209 // WHEN the user consents 210 mController.continueProvisioningAfterUserConsent(); 211 // THEN the UI elements should be updated accordingly 212 verifyInitiateProfileOwnerUi(); 213 // THEN show encryption screen 214 verify(mUi).requestEncryption(mParams); 215 verifyNoMoreInteractions(mUi); 216 } 217 218 public void testManagedProfile_afterEncryption() throws Exception { 219 // GIVEN managed profile provisioning continues after successful encryption. In this case 220 // we don't set the startedByTrustedSource flag. 221 prepareMocksForAfterEncryption(ACTION_PROVISION_MANAGED_PROFILE, false); 222 // WHEN initiating with a continuation intent 223 mController.initiateProvisioning(mIntent, null, MP_PACKAGE_NAME); 224 // THEN the UI elements should be updated accordingly 225 verifyInitiateProfileOwnerUi(); 226 // WHEN the user consents 227 mController.continueProvisioningAfterUserConsent(); 228 // THEN start profile provisioning 229 verify(mUi).startProvisioning(mUserManager.getUserHandle(), mParams); 230 verify(mEncryptionController).cancelEncryptionReminder(); 231 verifyNoMoreInteractions(mUi); 232 } 233 234 public void testManagedProfile_withExistingProfile() throws Exception { 235 // GIVEN a managed profile currently exist on the device 236 prepareMocksForManagedProfileIntent(false); 237 when(mUtils.alreadyHasManagedProfile(mContext)).thenReturn(TEST_USER_ID); 238 // WHEN initiating managed profile provisioning 239 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 240 // THEN the UI elements should be updated accordingly and a dialog to remove the existing 241 // profile should be shown 242 verifyInitiateProfileOwnerUi(); 243 verify(mUi).showDeleteManagedProfileDialog(any(), any(), eq(TEST_USER_ID)); 244 // WHEN the user consents 245 mController.continueProvisioningAfterUserConsent(); 246 // THEN start profile provisioning 247 verify(mUi).startProvisioning(mUserManager.getUserHandle(), mParams); 248 verify(mEncryptionController).cancelEncryptionReminder(); 249 verifyNoMoreInteractions(mUi); 250 } 251 252 public void testManagedProfile_badLauncher() throws Exception { 253 // GIVEN that the current launcher does not support managed profiles 254 prepareMocksForManagedProfileIntent(false); 255 when(mUtils.currentLauncherSupportsManagedProfiles(mContext)).thenReturn(false); 256 // WHEN initiating managed profile provisioning 257 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 258 // THEN the UI elements should be updated accordingly 259 verifyInitiateProfileOwnerUi(); 260 // WHEN the user consents 261 mController.continueProvisioningAfterUserConsent(); 262 // THEN show a dialog indicating that the current launcher is invalid 263 verify(mUi).showCurrentLauncherInvalid(); 264 verifyNoMoreInteractions(mUi); 265 } 266 267 public void testManagedProfile_wrongPackage() throws Exception { 268 // GIVEN that the provisioning intent tries to set a package different from the caller 269 // as owner of the profile 270 prepareMocksForManagedProfileIntent(false); 271 // WHEN initiating managed profile provisioning 272 mController.initiateProvisioning(mIntent, null, TEST_BOGUS_PACKAGE); 273 // THEN show an error dialog and do not continue 274 verify(mUi).showErrorAndClose(eq(R.string.cant_set_up_device), 275 eq(R.string.contact_your_admin_for_help), any()); 276 verifyNoMoreInteractions(mUi); 277 } 278 279 public void testManagedProfile_frp() throws Exception { 280 // GIVEN managed profile provisioning is invoked from SUW with FRP active 281 prepareMocksForManagedProfileIntent(false); 282 when(mSettingsFacade.isDeviceProvisioned(mContext)).thenReturn(false); 283 // setting the data block size to any number greater than 0 should invoke FRP. 284 when(mPdbManager.getDataBlockSize()).thenReturn(4); 285 // WHEN initiating managed profile provisioning 286 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 287 // THEN show an error dialog and do not continue 288 verify(mUi).showErrorAndClose(eq(R.string.cant_set_up_device), 289 eq(R.string.device_has_reset_protection_contact_admin), any()); 290 verifyNoMoreInteractions(mUi); 291 } 292 293 public void testCheckFactoryResetProtection_skipFrp() throws Exception { 294 // GIVEN managed profile provisioning is invoked from SUW with FRP active 295 when(mSettingsFacade.isDeviceProvisioned(mContext)).thenReturn(false); 296 // setting the data block size to any number greater than 0 to simulate FRP. 297 when(mPdbManager.getDataBlockSize()).thenReturn(4); 298 // GIVEN there is a persistent data package. 299 when(mContext.getResources()).thenReturn(mResources); 300 when(mResources.getString(anyInt())).thenReturn("test.persistent.data"); 301 // GIVEN the persistent data package is a system app. 302 PackageInfo packageInfo = new PackageInfo(); 303 ApplicationInfo applicationInfo = new ApplicationInfo(); 304 applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM; 305 packageInfo.applicationInfo = applicationInfo; 306 when(mPackageManager.getPackageInfo(eq("test.persistent.data"), anyInt())) 307 .thenReturn(packageInfo); 308 309 // WHEN factory reset protection is checked for trusted source device provisioning. 310 ProvisioningParams provisioningParams = createParams(true, false, null, 311 ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE, TEST_MDM_PACKAGE); 312 boolean result = mController.checkFactoryResetProtection( 313 provisioningParams, "test.persistent.data"); 314 315 // THEN the check is successful despite the FRP data presence. 316 assertTrue(result); 317 } 318 319 public void testManagedProfile_skipEncryption() throws Exception { 320 // GIVEN an intent to provision a managed profile with skip encryption 321 prepareMocksForManagedProfileIntent(true); 322 when(mUtils.isEncryptionRequired()).thenReturn(true); 323 // WHEN initiating provisioning 324 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 325 // THEN the UI elements should be updated accordingly 326 verifyInitiateProfileOwnerUi(); 327 // WHEN the user consents 328 mController.continueProvisioningAfterUserConsent(); 329 // THEN start profile provisioning 330 verify(mUi).startProvisioning(mUserManager.getUserHandle(), mParams); 331 verify(mUi, never()).requestEncryption(any(ProvisioningParams.class)); 332 verify(mEncryptionController).cancelEncryptionReminder(); 333 verifyNoMoreInteractions(mUi); 334 } 335 336 public void testManagedProfile_encryptionNotSupported() throws Exception { 337 // GIVEN an intent to provision a managed profile on an unencrypted device that does not 338 // support encryption 339 prepareMocksForManagedProfileIntent(false); 340 when(mUtils.isEncryptionRequired()).thenReturn(true); 341 when(mDevicePolicyManager.getStorageEncryptionStatus()) 342 .thenReturn(DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED); 343 // WHEN initiating provisioning 344 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 345 // WHEN the user consents 346 mController.continueProvisioningAfterUserConsent(); 347 // THEN the UI elements should be updated accordingly 348 verifyInitiateProfileOwnerUi(); 349 // THEN show an error indicating that this device does not support encryption 350 verify(mUi).showErrorAndClose(eq(R.string.cant_set_up_device), 351 eq(R.string.device_doesnt_allow_encryption_contact_admin), any()); 352 verifyNoMoreInteractions(mUi); 353 } 354 355 public void testNfc() throws Exception { 356 // GIVEN provisioning was started via an NFC tap and device is already encrypted 357 prepareMocksForNfcIntent(ACTION_PROVISION_MANAGED_DEVICE, false); 358 // WHEN initiating NFC provisioning 359 mController.initiateProvisioning(mIntent, null, null); 360 // WHEN the user consents 361 mController.continueProvisioningAfterUserConsent(); 362 // THEN start device owner provisioning 363 verifyInitiateDeviceOwnerUi(); 364 verify(mUi).startProvisioning(mUserManager.getUserHandle(), mParams); 365 verify(mEncryptionController).cancelEncryptionReminder(); 366 verifyNoMoreInteractions(mUi); 367 } 368 369 public void testNfc_skipEncryption() throws Exception { 370 // GIVEN provisioning was started via an NFC tap with encryption skipped 371 prepareMocksForNfcIntent(ACTION_PROVISION_MANAGED_DEVICE, true); 372 when(mUtils.isEncryptionRequired()).thenReturn(true); 373 // WHEN initiating NFC provisioning 374 375 mController.initiateProvisioning(mIntent, null, null); 376 // WHEN the user consents 377 mController.continueProvisioningAfterUserConsent(); 378 // THEN start device owner provisioning 379 verifyInitiateDeviceOwnerUi(); 380 verify(mUi).startProvisioning(mUserManager.getUserHandle(), mParams); 381 verify(mUi, never()).requestEncryption(any(ProvisioningParams.class)); 382 verify(mEncryptionController).cancelEncryptionReminder(); 383 verifyNoMoreInteractions(mUi); 384 } 385 386 public void testNfc_withEncryption() throws Exception { 387 // GIVEN provisioning was started via an NFC tap with encryption necessary 388 prepareMocksForNfcIntent(ACTION_PROVISION_MANAGED_DEVICE, false); 389 when(mUtils.isEncryptionRequired()).thenReturn(true); 390 // WHEN initiating NFC provisioning 391 mController.initiateProvisioning(mIntent, null, null); 392 // WHEN the user consents 393 mController.continueProvisioningAfterUserConsent(); 394 // THEN show encryption screen 395 verifyInitiateDeviceOwnerUi(); 396 verify(mUi).requestEncryption(mParams); 397 verifyNoMoreInteractions(mUi); 398 } 399 400 public void testNfc_afterEncryption() throws Exception { 401 // GIVEN provisioning was started via an NFC tap and we have gone through encryption 402 // in this case the device gets resumed with the DO intent and startedByTrustedSource flag 403 // set 404 prepareMocksForAfterEncryption(ACTION_PROVISION_MANAGED_DEVICE, true); 405 // WHEN continuing NFC provisioning after encryption 406 mController.initiateProvisioning(mIntent, null, null); 407 // WHEN the user consents 408 mController.continueProvisioningAfterUserConsent(); 409 // THEN start device owner provisioning 410 verifyInitiateDeviceOwnerUi(); 411 verify(mUi).startProvisioning(mUserManager.getUserHandle(), mParams); 412 verifyNoMoreInteractions(mUi); 413 } 414 415 public void testNfc_frp() throws Exception { 416 // GIVEN provisioning was started via an NFC tap, but the device is locked with FRP 417 prepareMocksForNfcIntent(ACTION_PROVISION_MANAGED_DEVICE, false); 418 // setting the data block size to any number greater than 0 should invoke FRP. 419 when(mPdbManager.getDataBlockSize()).thenReturn(4); 420 // WHEN initiating NFC provisioning 421 mController.initiateProvisioning(mIntent, null, null); 422 // THEN show an error dialog 423 verify(mUi).showErrorAndClose(eq(R.string.cant_set_up_device), 424 eq(R.string.device_has_reset_protection_contact_admin), any()); 425 verifyNoMoreInteractions(mUi); 426 } 427 428 public void testNfc_encryptionNotSupported() throws Exception { 429 // GIVEN provisioning was started via an NFC tap, the device is not encrypted and encryption 430 // is not supported on the device 431 prepareMocksForNfcIntent(ACTION_PROVISION_MANAGED_DEVICE, false); 432 when(mUtils.isEncryptionRequired()).thenReturn(true); 433 when(mDevicePolicyManager.getStorageEncryptionStatus()) 434 .thenReturn(DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED); 435 // WHEN initiating NFC provisioning 436 mController.initiateProvisioning(mIntent, null, null); 437 // WHEN the user consents 438 mController.continueProvisioningAfterUserConsent(); 439 // THEN show an error dialog 440 verifyInitiateDeviceOwnerUi(); 441 verify(mUi).showErrorAndClose(eq(R.string.cant_set_up_device), 442 eq(R.string.device_doesnt_allow_encryption_contact_admin), any()); 443 verifyNoMoreInteractions(mUi); 444 } 445 446 public void testQr() throws Exception { 447 // GIVEN provisioning was started via a QR code and device is already encrypted 448 prepareMocksForQrIntent(ACTION_PROVISION_MANAGED_DEVICE, false); 449 // WHEN initiating QR provisioning 450 mController.initiateProvisioning(mIntent, null, null); 451 // WHEN the user consents 452 mController.continueProvisioningAfterUserConsent(); 453 // THEN start device owner provisioning 454 verifyInitiateDeviceOwnerUi(); 455 verify(mUi).startProvisioning(mUserManager.getUserHandle(), mParams); 456 verifyNoMoreInteractions(mUi); 457 } 458 459 public void testQr_skipEncryption() throws Exception { 460 // GIVEN provisioning was started via a QR code with encryption skipped 461 prepareMocksForQrIntent(ACTION_PROVISION_MANAGED_DEVICE, true); 462 when(mUtils.isEncryptionRequired()).thenReturn(true); 463 // WHEN initiating QR provisioning 464 mController.initiateProvisioning(mIntent, null, null); 465 // WHEN the user consents 466 mController.continueProvisioningAfterUserConsent(); 467 // THEN start device owner provisioning 468 verifyInitiateDeviceOwnerUi(); 469 verify(mUi).startProvisioning(mUserManager.getUserHandle(), mParams); 470 verify(mUi, never()).requestEncryption(any()); 471 verifyNoMoreInteractions(mUi); 472 } 473 474 public void testQr_withEncryption() throws Exception { 475 // GIVEN provisioning was started via a QR code with encryption necessary 476 prepareMocksForQrIntent(ACTION_PROVISION_MANAGED_DEVICE, false); 477 when(mUtils.isEncryptionRequired()).thenReturn(true); 478 // WHEN initiating QR provisioning 479 mController.initiateProvisioning(mIntent, null, null); 480 // WHEN the user consents 481 mController.continueProvisioningAfterUserConsent(); 482 // THEN show encryption screen 483 verifyInitiateDeviceOwnerUi(); 484 verify(mUi).requestEncryption(mParams); 485 verifyNoMoreInteractions(mUi); 486 } 487 488 public void testQr_frp() throws Exception { 489 // GIVEN provisioning was started via a QR code, but the device is locked with FRP 490 prepareMocksForQrIntent(ACTION_PROVISION_MANAGED_DEVICE, false); 491 // setting the data block size to any number greater than 0 should invoke FRP. 492 when(mPdbManager.getDataBlockSize()).thenReturn(4); 493 // WHEN initiating QR provisioning 494 mController.initiateProvisioning(mIntent, null, null); 495 // THEN show an error dialog 496 verify(mUi).showErrorAndClose(eq(R.string.cant_set_up_device), 497 eq(R.string.device_has_reset_protection_contact_admin), any()); 498 verifyNoMoreInteractions(mUi); 499 } 500 501 public void testDeviceOwner() throws Exception { 502 // GIVEN device owner provisioning was started and device is already encrypted 503 prepareMocksForDoIntent(true); 504 // WHEN initiating provisioning 505 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 506 // THEN the UI elements should be updated accordingly 507 verifyInitiateDeviceOwnerUi(); 508 // WHEN the user consents 509 mController.continueProvisioningAfterUserConsent(); 510 // THEN start device owner provisioning 511 verify(mUi).startProvisioning(mUserManager.getUserHandle(), mParams); 512 verify(mEncryptionController).cancelEncryptionReminder(); 513 verifyNoMoreInteractions(mUi); 514 } 515 516 public void testDeviceOwner_skipEncryption() throws Exception { 517 // GIVEN device owner provisioning was started with skip encryption flag 518 prepareMocksForDoIntent(true); 519 when(mUtils.isEncryptionRequired()).thenReturn(true); 520 // WHEN initiating provisioning 521 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 522 // THEN the UI elements should be updated accordingly 523 verifyInitiateDeviceOwnerUi(); 524 // WHEN the user consents 525 mController.continueProvisioningAfterUserConsent(); 526 // THEN start device owner provisioning 527 verify(mUi).startProvisioning(mUserManager.getUserHandle(), mParams); 528 verify(mUi, never()).requestEncryption(any()); 529 verify(mEncryptionController).cancelEncryptionReminder(); 530 verifyNoMoreInteractions(mUi); 531 } 532 533 // TODO: There is a difference in behaviour here between the managed profile and the device 534 // owner case: In managed profile case, we invoke encryption after user clicks next, but in 535 // device owner mode we invoke it straight away. Also in theory no need to update 536 // the UI elements if we're moving away from this activity straight away. 537 public void testDeviceOwner_withEncryption() throws Exception { 538 // GIVEN device owner provisioning is started with encryption needed 539 prepareMocksForDoIntent(false); 540 when(mUtils.isEncryptionRequired()).thenReturn(true); 541 // WHEN initiating provisioning 542 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 543 // WHEN the user consents 544 mController.continueProvisioningAfterUserConsent(); 545 // THEN update the UI elements and show encryption screen 546 verifyInitiateDeviceOwnerUi(); 547 verify(mUi).requestEncryption(mParams); 548 verifyNoMoreInteractions(mUi); 549 } 550 551 public void testDeviceOwner_afterEncryption() throws Exception { 552 // GIVEN device owner provisioning is continued after encryption. In this case we do not set 553 // the startedByTrustedSource flag. 554 prepareMocksForAfterEncryption(ACTION_PROVISION_MANAGED_DEVICE, false); 555 // WHEN provisioning is continued 556 mController.initiateProvisioning(mIntent, null, null); 557 // THEN the UI elements should be updated accordingly 558 verifyInitiateDeviceOwnerUi(); 559 // WHEN the user consents 560 mController.continueProvisioningAfterUserConsent(); 561 // THEN start device owner provisioning 562 verify(mUi).startProvisioning(mUserManager.getUserHandle(), mParams); 563 verify(mEncryptionController).cancelEncryptionReminder(); 564 verifyNoMoreInteractions(mUi); 565 } 566 567 public void testNullParams() throws Exception { 568 // THEN verifying params is null initially 569 assertNull(mController.getParams()); 570 } 571 572 public void testDeviceOwner_frp() throws Exception { 573 // GIVEN device owner provisioning is invoked with FRP active 574 prepareMocksForDoIntent(false); 575 // setting the data block size to any number greater than 0 should invoke FRP. 576 when(mPdbManager.getDataBlockSize()).thenReturn(4); 577 // WHEN initiating provisioning 578 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 579 // THEN show an error dialog 580 verify(mUi).showErrorAndClose(eq(R.string.cant_set_up_device), 581 eq(R.string.device_has_reset_protection_contact_admin), any()); 582 verifyNoMoreInteractions(mUi); 583 } 584 585 public void testMaybeStartProfileOwnerProvisioningIfSkipUserConsent_continueProvisioning() 586 throws Exception { 587 // GIVEN skipping user consent and encryption 588 prepareMocksForMaybeStartProvisioning(true, true, false); 589 // WHEN calling initiateProvisioning 590 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 591 // THEN start profile owner provisioning 592 verify(mUi).startProvisioning(mUserManager.getUserHandle(), mParams); 593 } 594 595 public void testMaybeStartProfileOwnerProvisioningIfSkipUserConsent_notSkipUserConsent() 596 throws Exception { 597 // GIVEN not skipping user consent 598 prepareMocksForMaybeStartProvisioning(false, true, false); 599 // WHEN calling initiateProvisioning 600 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 601 // THEN not starting profile owner provisioning 602 verify(mUi, never()).startProvisioning(mUserManager.getUserHandle(), mParams); 603 } 604 605 public void testMaybeStartProfileOwnerProvisioningIfSkipUserConsent_requireEncryption() 606 throws Exception { 607 // GIVEN skipping user consent and encryption 608 prepareMocksForMaybeStartProvisioning(true, false, false); 609 // WHEN calling initiateProvisioning 610 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 611 // THEN not starting profile owner provisioning 612 verify(mUi, never()).startProvisioning(anyInt(), any()); 613 // THEN show encryption ui 614 verify(mUi).requestEncryption(mParams); 615 verifyNoMoreInteractions(mUi); 616 } 617 618 public void testMaybeStartProfileOwnerProvisioningIfSkipUserConsent_managedProfileExists() 619 throws Exception { 620 // GIVEN skipping user consent and encryption, but current managed profile exists 621 prepareMocksForMaybeStartProvisioning(true, true, true); 622 // WHEN calling initiateProvisioning 623 mController.initiateProvisioning(mIntent, null, TEST_MDM_PACKAGE); 624 // THEN not starting profile owner provisioning 625 verify(mUi, never()).startProvisioning(mUserManager.getUserHandle(), mParams); 626 // THEN show UI to delete user 627 verify(mUi).showDeleteManagedProfileDialog(any(), any(), anyInt()); 628 // WHEN user agrees to remove the current profile and continue provisioning 629 mController.continueProvisioningAfterUserConsent(); 630 // THEN start profile owner provisioning 631 verify(mUi).startProvisioning(mUserManager.getUserHandle(), mParams); 632 } 633 634 private void prepareMocksForMaybeStartProvisioning( 635 boolean skipUserConsent, boolean skipEncryption, boolean managedProfileExists) 636 throws IllegalProvisioningArgumentException { 637 String action = ACTION_PROVISION_MANAGED_PROFILE; 638 when(mDevicePolicyManager.checkProvisioningPreCondition(action, TEST_MDM_PACKAGE)) 639 .thenReturn(CODE_OK); 640 mParams = ProvisioningParams.Builder.builder() 641 .setProvisioningAction(action) 642 .setDeviceAdminComponentName(TEST_MDM_COMPONENT_NAME) 643 .setSkipUserConsent(skipUserConsent) 644 .build(); 645 646 when(mUtils.alreadyHasManagedProfile(mContext)).thenReturn( 647 managedProfileExists ? 10 : -1); 648 when(mUtils.isEncryptionRequired()).thenReturn(!skipEncryption); 649 650 651 when(mMessageParser.parse(mIntent)).thenReturn(mParams); 652 } 653 654 private void prepareMocksForManagedProfileIntent(boolean skipEncryption) throws Exception { 655 final String action = ACTION_PROVISION_MANAGED_PROFILE; 656 when(mIntent.getAction()).thenReturn(action); 657 when(mUtils.findDeviceAdmin(TEST_MDM_PACKAGE, null, mContext, UserHandle.myUserId())) 658 .thenReturn(TEST_MDM_COMPONENT_NAME); 659 when(mSettingsFacade.isDeviceProvisioned(mContext)).thenReturn(true); 660 when(mDevicePolicyManager.checkProvisioningPreCondition(action, TEST_MDM_PACKAGE)) 661 .thenReturn(CODE_OK); 662 when(mMessageParser.parse(mIntent)).thenReturn( 663 createParams(false, skipEncryption, null, action, TEST_MDM_PACKAGE)); 664 } 665 666 private void prepareMocksForNfcIntent(String action, boolean skipEncryption) throws Exception { 667 when(mIntent.getAction()).thenReturn(ACTION_NDEF_DISCOVERED); 668 when(mIntent.getComponent()).thenReturn(ComponentName.createRelative(MP_PACKAGE_NAME, 669 ".PreProvisioningActivityViaNfc")); 670 when(mDevicePolicyManager.checkProvisioningPreCondition(action, TEST_MDM_PACKAGE)) 671 .thenReturn(CODE_OK); 672 when(mMessageParser.parse(mIntent)).thenReturn( 673 createParams(true, skipEncryption, TEST_WIFI_SSID, action, TEST_MDM_PACKAGE)); 674 } 675 676 private void prepareMocksForQrIntent(String action, boolean skipEncryption) throws Exception { 677 when(mIntent.getAction()) 678 .thenReturn(ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE); 679 when(mIntent.getComponent()).thenReturn(ComponentName.createRelative(MP_PACKAGE_NAME, 680 ".PreProvisioningActivityViaTrustedApp")); 681 when(mDevicePolicyManager.checkProvisioningPreCondition(action, TEST_MDM_PACKAGE)) 682 .thenReturn(CODE_OK); 683 when(mMessageParser.parse(mIntent)).thenReturn( 684 createParams(true, skipEncryption, TEST_WIFI_SSID, action, TEST_MDM_PACKAGE)); 685 } 686 687 private void prepareMocksForDoIntent(boolean skipEncryption) throws Exception { 688 final String action = ACTION_PROVISION_MANAGED_DEVICE; 689 when(mIntent.getAction()).thenReturn(action); 690 when(mDevicePolicyManager.checkProvisioningPreCondition(action, TEST_MDM_PACKAGE)) 691 .thenReturn(CODE_OK); 692 when(mMessageParser.parse(mIntent)).thenReturn( 693 createParams(false, skipEncryption, TEST_WIFI_SSID, action, TEST_MDM_PACKAGE)); 694 } 695 696 private void prepareMocksForAfterEncryption(String action, boolean startedByTrustedSource) 697 throws Exception { 698 when(mIntent.getAction()).thenReturn(ACTION_RESUME_PROVISIONING); 699 when(mIntent.getComponent()).thenReturn(ComponentName.createRelative(MP_PACKAGE_NAME, 700 ".PreProvisioningActivityAfterEncryption")); 701 when(mDevicePolicyManager.checkProvisioningPreCondition(action, TEST_MDM_PACKAGE)) 702 .thenReturn(CODE_OK); 703 when(mMessageParser.parse(mIntent)).thenReturn( 704 createParams( 705 startedByTrustedSource, false, TEST_WIFI_SSID, action, TEST_MDM_PACKAGE)); 706 } 707 708 private ProvisioningParams createParams(boolean startedByTrustedSource, boolean skipEncryption, 709 String wifiSsid, String action, String packageName) { 710 ProvisioningParams.Builder builder = ProvisioningParams.Builder.builder() 711 .setStartedByTrustedSource(startedByTrustedSource) 712 .setSkipEncryption(skipEncryption) 713 .setProvisioningAction(action) 714 .setDeviceAdminPackageName(packageName); 715 if (!TextUtils.isEmpty(wifiSsid)) { 716 builder.setWifiInfo(WifiInfo.Builder.builder().setSsid(wifiSsid).build()); 717 } 718 return mParams = builder.build(); 719 } 720 721 private void verifyInitiateProfileOwnerUi() { 722 verify(mUi).initiateUi(eq(R.layout.intro_profile_owner), 723 eq(R.string.setup_profile), any(), any(), eq(true), 724 eq(false), eq(emptyList()), any()); 725 } 726 727 private void verifyInitiateDeviceOwnerUi() { 728 verify(mUi).initiateUi(eq(R.layout.intro_device_owner), 729 eq(R.string.setup_device), eq(TEST_MDM_PACKAGE_LABEL), any(), eq(false), 730 eq(false), eq(emptyList()), any()); 731 } 732}