blob: 1adfb67cd6edb3aa7f8d349f31331913560f49d4 [file] [log] [blame]
Benjamin Franza83859f2017-07-03 16:34:14 +01001/*
2 * Copyright 2017, 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
17package com.android.server.am;
18
19import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
20import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
21import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
Charles Hee078db72017-10-19 18:03:20 +010022import static android.app.StatusBarManager.DISABLE2_MASK;
23import static android.app.StatusBarManager.DISABLE2_NONE;
24import static android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE;
25import static android.app.StatusBarManager.DISABLE_HOME;
26import static android.app.StatusBarManager.DISABLE_NOTIFICATION_ALERTS;
27import static android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS;
28import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
29import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
30import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
31import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
Benjamin Franza83859f2017-07-03 16:34:14 +010032import static android.os.Process.SYSTEM_UID;
Charles He520b2832017-09-02 15:27:16 +010033
Benjamin Franza83859f2017-07-03 16:34:14 +010034import static com.android.server.am.LockTaskController.STATUS_BAR_MASK_LOCKED;
35import static com.android.server.am.LockTaskController.STATUS_BAR_MASK_PINNED;
Charles He520b2832017-09-02 15:27:16 +010036
37import static org.junit.Assert.*;
38import static org.mockito.ArgumentMatchers.*;
39import static org.mockito.Mockito.*;
Benjamin Franza83859f2017-07-03 16:34:14 +010040
41import android.app.StatusBarManager;
Charles Hee078db72017-10-19 18:03:20 +010042import android.app.admin.DevicePolicyManager;
Benjamin Franza83859f2017-07-03 16:34:14 +010043import android.app.admin.IDevicePolicyManager;
44import android.content.ComponentName;
45import android.content.Context;
46import android.content.Intent;
47import android.os.Handler;
48import android.os.IBinder;
49import android.os.Looper;
50import android.os.Message;
51import android.os.UserHandle;
52import android.platform.test.annotations.Presubmit;
53import android.provider.Settings;
54import android.support.test.InstrumentationRegistry;
55import android.support.test.filters.SmallTest;
Charles Hee078db72017-10-19 18:03:20 +010056import android.util.Pair;
Benjamin Franza83859f2017-07-03 16:34:14 +010057
58import com.android.internal.statusbar.IStatusBarService;
59import com.android.internal.widget.LockPatternUtils;
60import com.android.server.LocalServices;
61import com.android.server.statusbar.StatusBarManagerInternal;
62import com.android.server.wm.WindowManagerService;
63
64import org.junit.After;
65import org.junit.Before;
66import org.junit.Test;
67import org.mockito.Mock;
68import org.mockito.MockitoAnnotations;
69import org.mockito.verification.VerificationMode;
70
71/**
72 * Unit tests for {@link LockTaskController}.
73 *
74 * Build/Install/Run:
75 * bit FrameworksServicesTests:com.android.server.am.LockTaskControllerTest
76 */
77@Presubmit
78@SmallTest
79public class LockTaskControllerTest {
80 private static final String TEST_PACKAGE_NAME = "com.test.package";
Charles He520b2832017-09-02 15:27:16 +010081 private static final String TEST_PACKAGE_NAME_2 = "com.test.package2";
82 private static final String TEST_CLASS_NAME = ".TestClass";
Benjamin Franza83859f2017-07-03 16:34:14 +010083 private static final int TEST_USER_ID = 123;
84 private static final int TEST_UID = 10467;
85
86 @Mock private ActivityStackSupervisor mSupervisor;
87 @Mock private IDevicePolicyManager mDevicePolicyManager;
88 @Mock private IStatusBarService mStatusBarService;
89 @Mock private WindowManagerService mWindowManager;
90 @Mock private LockPatternUtils mLockPatternUtils;
91 @Mock private LockTaskNotify mLockTaskNotify;
92 @Mock private StatusBarManagerInternal mStatusBarManagerInternal;
93
94 private LockTaskController mLockTaskController;
95 private Context mContext;
96 private String mLockToAppSetting;
97
98 @Before
99 public void setUp() throws Exception {
100 // This property is used to allow mocking of package private classes with mockito
101 System.setProperty("dexmaker.share_classloader", "true");
102
103 MockitoAnnotations.initMocks(this);
104
105 mContext = InstrumentationRegistry.getTargetContext();
106 mLockToAppSetting = Settings.Secure.getString(mContext.getContentResolver(),
107 Settings.Secure.LOCK_TO_APP_EXIT_LOCKED);
108
109 if (Looper.myLooper() == null) {
110 Looper.prepare();
111 }
112
113 mLockTaskController = new LockTaskController(mContext, mSupervisor,
114 new ImmediatelyExecuteHandler());
115
116 mLockTaskController.setWindowManager(mWindowManager);
117 mLockTaskController.mStatusBarService = mStatusBarService;
118 mLockTaskController.mDevicePolicyManager = mDevicePolicyManager;
119 mLockTaskController.mLockPatternUtils = mLockPatternUtils;
120 mLockTaskController.mLockTaskNotify = mLockTaskNotify;
121
122 LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
123 LocalServices.addService(StatusBarManagerInternal.class, mStatusBarManagerInternal);
124 }
125
126 @After
127 public void tearDown() throws Exception {
128 Settings.Secure.putString(mContext.getContentResolver(),
129 Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, mLockToAppSetting);
130 }
131
132 @Test
133 public void testPreconditions() {
134 // GIVEN nothing has happened
135
136 // THEN current lock task mode should be NONE
137 assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState());
138 }
139
140 @Test
141 public void testStartLockTaskMode_once() throws Exception {
142 // GIVEN a task record with whitelisted auth
143 TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
144
145 // WHEN calling setLockTaskMode for LOCKED mode without resuming
146 mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
147
148 // THEN the lock task mode state should be LOCKED
149 assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState());
150 // THEN the task should be locked
Charles Heff9b4dff2017-09-22 10:18:37 +0100151 assertTrue(mLockTaskController.isTaskLocked(tr));
Benjamin Franza83859f2017-07-03 16:34:14 +0100152
153 // THEN lock task mode should be started
Charles Hee078db72017-10-19 18:03:20 +0100154 verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED, DISABLE2_MASK);
Benjamin Franza83859f2017-07-03 16:34:14 +0100155 }
156
157 @Test
158 public void testStartLockTaskMode_twice() throws Exception {
159 // GIVEN two task records with whitelisted auth
160 TaskRecord tr1 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
161 TaskRecord tr2 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
162
163 // WHEN calling setLockTaskMode for LOCKED mode on both tasks
164 mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
165 mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);
166
167 // THEN the lock task mode state should be LOCKED
168 assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState());
169 // THEN neither of the tasks should be able to move to back of stack
Charles Heff9b4dff2017-09-22 10:18:37 +0100170 assertTrue(mLockTaskController.isTaskLocked(tr1));
171 assertTrue(mLockTaskController.isTaskLocked(tr2));
Benjamin Franza83859f2017-07-03 16:34:14 +0100172
173 // THEN lock task mode should be started
Charles Hee078db72017-10-19 18:03:20 +0100174 verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED, DISABLE2_MASK);
Benjamin Franza83859f2017-07-03 16:34:14 +0100175 }
176
177 @Test
178 public void testStartLockTaskMode_pinningRequest() throws Exception {
179 // GIVEN a task record that is not whitelisted, i.e. with pinned auth
180 TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_PINNABLE);
181
182 // WHEN calling startLockTaskMode
183 mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
184
185 // THEN a pinning request should be shown
186 verify(mStatusBarManagerInternal).showScreenPinningRequest(anyInt());
187 }
188
189 @Test
190 public void testStartLockTaskMode_pinnedBySystem() throws Exception {
191 // GIVEN a task record with pinned auth
192 TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_PINNABLE);
193
194 // WHEN the system calls startLockTaskMode
195 mLockTaskController.startLockTaskMode(tr, true, SYSTEM_UID);
196
197 // THEN the lock task mode state should be PINNED
198 assertEquals(LOCK_TASK_MODE_PINNED, mLockTaskController.getLockTaskModeState());
199 // THEN the task should be locked
Charles Heff9b4dff2017-09-22 10:18:37 +0100200 assertTrue(mLockTaskController.isTaskLocked(tr));
Benjamin Franza83859f2017-07-03 16:34:14 +0100201
202 // THEN lock task mode should be started
Charles Hee078db72017-10-19 18:03:20 +0100203 verifyLockTaskStarted(STATUS_BAR_MASK_PINNED, DISABLE2_NONE);
Charles Hebfe82d12017-10-20 11:59:44 +0100204 // THEN screen pinning toast should be shown
205 verify(mLockTaskNotify).showPinningStartToast();
Benjamin Franza83859f2017-07-03 16:34:14 +0100206 }
207
208 @Test
209 public void testLockTaskViolation() throws Exception {
210 // GIVEN one task records with whitelisted auth that is in lock task mode
211 TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
212 mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
213
214 // THEN it's not a lock task violation to try and launch this task without clearing
215 assertFalse(mLockTaskController.isLockTaskModeViolation(tr, false));
216
217 // THEN it's a lock task violation to launch another task that is not whitelisted
218 assertTrue(mLockTaskController.isLockTaskModeViolation(getTaskRecord(
219 TaskRecord.LOCK_TASK_AUTH_PINNABLE)));
220 // THEN it's a lock task violation to launch another task that is disallowed from lock task
221 assertTrue(mLockTaskController.isLockTaskModeViolation(getTaskRecord(
222 TaskRecord.LOCK_TASK_AUTH_DONT_LOCK)));
223
224 // THEN it's no a lock task violation to launch another task that is whitelisted
225 assertFalse(mLockTaskController.isLockTaskModeViolation(getTaskRecord(
226 TaskRecord.LOCK_TASK_AUTH_WHITELISTED)));
227 assertFalse(mLockTaskController.isLockTaskModeViolation(getTaskRecord(
228 TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE)));
229 // THEN it's not a lock task violation to launch another task that is priv launchable
230 assertFalse(mLockTaskController.isLockTaskModeViolation(getTaskRecord(
231 TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV)));
232 }
233
234 @Test
235 public void testStopLockTaskMode() throws Exception {
236 // GIVEN one task record with whitelisted auth that is in lock task mode
237 TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
238 mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
239
240 // WHEN the same caller calls stopLockTaskMode
Charles Heff9b4dff2017-09-22 10:18:37 +0100241 mLockTaskController.stopLockTaskMode(tr, false, TEST_UID);
Benjamin Franza83859f2017-07-03 16:34:14 +0100242
243 // THEN the lock task mode should be NONE
244 assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState());
245 // THEN the task should no longer be locked
Charles Heff9b4dff2017-09-22 10:18:37 +0100246 assertFalse(mLockTaskController.isTaskLocked(tr));
Benjamin Franza83859f2017-07-03 16:34:14 +0100247 // THEN lock task mode should have been finished
248 verifyLockTaskStopped(times(1));
249 }
250
251 @Test(expected = SecurityException.class)
Charles Heff9b4dff2017-09-22 10:18:37 +0100252 public void testStopLockTaskMode_differentCaller() throws Exception {
Benjamin Franza83859f2017-07-03 16:34:14 +0100253 // GIVEN one task record with whitelisted auth that is in lock task mode
254 TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
255 mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
256
257 // WHEN a different caller calls stopLockTaskMode
Charles Heff9b4dff2017-09-22 10:18:37 +0100258 mLockTaskController.stopLockTaskMode(tr, false, TEST_UID + 1);
Benjamin Franza83859f2017-07-03 16:34:14 +0100259
260 // THEN security exception should be thrown, because different caller tried to unlock
261 }
262
263 @Test
Charles Heff9b4dff2017-09-22 10:18:37 +0100264 public void testStopLockTaskMode_systemCaller() throws Exception {
Benjamin Franza83859f2017-07-03 16:34:14 +0100265 // GIVEN one task record with whitelisted auth that is in lock task mode
266 TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
267 mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
268
269 // WHEN system calls stopLockTaskMode
Charles Heff9b4dff2017-09-22 10:18:37 +0100270 mLockTaskController.stopLockTaskMode(tr, true, SYSTEM_UID);
Benjamin Franza83859f2017-07-03 16:34:14 +0100271
Benjamin Franza83859f2017-07-03 16:34:14 +0100272 // THEN lock task mode should still be active
273 assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState());
274 }
275
276 @Test
277 public void testStopLockTaskMode_twoTasks() throws Exception {
278 // GIVEN two task records with whitelisted auth that is in lock task mode
279 TaskRecord tr1 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
280 TaskRecord tr2 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
281 mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
282 mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);
283
284 // WHEN calling stopLockTaskMode
Charles Heff9b4dff2017-09-22 10:18:37 +0100285 mLockTaskController.stopLockTaskMode(tr2, false, TEST_UID);
Benjamin Franza83859f2017-07-03 16:34:14 +0100286
287 // THEN the lock task mode should still be active
288 assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState());
289 // THEN the first task should still be locked
Charles Heff9b4dff2017-09-22 10:18:37 +0100290 assertTrue(mLockTaskController.isTaskLocked(tr1));
Benjamin Franza83859f2017-07-03 16:34:14 +0100291 // THEN the top task should no longer be locked
Charles Heff9b4dff2017-09-22 10:18:37 +0100292 assertFalse(mLockTaskController.isTaskLocked(tr2));
Benjamin Franza83859f2017-07-03 16:34:14 +0100293 // THEN lock task mode should not have been finished
294 verifyLockTaskStopped(never());
295 }
296
297 @Test
Charles Heff9b4dff2017-09-22 10:18:37 +0100298 public void testStopLockTaskMode_rootTask() throws Exception {
299 // GIVEN two task records with whitelisted auth that is in lock task mode
300 TaskRecord tr1 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
301 TaskRecord tr2 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
302 mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
303 mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);
304
305 // WHEN calling stopLockTaskMode on the root task
306 mLockTaskController.stopLockTaskMode(tr1, false, TEST_UID);
307
308 // THEN the lock task mode should be inactive
309 assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState());
310 // THEN the first task should no longer be locked
311 assertFalse(mLockTaskController.isTaskLocked(tr1));
312 // THEN the top task should no longer be locked
313 assertFalse(mLockTaskController.isTaskLocked(tr2));
314 // THEN lock task mode should be finished
315 verifyLockTaskStopped(times(1));
316 }
317
318 @Test
Benjamin Franza83859f2017-07-03 16:34:14 +0100319 public void testStopLockTaskMode_pinned() throws Exception {
320 // GIVEN one task records that is in pinned mode
321 TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_PINNABLE);
322 mLockTaskController.startLockTaskMode(tr, true, SYSTEM_UID);
323 // GIVEN that the keyguard is required to show after unlocking
324 Settings.Secure.putInt(mContext.getContentResolver(),
325 Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, 1);
326
Charles Hee078db72017-10-19 18:03:20 +0100327 // reset invocation counter
328 reset(mStatusBarService);
329
Benjamin Franza83859f2017-07-03 16:34:14 +0100330 // WHEN calling stopLockTask
Charles Heff9b4dff2017-09-22 10:18:37 +0100331 mLockTaskController.stopLockTaskMode(null, true, SYSTEM_UID);
Benjamin Franza83859f2017-07-03 16:34:14 +0100332
333 // THEN the lock task mode should no longer be active
334 assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState());
335 // THEN the task should no longer be locked
Charles Heff9b4dff2017-09-22 10:18:37 +0100336 assertFalse(mLockTaskController.isTaskLocked(tr));
Benjamin Franza83859f2017-07-03 16:34:14 +0100337 // THEN lock task mode should have been finished
338 verifyLockTaskStopped(times(1));
339 // THEN the keyguard should be shown
340 verify(mLockPatternUtils).requireCredentialEntry(UserHandle.USER_ALL);
Charles Hebfe82d12017-10-20 11:59:44 +0100341 // THEN screen pinning toast should be shown
342 verify(mLockTaskNotify).showPinningExitToast();
Benjamin Franza83859f2017-07-03 16:34:14 +0100343 }
344
Charles He520b2832017-09-02 15:27:16 +0100345 @Test
Charles Heff9b4dff2017-09-22 10:18:37 +0100346 public void testClearLockedTasks() throws Exception {
347 // GIVEN two task records with whitelisted auth that is in lock task mode
348 TaskRecord tr1 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
349 TaskRecord tr2 = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
350 mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
351 mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);
352
353 // WHEN calling stopLockTaskMode on the root task
354 mLockTaskController.clearLockedTasks("testClearLockedTasks");
355
356 // THEN the lock task mode should be inactive
357 assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState());
358 // THEN the first task should no longer be locked
359 assertFalse(mLockTaskController.isTaskLocked(tr1));
360 // THEN the top task should no longer be locked
361 assertFalse(mLockTaskController.isTaskLocked(tr2));
362 // THEN lock task mode should be finished
363 verifyLockTaskStopped(times(1));
364 }
365
366 @Test
Charles He520b2832017-09-02 15:27:16 +0100367 public void testUpdateLockTaskPackages() throws Exception {
368 String[] whitelist1 = {TEST_PACKAGE_NAME, TEST_PACKAGE_NAME_2};
369 String[] whitelist2 = {TEST_PACKAGE_NAME};
370
371 // No package is whitelisted initially
372 for (String pkg : whitelist1) {
373 assertFalse("Package shouldn't be whitelisted: " + pkg,
374 mLockTaskController.isPackageWhitelisted(TEST_USER_ID, pkg));
375 assertFalse("Package shouldn't be whitelisted for user 0: " + pkg,
376 mLockTaskController.isPackageWhitelisted(0, pkg));
377 }
378
379 // Apply whitelist
380 mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist1);
381
382 // Assert the whitelist is applied to the correct user
383 for (String pkg : whitelist1) {
384 assertTrue("Package should be whitelisted: " + pkg,
385 mLockTaskController.isPackageWhitelisted(TEST_USER_ID, pkg));
386 assertFalse("Package shouldn't be whitelisted for user 0: " + pkg,
387 mLockTaskController.isPackageWhitelisted(0, pkg));
388 }
389
390 // Update whitelist
391 mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist2);
392
393 // Assert the new whitelist is applied
394 assertTrue("Package should remain whitelisted: " + TEST_PACKAGE_NAME,
395 mLockTaskController.isPackageWhitelisted(TEST_USER_ID, TEST_PACKAGE_NAME));
396 assertFalse("Package should no longer be whitelisted: " + TEST_PACKAGE_NAME_2,
397 mLockTaskController.isPackageWhitelisted(TEST_USER_ID, TEST_PACKAGE_NAME_2));
398 }
399
400 @Test
401 public void testUpdateLockTaskPackages_taskRemoved() throws Exception {
402 // GIVEN two tasks which are whitelisted initially
403 TaskRecord tr1 = getTaskRecordForUpdate(TEST_PACKAGE_NAME, true);
404 TaskRecord tr2 = getTaskRecordForUpdate(TEST_PACKAGE_NAME_2, false);
405 String[] whitelist = {TEST_PACKAGE_NAME, TEST_PACKAGE_NAME_2};
406 mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist);
407
408 // GIVEN the tasks are launched into LockTask mode
409 mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
410 mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);
411 assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState());
Charles Heff9b4dff2017-09-22 10:18:37 +0100412 assertTrue(mLockTaskController.isTaskLocked(tr1));
413 assertTrue(mLockTaskController.isTaskLocked(tr2));
Charles Hee078db72017-10-19 18:03:20 +0100414 verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED, DISABLE2_MASK);
Charles He520b2832017-09-02 15:27:16 +0100415
416 // WHEN removing one package from whitelist
417 whitelist = new String[] {TEST_PACKAGE_NAME};
418 mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist);
419
420 // THEN the task running that package should be stopped
421 verify(tr2).performClearTaskLocked();
Charles Heff9b4dff2017-09-22 10:18:37 +0100422 assertFalse(mLockTaskController.isTaskLocked(tr2));
Charles He520b2832017-09-02 15:27:16 +0100423 // THEN the other task should remain locked
424 assertEquals(LOCK_TASK_MODE_LOCKED, mLockTaskController.getLockTaskModeState());
Charles Heff9b4dff2017-09-22 10:18:37 +0100425 assertTrue(mLockTaskController.isTaskLocked(tr1));
Charles Hee078db72017-10-19 18:03:20 +0100426 verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED, DISABLE2_MASK);
Charles He520b2832017-09-02 15:27:16 +0100427
428 // WHEN removing the last package from whitelist
429 whitelist = new String[] {};
430 mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist);
431
432 // THEN the last task should be cleared, and the system should quit LockTask mode
433 verify(tr1).performClearTaskLocked();
Charles Heff9b4dff2017-09-22 10:18:37 +0100434 assertFalse(mLockTaskController.isTaskLocked(tr1));
Charles He520b2832017-09-02 15:27:16 +0100435 assertEquals(LOCK_TASK_MODE_NONE, mLockTaskController.getLockTaskModeState());
436 verifyLockTaskStopped(times(1));
437 }
438
Charles Hee078db72017-10-19 18:03:20 +0100439 @Test
440 public void testUpdateLockTaskFeatures() throws Exception {
441 // GIVEN a locked task
442 TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
443 mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
444
445 // THEN lock task mode should be started with default status bar masks
446 verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED, DISABLE2_MASK);
447
448 // reset invocation counter
449 reset(mStatusBarService);
450
451 // WHEN home button is enabled for lock task mode
452 mLockTaskController.updateLockTaskFeatures(TEST_USER_ID, LOCK_TASK_FEATURE_HOME);
453
454 // THEN status bar should be updated to reflect this change
455 int expectedFlags = STATUS_BAR_MASK_LOCKED
456 & ~DISABLE_HOME;
457 int expectedFlags2 = DISABLE2_MASK;
458 verify(mStatusBarService).disable(eq(expectedFlags), any(IBinder.class),
459 eq(mContext.getPackageName()));
460 verify(mStatusBarService).disable2(eq(expectedFlags2), any(IBinder.class),
461 eq(mContext.getPackageName()));
462
463 // reset invocation counter
464 reset(mStatusBarService);
465
466 // WHEN notifications are enabled for lock task mode
467 mLockTaskController.updateLockTaskFeatures(TEST_USER_ID, LOCK_TASK_FEATURE_NOTIFICATIONS);
468
469 // THEN status bar should be updated to reflect this change
470 expectedFlags = STATUS_BAR_MASK_LOCKED
471 & ~DISABLE_NOTIFICATION_ICONS
472 & ~DISABLE_NOTIFICATION_ALERTS;
473 expectedFlags2 = DISABLE2_MASK
474 & ~DISABLE2_NOTIFICATION_SHADE;
475 verify(mStatusBarService).disable(eq(expectedFlags), any(IBinder.class),
476 eq(mContext.getPackageName()));
477 verify(mStatusBarService).disable2(eq(expectedFlags2), any(IBinder.class),
478 eq(mContext.getPackageName()));
479 }
480
481 @Test
482 public void testUpdateLockTaskFeatures_differentUser() throws Exception {
483 // GIVEN a locked task
484 TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
485 mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
486
487 // THEN lock task mode should be started with default status bar masks
488 verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED, DISABLE2_MASK);
489
490 // reset invocation counter
491 reset(mStatusBarService);
492
493 // WHEN home button is enabled for lock task mode for another user
494 mLockTaskController.updateLockTaskFeatures(TEST_USER_ID + 1, LOCK_TASK_FEATURE_HOME);
495
496 // THEN status bar shouldn't change
497 verify(mStatusBarService, never()).disable(anyInt(), any(IBinder.class),
498 eq(mContext.getPackageName()));
499 verify(mStatusBarService, never()).disable2(anyInt(), any(IBinder.class),
500 eq(mContext.getPackageName()));
501 }
502
503 @Test
504 public void testUpdateLockTaskFeatures_keyguard() throws Exception {
505 // GIVEN a locked task
506 TaskRecord tr = getTaskRecord(TaskRecord.LOCK_TASK_AUTH_WHITELISTED);
507 mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
508
509 // THEN keyguard should be disabled
510 verify(mWindowManager).disableKeyguard(any(IBinder.class), anyString());
511
512 // WHEN keyguard is enabled for lock task mode
513 mLockTaskController.updateLockTaskFeatures(TEST_USER_ID, LOCK_TASK_FEATURE_KEYGUARD);
514
515 // THEN keyguard should be enabled
516 verify(mWindowManager).reenableKeyguard(any(IBinder.class));
517
518 // WHEN keyguard is disabled again for lock task mode
519 mLockTaskController.updateLockTaskFeatures(TEST_USER_ID, LOCK_TASK_FEATURE_NONE);
520
521 // THEN keyguard should be disabled
522 verify(mWindowManager, times(2)).disableKeyguard(any(IBinder.class), anyString());
523 }
524
525 @Test
526 public void testGetStatusBarDisableFlags() {
527 // Note that we don't enumerate all StatusBarManager flags, but only choose a subset to test
528
529 // WHEN nothing is enabled
530 Pair<Integer, Integer> flags = mLockTaskController.getStatusBarDisableFlags(
531 LOCK_TASK_FEATURE_NONE);
532 // THEN unsupported feature flags should still be untouched
533 assertTrue((~STATUS_BAR_MASK_LOCKED & flags.first) == 0);
534 // THEN everything else should be disabled
535 assertTrue((StatusBarManager.DISABLE_CLOCK & flags.first) != 0);
536 assertTrue((StatusBarManager.DISABLE2_QUICK_SETTINGS & flags.second) != 0);
537
538 // WHEN only home button is enabled
539 flags = mLockTaskController.getStatusBarDisableFlags(
540 LOCK_TASK_FEATURE_HOME);
541 // THEN unsupported feature flags should still be untouched
542 assertTrue((~STATUS_BAR_MASK_LOCKED & flags.first) == 0);
543 // THEN home button should indeed be enabled
544 assertTrue((StatusBarManager.DISABLE_HOME & flags.first) == 0);
545 // THEN other feature flags should remain disabled
546 assertTrue((StatusBarManager.DISABLE2_NOTIFICATION_SHADE & flags.second) != 0);
547
548 // WHEN only global actions menu and notifications are enabled
549 flags = mLockTaskController.getStatusBarDisableFlags(
550 DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS
551 | DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS);
552 // THEN unsupported feature flags should still be untouched
553 assertTrue((~STATUS_BAR_MASK_LOCKED & flags.first) == 0);
554 // THEN notifications should be enabled
555 assertTrue((StatusBarManager.DISABLE_NOTIFICATION_ICONS & flags.first) == 0);
556 assertTrue((StatusBarManager.DISABLE_NOTIFICATION_ALERTS & flags.first) == 0);
557 assertTrue((StatusBarManager.DISABLE2_NOTIFICATION_SHADE & flags.second) == 0);
558 // THEN global actions should be enabled
559 assertTrue((StatusBarManager.DISABLE2_GLOBAL_ACTIONS & flags.second) == 0);
560 // THEN quick settings should still be disabled
561 assertTrue((StatusBarManager.DISABLE2_QUICK_SETTINGS & flags.second) != 0);
562 }
563
Benjamin Franza83859f2017-07-03 16:34:14 +0100564 private TaskRecord getTaskRecord(int lockTaskAuth) {
Charles He520b2832017-09-02 15:27:16 +0100565 return getTaskRecord(TEST_PACKAGE_NAME, lockTaskAuth);
566 }
567
568 private TaskRecord getTaskRecord(String pkg, int lockTaskAuth) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100569 TaskRecord tr = mock(TaskRecord.class);
570 tr.mLockTaskAuth = lockTaskAuth;
571 tr.intent = new Intent()
Charles He520b2832017-09-02 15:27:16 +0100572 .setComponent(ComponentName.createRelative(pkg, TEST_CLASS_NAME));
Benjamin Franza83859f2017-07-03 16:34:14 +0100573 tr.userId = TEST_USER_ID;
574 return tr;
575 }
576
Charles He520b2832017-09-02 15:27:16 +0100577 /**
578 * @param isAppAware {@code true} if the app has marked if_whitelisted in its manifest
579 */
580 private TaskRecord getTaskRecordForUpdate(String pkg, boolean isAppAware) {
581 final int authIfWhitelisted = isAppAware
582 ? TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE
583 : TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
584 TaskRecord tr = getTaskRecord(pkg, authIfWhitelisted);
585 doAnswer((invocation) -> {
586 boolean isWhitelisted =
587 mLockTaskController.isPackageWhitelisted(TEST_USER_ID, pkg);
588 tr.mLockTaskAuth = isWhitelisted
589 ? authIfWhitelisted
590 : TaskRecord.LOCK_TASK_AUTH_PINNABLE;
591 return null;
592 }).when(tr).setLockTaskAuth();
593 return tr;
594 }
595
Charles Hee078db72017-10-19 18:03:20 +0100596 private void verifyLockTaskStarted(int statusBarMask, int statusBarMask2) throws Exception {
Benjamin Franza83859f2017-07-03 16:34:14 +0100597 // THEN the keyguard should have been disabled
598 verify(mWindowManager).disableKeyguard(any(IBinder.class), anyString());
599 // THEN the status bar should have been disabled
600 verify(mStatusBarService).disable(eq(statusBarMask), any(IBinder.class),
601 eq(mContext.getPackageName()));
Charles Hee078db72017-10-19 18:03:20 +0100602 verify(mStatusBarService).disable2(eq(statusBarMask2), any(IBinder.class),
603 eq(mContext.getPackageName()));
Benjamin Franza83859f2017-07-03 16:34:14 +0100604 // THEN the DO/PO should be informed about the operation
605 verify(mDevicePolicyManager).notifyLockTaskModeChanged(true, TEST_PACKAGE_NAME,
606 TEST_USER_ID);
607 }
608
609 private void verifyLockTaskStopped(VerificationMode mode) throws Exception {
610 // THEN the keyguard should have been disabled
611 verify(mWindowManager, mode).reenableKeyguard(any(IBinder.class));
612 // THEN the status bar should have been disabled
613 verify(mStatusBarService, mode).disable(eq(StatusBarManager.DISABLE_NONE),
614 any(IBinder.class), eq(mContext.getPackageName()));
Charles Hee078db72017-10-19 18:03:20 +0100615 verify(mStatusBarService, mode).disable2(eq(StatusBarManager.DISABLE2_NONE),
616 any(IBinder.class), eq(mContext.getPackageName()));
Benjamin Franza83859f2017-07-03 16:34:14 +0100617 // THEN the DO/PO should be informed about the operation
618 verify(mDevicePolicyManager, mode).notifyLockTaskModeChanged(false, null, TEST_USER_ID);
619 }
620
621 /**
622 * Special handler implementation that executes any message / runnable posted immediately on the
623 * thread that it's posted on rather than enqueuing them on its looper.
624 */
625 private static class ImmediatelyExecuteHandler extends Handler {
626 @Override
627 public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
628 if (msg.getCallback() != null) {
629 msg.getCallback().run();
630 }
631 return true;
632 }
633 }
634}