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