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_PROFILE;
20 
21 import static org.mockito.Mockito.any;
22 import static org.mockito.Mockito.never;
23 import static org.mockito.Mockito.verify;
24 import static org.mockito.Mockito.when;
25 
26 import android.content.ComponentName;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.pm.PackageManager;
30 import android.content.res.Resources;
31 import android.os.Handler;
32 import android.os.Looper;
33 import android.test.AndroidTestCase;
34 
35 import androidx.test.filters.SmallTest;
36 
37 import com.android.managedprovisioning.common.NotificationHelper;
38 import com.android.managedprovisioning.common.SettingsFacade;
39 import com.android.managedprovisioning.common.Utils;
40 import com.android.managedprovisioning.model.ProvisioningParams;
41 
42 import org.mockito.ArgumentCaptor;
43 import org.mockito.Mock;
44 import org.mockito.MockitoAnnotations;
45 
46 import java.util.concurrent.Semaphore;
47 import java.util.concurrent.TimeUnit;
48 
49 @SmallTest
50 public class EncryptionControllerTest extends AndroidTestCase {
51     private static final int TEST_USER_ID = 10;
52     private static final String MP_PACKAGE_NAME = "com.android.managedprovisioning";
53     private static final ComponentName TEST_HOME_RECEIVER = new ComponentName(MP_PACKAGE_NAME,
54             ".HomeReceiverActivity");
55     private static final String TEST_MDM_PACKAGE = "com.admin.test";
56     private static final int RESUME_PROVISIONING_TIMEOUT_MS = 1000;
57 
58     @Mock private Context mContext;
59     @Mock private Utils mUtils;
60     @Mock private SettingsFacade mSettingsFacade;
61     @Mock private Resources mResources;
62     @Mock private PackageManager mPackageManager;
63     @Mock private NotificationHelper mNotificationHelper;
64 
65     private EncryptionController mController;
66 
67     @Override
setUp()68     public void setUp() {
69         // this is necessary for mockito to work
70         System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
71 
72         MockitoAnnotations.initMocks(this);
73 
74         when(mUtils.isPhysicalDeviceEncrypted()).thenReturn(true);
75         when(mContext.getApplicationContext()).thenReturn(mContext);
76         when(mContext.getPackageManager()).thenReturn(mPackageManager);
77         when(mContext.getFilesDir()).thenReturn(getContext().getFilesDir());
78 
79         mController = createEncryptionController();
80         mController.getProvisioningParamsFile(mContext).delete();
81     }
82 
testDeviceOwner()83     public void testDeviceOwner() throws Exception {
84         // GIVEN we've set a provisioning reminder for device owner provisioning.
85         when(mSettingsFacade.isUserSetupCompleted(mContext)).thenReturn(false);
86         ProvisioningParams params = createProvisioningParams(ACTION_PROVISION_MANAGED_DEVICE);
87         setReminder(params);
88         verify(mUtils).enableComponent(TEST_HOME_RECEIVER, TEST_USER_ID);
89         verify(mPackageManager).flushPackageRestrictionsAsUser(TEST_USER_ID);
90         // WHEN resuming the provisioning
91         runResumeProvisioningOnUiThread();
92         // THEN the pre provisioning activity is started
93         verifyStartPreProvisioningActivity(params);
94     }
95 
testProfileOwnerAfterSuw()96     public void testProfileOwnerAfterSuw() throws Exception {
97         // GIVEN we set a provisioning reminder for managed profile provisioning after SUW
98         when(mSettingsFacade.isUserSetupCompleted(mContext)).thenReturn(true);
99         ProvisioningParams params = createProvisioningParams(ACTION_PROVISION_MANAGED_PROFILE);
100         setReminder(params);
101         // WHEN resuming the provisioning
102         runResumeProvisioningOnUiThread();
103         // THEN we show a notification
104         verifyShowResumeNotification(params);
105     }
106 
testProfileOwnerDuringSuw()107     public void testProfileOwnerDuringSuw() throws Exception {
108         // GIVEN we set a provisioning reminder for managed profile provisioning during SUW
109         when(mSettingsFacade.isUserSetupCompleted(mContext)).thenReturn(false);
110         ProvisioningParams params = createProvisioningParams(ACTION_PROVISION_MANAGED_PROFILE);
111         setReminder(params);
112         verify(mUtils).enableComponent(TEST_HOME_RECEIVER, TEST_USER_ID);
113         verify(mPackageManager).flushPackageRestrictionsAsUser(TEST_USER_ID);
114         // WHEN resuming the provisioning
115         runResumeProvisioningOnUiThread();
116         // THEN we start the pre provisioning activity
117         verifyStartPreProvisioningActivity(params);
118     }
119 
testDeviceNotEncrypted()120     public void testDeviceNotEncrypted() throws Exception {
121         // GIVEN an intent was stored to resume device owner provisioning, but the device
122         // is not encrypted
123         ProvisioningParams params = createProvisioningParams(ACTION_PROVISION_MANAGED_DEVICE);
124         setReminder(params);
125         when(mUtils.isPhysicalDeviceEncrypted()).thenReturn(false);
126         // WHEN resuming provisioning
127         runResumeProvisioningOnUiThread();
128         // THEN nothing should happen
129         verifyNothingStarted();
130     }
131 
testResumeProvisioningNoIntent()132     public void testResumeProvisioningNoIntent() throws Exception {
133         // GIVEN no reminder is set
134         // WHEN resuming the provisioning
135         runResumeProvisioningOnUiThread();
136         // THEN nothing should happen
137         verifyNothingStarted();
138     }
139 
testCancelProvisioningReminder()140     public void testCancelProvisioningReminder() throws Exception {
141         // WHEN we've set a provisioning reminder
142         when(mSettingsFacade.isUserSetupCompleted(mContext)).thenReturn(true);
143         ProvisioningParams params = createProvisioningParams(ACTION_PROVISION_MANAGED_PROFILE);
144         setReminder(params);
145         // WHEN canceling the reminder and then resuming the provisioning
146         mController.cancelEncryptionReminder();
147         verify(mUtils).disableComponent(TEST_HOME_RECEIVER, TEST_USER_ID);
148         runResumeProvisioningOnUiThread();
149         // THEN nothing should start
150         verifyNothingStarted();
151     }
152 
createProvisioningParams(String action)153     private ProvisioningParams createProvisioningParams(String action) {
154         return new ProvisioningParams.Builder()
155                 .setProvisioningAction(action)
156                 .setDeviceAdminPackageName(TEST_MDM_PACKAGE)
157                 .build();
158     }
159 
runResumeProvisioningOnUiThread()160     private void runResumeProvisioningOnUiThread() throws InterruptedException {
161         final Semaphore semaphore = new Semaphore(0);
162         new Handler(Looper.getMainLooper()).post(new Runnable() {
163             @Override
164             public void run() {
165                 // In a real case, the device may have rebooted between the moment when the
166                 // reminder was set and the moment we resume the provisioning. Recreate the
167                 // encryption controller to simulate this.
168                 createEncryptionController().resumeProvisioning();
169                 semaphore.release();
170             }
171         });
172         assertTrue("Timeout trying to resume provisioning",
173                 semaphore.tryAcquire(RESUME_PROVISIONING_TIMEOUT_MS, TimeUnit.MILLISECONDS));
174     }
175 
createEncryptionController()176     private EncryptionController createEncryptionController() {
177         return new EncryptionController(mContext, mUtils, mSettingsFacade, TEST_HOME_RECEIVER,
178             mNotificationHelper, TEST_USER_ID);
179     }
180 
setReminder(ProvisioningParams params)181     private void setReminder(ProvisioningParams params) {
182         mController.setEncryptionReminder(params);
183     }
184 
verifyStartPreProvisioningActivity(ProvisioningParams params)185     private void verifyStartPreProvisioningActivity(ProvisioningParams params) throws Exception {
186         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
187         verify(mContext).startActivity(intentCaptor.capture());
188         assertEquals(params, intentCaptor.getValue().getParcelableExtra(
189                 ProvisioningParams.EXTRA_PROVISIONING_PARAMS));
190         verify(mNotificationHelper, never()).showResumeNotification(any(Intent.class));
191     }
192 
verifyShowResumeNotification(ProvisioningParams params)193     private void verifyShowResumeNotification(ProvisioningParams params) throws Exception {
194         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
195         verify(mNotificationHelper).showResumeNotification(intentCaptor.capture());
196         assertEquals(params, intentCaptor.getValue().getParcelableExtra(
197                 ProvisioningParams.EXTRA_PROVISIONING_PARAMS));
198         verify(mContext, never()).startActivity(any(Intent.class));
199     }
200 
verifyNothingStarted()201     private void verifyNothingStarted() throws Exception {
202         verify(mContext, never()).startActivity(any(Intent.class));
203         verify(mNotificationHelper, never()).showResumeNotification(any(Intent.class));
204     }
205 }
206