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