• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }