1 /*
2  * Copyright (C) 2024 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 
17 package com.android.devicelockcontroller.policy;
18 
19 import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNDEFINED;
20 
21 import static org.mockito.Mockito.verify;
22 import static org.mockito.Mockito.verifyNoInteractions;
23 import static org.mockito.Mockito.verifyNoMoreInteractions;
24 import static org.mockito.Mockito.when;
25 
26 import android.app.admin.DevicePolicyManager;
27 import android.os.UserManager;
28 
29 import androidx.test.core.app.ApplicationProvider;
30 
31 import com.android.devicelockcontroller.TestDeviceLockControllerApplication;
32 import com.android.devicelockcontroller.storage.GlobalParametersClient;
33 
34 import com.google.common.util.concurrent.Futures;
35 
36 import org.junit.Before;
37 import org.junit.Rule;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
40 import org.mockito.Mock;
41 import org.mockito.junit.MockitoJUnit;
42 import org.mockito.junit.MockitoRule;
43 import org.robolectric.RobolectricTestRunner;
44 
45 import java.util.concurrent.ExecutionException;
46 import java.util.concurrent.ExecutorService;
47 import java.util.concurrent.Executors;
48 
49 @RunWith(RobolectricTestRunner.class)
50 public final class DevicePolicyControllerImplEnforcementTest {
51     @Rule
52     public MockitoRule mMockitoRule = MockitoJUnit.rule();
53 
54     @Mock
55     private ProvisionStateController mMockProvisionStateController;
56     @Mock
57     private DevicePolicyManager mMockDpm;
58     @Mock
59     private UserManager mMockUserManager;
60     @Mock
61     private PolicyHandler mMockUserRestrictionsPolicyHandler;
62     @Mock
63     private PolicyHandler mMockAppOpsPolicyHandler;
64     @Mock
65     private PolicyHandler mMockLockTaskModePolicyHandler;
66     @Mock
67     private PolicyHandler mMockPackagePolicyHandler;
68     @Mock
69     private PolicyHandler mMockRolePolicyHandler;
70     @Mock
71     private PolicyHandler mMockKioskKeepAlivePolicyHandler;
72     @Mock
73     private PolicyHandler mMockControllerKeepAlivePolicyHandler;
74     @Mock
75     private PolicyHandler mMockNotificationsPolicyHandler;
76 
77     private DevicePolicyController mDevicePolicyController;
78     private TestDeviceLockControllerApplication mTestApp;
79 
setupPolicyHandler(PolicyHandler policyHandler)80     private void setupPolicyHandler(PolicyHandler policyHandler) {
81         when(policyHandler.onUnprovisioned()).thenReturn(Futures.immediateFuture(true));
82         when(policyHandler.onProvisioned()).thenReturn(Futures.immediateFuture(true));
83         when(policyHandler.onProvisionInProgress()).thenReturn(Futures.immediateFuture(true));
84         when(policyHandler.onProvisionPaused()).thenReturn(Futures.immediateFuture(true));
85         when(policyHandler.onProvisionFailed()).thenReturn(Futures.immediateFuture(true));
86         when(policyHandler.onLocked()).thenReturn(Futures.immediateFuture(true));
87         when(policyHandler.onUnlocked()).thenReturn(Futures.immediateFuture(true));
88         when(policyHandler.onCleared()).thenReturn(Futures.immediateFuture(true));
89     }
90 
91     @Before
setUp()92     public void setUp() {
93         mTestApp = ApplicationProvider.getApplicationContext();
94         ExecutorService bgExecutor = Executors.newSingleThreadExecutor();
95 
96         setupPolicyHandler(mMockUserRestrictionsPolicyHandler);
97         setupPolicyHandler(mMockAppOpsPolicyHandler);
98         setupPolicyHandler(mMockLockTaskModePolicyHandler);
99         setupPolicyHandler(mMockPackagePolicyHandler);
100         setupPolicyHandler(mMockRolePolicyHandler);
101         setupPolicyHandler(mMockKioskKeepAlivePolicyHandler);
102         setupPolicyHandler(mMockControllerKeepAlivePolicyHandler);
103         setupPolicyHandler(mMockNotificationsPolicyHandler);
104 
105         mDevicePolicyController =
106                 new DevicePolicyControllerImpl(mTestApp,
107                         mMockDpm,
108                         mMockUserManager,
109                         mMockUserRestrictionsPolicyHandler,
110                         mMockAppOpsPolicyHandler,
111                         mMockLockTaskModePolicyHandler,
112                         mMockPackagePolicyHandler,
113                         mMockRolePolicyHandler,
114                         mMockKioskKeepAlivePolicyHandler,
115                         mMockControllerKeepAlivePolicyHandler,
116                         mMockNotificationsPolicyHandler,
117                         mMockProvisionStateController,
118                         bgExecutor);
119     }
120 
121     @Test
enforceCurrentPolicies_withProvisionStateUnprovisioned_shouldCallOnUnprovisioned()122     public void enforceCurrentPolicies_withProvisionStateUnprovisioned_shouldCallOnUnprovisioned()
123             throws ExecutionException, InterruptedException {
124         when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
125                 ProvisionStateController.ProvisionState.UNPROVISIONED));
126         GlobalParametersClient.getInstance().setDeviceState(UNDEFINED).get();
127 
128         mDevicePolicyController.enforceCurrentPolicies().get();
129 
130         verify(mMockUserRestrictionsPolicyHandler).onUnprovisioned();
131         verifyNoMoreInteractions(mMockUserRestrictionsPolicyHandler);
132 
133         verify(mMockAppOpsPolicyHandler).onUnprovisioned();
134         verifyNoMoreInteractions(mMockAppOpsPolicyHandler);
135 
136         verify(mMockLockTaskModePolicyHandler).onUnprovisioned();
137         verifyNoMoreInteractions(mMockLockTaskModePolicyHandler);
138 
139         verify(mMockPackagePolicyHandler).onUnprovisioned();
140         verifyNoMoreInteractions(mMockPackagePolicyHandler);
141 
142         verify(mMockRolePolicyHandler).onUnprovisioned();
143         verifyNoMoreInteractions(mMockRolePolicyHandler);
144 
145         verify(mMockKioskKeepAlivePolicyHandler).onUnprovisioned();
146         verifyNoMoreInteractions(mMockKioskKeepAlivePolicyHandler);
147 
148         verify(mMockControllerKeepAlivePolicyHandler).onUnprovisioned();
149         verifyNoMoreInteractions(mMockControllerKeepAlivePolicyHandler);
150 
151         verify(mMockNotificationsPolicyHandler).onUnprovisioned();
152         verifyNoMoreInteractions(mMockNotificationsPolicyHandler);
153     }
154 
155     @Test
enforceCurrentPolicies_withProvisionStateProgress_shouldCallOnProvisionInProgress()156     public void enforceCurrentPolicies_withProvisionStateProgress_shouldCallOnProvisionInProgress()
157             throws ExecutionException, InterruptedException {
158         when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
159                 ProvisionStateController.ProvisionState.PROVISION_IN_PROGRESS));
160         GlobalParametersClient.getInstance().setDeviceState(UNDEFINED).get();
161 
162         mDevicePolicyController.enforceCurrentPolicies().get();
163 
164         verify(mMockUserRestrictionsPolicyHandler).onProvisionInProgress();
165         verifyNoMoreInteractions(mMockUserRestrictionsPolicyHandler);
166 
167         verify(mMockAppOpsPolicyHandler).onProvisionInProgress();
168         verifyNoMoreInteractions(mMockAppOpsPolicyHandler);
169 
170         verify(mMockLockTaskModePolicyHandler).onProvisionInProgress();
171         verifyNoMoreInteractions(mMockLockTaskModePolicyHandler);
172 
173         verify(mMockPackagePolicyHandler).onProvisionInProgress();
174         verifyNoMoreInteractions(mMockPackagePolicyHandler);
175 
176         verify(mMockRolePolicyHandler).onProvisionInProgress();
177         verifyNoMoreInteractions(mMockRolePolicyHandler);
178 
179         verify(mMockKioskKeepAlivePolicyHandler).onProvisionInProgress();
180         verifyNoMoreInteractions(mMockKioskKeepAlivePolicyHandler);
181 
182         verify(mMockControllerKeepAlivePolicyHandler).onProvisionInProgress();
183         verifyNoMoreInteractions(mMockControllerKeepAlivePolicyHandler);
184 
185         verify(mMockNotificationsPolicyHandler).onProvisionInProgress();
186         verifyNoMoreInteractions(mMockNotificationsPolicyHandler);
187     }
188 
189     @Test
enforceCurrentPolicies_withProvisionStateKioskProvisioned_shouldCallOnProvisioned()190     public void enforceCurrentPolicies_withProvisionStateKioskProvisioned_shouldCallOnProvisioned()
191             throws ExecutionException, InterruptedException {
192         when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
193                 ProvisionStateController.ProvisionState.KIOSK_PROVISIONED));
194         GlobalParametersClient.getInstance().setDeviceState(UNDEFINED).get();
195 
196         mDevicePolicyController.enforceCurrentPolicies().get();
197 
198         verify(mMockUserRestrictionsPolicyHandler).onProvisioned();
199         verifyNoMoreInteractions(mMockUserRestrictionsPolicyHandler);
200 
201         verify(mMockAppOpsPolicyHandler).onProvisioned();
202         verifyNoMoreInteractions(mMockAppOpsPolicyHandler);
203 
204         verify(mMockLockTaskModePolicyHandler).onProvisioned();
205         verifyNoMoreInteractions(mMockLockTaskModePolicyHandler);
206 
207         verify(mMockPackagePolicyHandler).onProvisioned();
208         verifyNoMoreInteractions(mMockPackagePolicyHandler);
209 
210         verify(mMockRolePolicyHandler).onProvisioned();
211         verifyNoMoreInteractions(mMockRolePolicyHandler);
212 
213         verify(mMockKioskKeepAlivePolicyHandler).onProvisioned();
214         verifyNoMoreInteractions(mMockKioskKeepAlivePolicyHandler);
215 
216         verify(mMockControllerKeepAlivePolicyHandler).onProvisioned();
217         verifyNoMoreInteractions(mMockControllerKeepAlivePolicyHandler);
218 
219         verify(mMockNotificationsPolicyHandler).onProvisioned();
220         verifyNoMoreInteractions(mMockNotificationsPolicyHandler);
221     }
222 
223     @Test
enforceCurrentPolicies_withProvisionStatePaused_shouldCallOnProvisionPaused()224     public void enforceCurrentPolicies_withProvisionStatePaused_shouldCallOnProvisionPaused()
225             throws ExecutionException, InterruptedException {
226         when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
227                 ProvisionStateController.ProvisionState.PROVISION_PAUSED));
228         GlobalParametersClient.getInstance().setDeviceState(UNDEFINED).get();
229 
230         mDevicePolicyController.enforceCurrentPolicies().get();
231 
232         verify(mMockUserRestrictionsPolicyHandler).onProvisionPaused();
233         verifyNoMoreInteractions(mMockUserRestrictionsPolicyHandler);
234 
235         verify(mMockAppOpsPolicyHandler).onProvisionPaused();
236         verifyNoMoreInteractions(mMockAppOpsPolicyHandler);
237 
238         verify(mMockLockTaskModePolicyHandler).onProvisionPaused();
239         verifyNoMoreInteractions(mMockLockTaskModePolicyHandler);
240 
241         verify(mMockPackagePolicyHandler).onProvisionPaused();
242         verifyNoMoreInteractions(mMockPackagePolicyHandler);
243 
244         verify(mMockRolePolicyHandler).onProvisionPaused();
245         verifyNoMoreInteractions(mMockRolePolicyHandler);
246 
247         verify(mMockKioskKeepAlivePolicyHandler).onProvisionPaused();
248         verifyNoMoreInteractions(mMockKioskKeepAlivePolicyHandler);
249 
250         verify(mMockControllerKeepAlivePolicyHandler).onProvisionPaused();
251         verifyNoMoreInteractions(mMockControllerKeepAlivePolicyHandler);
252 
253         verify(mMockNotificationsPolicyHandler).onProvisionPaused();
254         verifyNoMoreInteractions(mMockNotificationsPolicyHandler);
255     }
256 
257     @Test
enforceCurrentPolicies_withProvisionStateFailed_shouldCallOnProvisionFailed()258     public void enforceCurrentPolicies_withProvisionStateFailed_shouldCallOnProvisionFailed()
259             throws ExecutionException, InterruptedException {
260         when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
261                 ProvisionStateController.ProvisionState.PROVISION_FAILED));
262         GlobalParametersClient.getInstance().setDeviceState(UNDEFINED).get();
263 
264         mDevicePolicyController.enforceCurrentPolicies().get();
265 
266         verify(mMockUserRestrictionsPolicyHandler).onProvisionFailed();
267         verifyNoMoreInteractions(mMockUserRestrictionsPolicyHandler);
268 
269         verify(mMockAppOpsPolicyHandler).onProvisionFailed();
270         verifyNoMoreInteractions(mMockAppOpsPolicyHandler);
271 
272         verify(mMockLockTaskModePolicyHandler).onProvisionFailed();
273         verifyNoMoreInteractions(mMockLockTaskModePolicyHandler);
274 
275         verify(mMockPackagePolicyHandler).onProvisionFailed();
276         verifyNoMoreInteractions(mMockPackagePolicyHandler);
277 
278         verify(mMockRolePolicyHandler).onProvisionFailed();
279         verifyNoMoreInteractions(mMockRolePolicyHandler);
280 
281         verify(mMockKioskKeepAlivePolicyHandler).onProvisionFailed();
282         verifyNoMoreInteractions(mMockKioskKeepAlivePolicyHandler);
283 
284         verify(mMockControllerKeepAlivePolicyHandler).onProvisionFailed();
285         verifyNoMoreInteractions(mMockControllerKeepAlivePolicyHandler);
286 
287         verify(mMockNotificationsPolicyHandler).onProvisionFailed();
288         verifyNoMoreInteractions(mMockNotificationsPolicyHandler);
289     }
290 
291     @Test
enforceCurrentPolicies_provisionSucceeded_deviceUnlocked_shouldCallOnUnlocked()292     public void enforceCurrentPolicies_provisionSucceeded_deviceUnlocked_shouldCallOnUnlocked()
293             throws ExecutionException, InterruptedException {
294         when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
295                 ProvisionStateController.ProvisionState.PROVISION_SUCCEEDED));
296         GlobalParametersClient.getInstance().setDeviceState(
297                 DeviceStateController.DeviceState.UNLOCKED).get();
298 
299         mDevicePolicyController.enforceCurrentPolicies().get();
300 
301         verify(mMockUserRestrictionsPolicyHandler).onUnlocked();
302         verifyNoMoreInteractions(mMockUserRestrictionsPolicyHandler);
303 
304         verify(mMockAppOpsPolicyHandler).onUnlocked();
305         verifyNoMoreInteractions(mMockAppOpsPolicyHandler);
306 
307         verify(mMockLockTaskModePolicyHandler).onUnlocked();
308         verifyNoMoreInteractions(mMockLockTaskModePolicyHandler);
309 
310         verify(mMockPackagePolicyHandler).onUnlocked();
311         verifyNoMoreInteractions(mMockPackagePolicyHandler);
312 
313         verify(mMockRolePolicyHandler).onUnlocked();
314         verifyNoMoreInteractions(mMockRolePolicyHandler);
315 
316         verify(mMockKioskKeepAlivePolicyHandler).onUnlocked();
317         verifyNoMoreInteractions(mMockKioskKeepAlivePolicyHandler);
318 
319         verify(mMockControllerKeepAlivePolicyHandler).onUnlocked();
320         verifyNoMoreInteractions(mMockControllerKeepAlivePolicyHandler);
321 
322         verify(mMockNotificationsPolicyHandler).onUnlocked();
323         verifyNoMoreInteractions(mMockNotificationsPolicyHandler);
324     }
325 
326     @Test
enforceCurrentPolicies_provisionSucceeded_deviceLocked_shouldCallOnLocked()327     public void enforceCurrentPolicies_provisionSucceeded_deviceLocked_shouldCallOnLocked()
328             throws ExecutionException, InterruptedException {
329         when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
330                 ProvisionStateController.ProvisionState.PROVISION_SUCCEEDED));
331         GlobalParametersClient.getInstance().setDeviceState(
332                 DeviceStateController.DeviceState.LOCKED).get();
333 
334         mDevicePolicyController.enforceCurrentPolicies().get();
335 
336         verify(mMockUserRestrictionsPolicyHandler).onLocked();
337         verifyNoMoreInteractions(mMockUserRestrictionsPolicyHandler);
338 
339         verify(mMockAppOpsPolicyHandler).onLocked();
340         verifyNoMoreInteractions(mMockAppOpsPolicyHandler);
341 
342         verify(mMockLockTaskModePolicyHandler).onLocked();
343         verifyNoMoreInteractions(mMockLockTaskModePolicyHandler);
344 
345         verify(mMockPackagePolicyHandler).onLocked();
346         verifyNoMoreInteractions(mMockPackagePolicyHandler);
347 
348         verify(mMockRolePolicyHandler).onLocked();
349         verifyNoMoreInteractions(mMockRolePolicyHandler);
350 
351         verify(mMockKioskKeepAlivePolicyHandler).onLocked();
352         verifyNoMoreInteractions(mMockKioskKeepAlivePolicyHandler);
353 
354         verify(mMockControllerKeepAlivePolicyHandler).onLocked();
355         verifyNoMoreInteractions(mMockControllerKeepAlivePolicyHandler);
356 
357         verify(mMockNotificationsPolicyHandler).onLocked();
358         verifyNoMoreInteractions(mMockNotificationsPolicyHandler);
359     }
360 
361     @Test
enforceCurrentPolicies_provisionSucceeded_deviceStateUndefined_shouldDoNothing()362     public void enforceCurrentPolicies_provisionSucceeded_deviceStateUndefined_shouldDoNothing()
363             throws ExecutionException, InterruptedException {
364         when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
365                 ProvisionStateController.ProvisionState.PROVISION_SUCCEEDED));
366         GlobalParametersClient.getInstance().setDeviceState(UNDEFINED).get();
367 
368         mDevicePolicyController.enforceCurrentPolicies().get();
369 
370         verifyNoInteractions(mMockUserRestrictionsPolicyHandler);
371 
372         verifyNoInteractions(mMockAppOpsPolicyHandler);
373 
374         verifyNoInteractions(mMockLockTaskModePolicyHandler);
375 
376         verifyNoInteractions(mMockPackagePolicyHandler);
377 
378         verifyNoInteractions(mMockRolePolicyHandler);
379 
380         verifyNoInteractions(mMockKioskKeepAlivePolicyHandler);
381 
382         verifyNoInteractions(mMockControllerKeepAlivePolicyHandler);
383 
384         verifyNoInteractions(mMockNotificationsPolicyHandler);
385     }
386 
387     @Test
enforceCurrentPolicies_withDeviceStateCleared_shouldCallOnCleared()388     public void enforceCurrentPolicies_withDeviceStateCleared_shouldCallOnCleared()
389             throws ExecutionException, InterruptedException {
390         // Provision state can be anything.
391         when(mMockProvisionStateController.getState()).thenReturn(Futures.immediateFuture(
392                 ProvisionStateController.ProvisionState.UNPROVISIONED));
393         GlobalParametersClient.getInstance().setDeviceState(
394                 DeviceStateController.DeviceState.CLEARED).get();
395 
396         mDevicePolicyController.enforceCurrentPolicies().get();
397 
398         verify(mMockUserRestrictionsPolicyHandler).onCleared();
399         verifyNoMoreInteractions(mMockUserRestrictionsPolicyHandler);
400 
401         verify(mMockAppOpsPolicyHandler).onCleared();
402         verifyNoMoreInteractions(mMockAppOpsPolicyHandler);
403 
404         verify(mMockLockTaskModePolicyHandler).onCleared();
405         verifyNoMoreInteractions(mMockLockTaskModePolicyHandler);
406 
407         verify(mMockPackagePolicyHandler).onCleared();
408         verifyNoMoreInteractions(mMockPackagePolicyHandler);
409 
410         verify(mMockRolePolicyHandler).onCleared();
411         verifyNoMoreInteractions(mMockRolePolicyHandler);
412 
413         verify(mMockKioskKeepAlivePolicyHandler).onCleared();
414         verifyNoMoreInteractions(mMockKioskKeepAlivePolicyHandler);
415 
416         verify(mMockControllerKeepAlivePolicyHandler).onCleared();
417         verifyNoMoreInteractions(mMockControllerKeepAlivePolicyHandler);
418 
419         verify(mMockNotificationsPolicyHandler).onCleared();
420         verifyNoMoreInteractions(mMockNotificationsPolicyHandler);
421     }
422 }
423