blob: 3b66f7d79752dfa18639a703c18162fa9abd7a4a [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
Wale Ogunwale59507092018-10-29 09:00:30 -070017package com.android.server.wm;
Benjamin Franza83859f2017-07-03 16:34:14 +010018
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;
Wale Ogunwale0568aed2017-09-08 13:29:37 -070022import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Benjamin Franza83859f2017-07-03 16:34:14 +010023import static android.content.Context.DEVICE_POLICY_SERVICE;
24import static android.content.Context.STATUS_BAR_SERVICE;
Charles He858f1322017-11-27 17:11:04 -080025import static android.content.Intent.ACTION_CALL_EMERGENCY;
Benjamin Franza83859f2017-07-03 16:34:14 +010026import static android.os.UserHandle.USER_ALL;
Amith Yamasani7cbbf2222017-08-30 14:22:37 -070027import static android.os.UserHandle.USER_CURRENT;
Charles He858f1322017-11-27 17:11:04 -080028import static android.telecom.TelecomManager.EMERGENCY_DIALER_COMPONENT;
Benjamin Franza83859f2017-07-03 16:34:14 +010029import static android.view.Display.DEFAULT_DISPLAY;
Charles He520b2832017-09-02 15:27:16 +010030
Wale Ogunwale59507092018-10-29 09:00:30 -070031import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
32import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
33import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
34import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
35import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
36import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
37import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
38import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
39import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
Benjamin Franza83859f2017-07-03 16:34:14 +010040
41import android.annotation.NonNull;
42import android.annotation.Nullable;
43import android.app.Activity;
44import android.app.ActivityManager;
Charles Hee078db72017-10-19 18:03:20 +010045import android.app.StatusBarManager;
46import android.app.admin.DevicePolicyManager;
Benjamin Franza83859f2017-07-03 16:34:14 +010047import android.app.admin.IDevicePolicyManager;
Charles Hee078db72017-10-19 18:03:20 +010048import android.content.ComponentName;
Benjamin Franza83859f2017-07-03 16:34:14 +010049import android.content.Context;
Charles He858f1322017-11-27 17:11:04 -080050import android.content.Intent;
Benjamin Franza83859f2017-07-03 16:34:14 +010051import android.os.Binder;
52import android.os.Debug;
53import android.os.Handler;
54import android.os.IBinder;
55import android.os.RemoteException;
56import android.os.ServiceManager;
57import android.provider.Settings;
Charles He858f1322017-11-27 17:11:04 -080058import android.telecom.TelecomManager;
Charles Hee078db72017-10-19 18:03:20 +010059import android.util.Pair;
Benjamin Franza83859f2017-07-03 16:34:14 +010060import android.util.Slog;
Charles He520b2832017-09-02 15:27:16 +010061import android.util.SparseArray;
Charles He858f1322017-11-27 17:11:04 -080062import android.util.SparseIntArray;
Benjamin Franza83859f2017-07-03 16:34:14 +010063
64import com.android.internal.annotations.VisibleForTesting;
Tony Mak2bf36912018-03-21 15:45:52 +000065import com.android.internal.policy.IKeyguardDismissCallback;
Benjamin Franza83859f2017-07-03 16:34:14 +010066import com.android.internal.statusbar.IStatusBarService;
67import com.android.internal.widget.LockPatternUtils;
68import com.android.server.LocalServices;
Wale Ogunwale59507092018-10-29 09:00:30 -070069import com.android.server.am.ActivityManagerService;
Benjamin Franza83859f2017-07-03 16:34:14 +010070import com.android.server.statusbar.StatusBarManagerInternal;
Benjamin Franza83859f2017-07-03 16:34:14 +010071
72import java.io.PrintWriter;
73import java.util.ArrayList;
Charles He520b2832017-09-02 15:27:16 +010074import java.util.Arrays;
Benjamin Franza83859f2017-07-03 16:34:14 +010075
76/**
77 * Helper class that deals with all things related to task locking. This includes the screen pinning
78 * mode that can be launched via System UI as well as the fully locked mode that can be achieved
79 * on fully managed devices.
80 *
Wale Ogunwale27c48ae2018-10-25 19:01:01 -070081 * Note: All methods in this class should only be called with the ActivityTaskManagerService lock
82 * held.
Benjamin Franza83859f2017-07-03 16:34:14 +010083 *
84 * @see Activity#startLockTask()
85 * @see Activity#stopLockTask()
86 */
87public class LockTaskController {
Wale Ogunwale98875612018-10-12 07:53:02 -070088 private static final String TAG = TAG_WITH_CLASS_NAME ? "LockTaskController" : TAG_ATM;
Benjamin Franza83859f2017-07-03 16:34:14 +010089 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
90
91 @VisibleForTesting
Charles Hee078db72017-10-19 18:03:20 +010092 static final int STATUS_BAR_MASK_LOCKED = StatusBarManager.DISABLE_MASK
93 & (~StatusBarManager.DISABLE_EXPAND)
94 & (~StatusBarManager.DISABLE_NOTIFICATION_TICKER)
95 & (~StatusBarManager.DISABLE_SYSTEM_INFO)
96 & (~StatusBarManager.DISABLE_BACK);
Benjamin Franza83859f2017-07-03 16:34:14 +010097 @VisibleForTesting
Charles Hee078db72017-10-19 18:03:20 +010098 static final int STATUS_BAR_MASK_PINNED = StatusBarManager.DISABLE_MASK
99 & (~StatusBarManager.DISABLE_BACK)
100 & (~StatusBarManager.DISABLE_HOME)
101 & (~StatusBarManager.DISABLE_RECENT);
102
103 private static final SparseArray<Pair<Integer, Integer>> STATUS_BAR_FLAG_MAP_LOCKED;
104 static {
105 STATUS_BAR_FLAG_MAP_LOCKED = new SparseArray<>();
106
107 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO,
108 new Pair<>(StatusBarManager.DISABLE_CLOCK, StatusBarManager.DISABLE2_SYSTEM_ICONS));
109
110 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS,
111 new Pair<>(StatusBarManager.DISABLE_NOTIFICATION_ICONS
112 | StatusBarManager.DISABLE_NOTIFICATION_ALERTS,
113 StatusBarManager.DISABLE2_NOTIFICATION_SHADE));
114
115 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_HOME,
116 new Pair<>(StatusBarManager.DISABLE_HOME, StatusBarManager.DISABLE2_NONE));
117
Benjamin Franzcaffa772018-02-05 16:36:10 +0000118 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW,
Charles Hee078db72017-10-19 18:03:20 +0100119 new Pair<>(StatusBarManager.DISABLE_RECENT, StatusBarManager.DISABLE2_NONE));
120
121 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS,
122 new Pair<>(StatusBarManager.DISABLE_NONE,
123 StatusBarManager.DISABLE2_GLOBAL_ACTIONS));
124 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100125
126 /** Tag used for disabling of keyguard */
127 private static final String LOCK_TASK_TAG = "Lock-to-App";
128
129 private final IBinder mToken = new Binder();
130 private final ActivityStackSupervisor mSupervisor;
131 private final Context mContext;
132
133 // The following system services cannot be final, because they do not exist when this class
134 // is instantiated during device boot
135 @VisibleForTesting
136 IStatusBarService mStatusBarService;
137 @VisibleForTesting
138 IDevicePolicyManager mDevicePolicyManager;
139 @VisibleForTesting
140 WindowManagerService mWindowManager;
141 @VisibleForTesting
142 LockPatternUtils mLockPatternUtils;
Charles He858f1322017-11-27 17:11:04 -0800143 @VisibleForTesting
144 TelecomManager mTelecomManager;
Benjamin Franza83859f2017-07-03 16:34:14 +0100145
146 /**
Charles Heff9b4dff2017-09-22 10:18:37 +0100147 * The chain of tasks in LockTask mode, in the order of when they first entered LockTask mode.
148 *
149 * The first task in the list, which started the current LockTask session, is called the root
150 * task. It coincides with the Home task in a typical multi-app kiosk deployment. When there are
151 * more than one locked tasks, the root task can't be finished. Nor can it be moved to the back
152 * of the stack by {@link ActivityStack#moveTaskToBackLocked(int)};
153 *
154 * Calling {@link Activity#stopLockTask()} on the root task will finish all tasks but itself in
155 * this list, and the device will exit LockTask mode.
156 *
157 * The list is empty if LockTask is inactive.
Benjamin Franza83859f2017-07-03 16:34:14 +0100158 */
159 private final ArrayList<TaskRecord> mLockTaskModeTasks = new ArrayList<>();
160
161 /**
Charles He520b2832017-09-02 15:27:16 +0100162 * Packages that are allowed to be launched into the lock task mode for each user.
163 */
164 private final SparseArray<String[]> mLockTaskPackages = new SparseArray<>();
165
166 /**
Charles Hee078db72017-10-19 18:03:20 +0100167 * Features that are allowed by DPC to show during LockTask mode.
168 */
Charles He858f1322017-11-27 17:11:04 -0800169 private final SparseIntArray mLockTaskFeatures = new SparseIntArray();
Charles Hee078db72017-10-19 18:03:20 +0100170
171 /**
Benjamin Franza83859f2017-07-03 16:34:14 +0100172 * Store the current lock task mode. Possible values:
173 * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
174 * {@link ActivityManager#LOCK_TASK_MODE_PINNED}
175 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100176 private int mLockTaskModeState = LOCK_TASK_MODE_NONE;
Benjamin Franza83859f2017-07-03 16:34:14 +0100177
178 /**
179 * This is ActivityStackSupervisor's Handler.
180 */
181 private final Handler mHandler;
182
183 LockTaskController(Context context, ActivityStackSupervisor supervisor,
184 Handler handler) {
185 mContext = context;
186 mSupervisor = supervisor;
187 mHandler = handler;
188 }
189
190 /**
191 * Set the window manager instance used in this class. This is necessary, because the window
192 * manager does not exist during instantiation of this class.
193 */
194 void setWindowManager(WindowManagerService windowManager) {
195 mWindowManager = windowManager;
196 }
197
198 /**
199 * @return the current lock task state. This can be any of
200 * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
201 * {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
202 */
203 int getLockTaskModeState() {
204 return mLockTaskModeState;
205 }
206
207 /**
Charles He520b2832017-09-02 15:27:16 +0100208 * @return whether the given task is locked at the moment. Locked tasks cannot be moved to the
209 * back of the stack.
Benjamin Franza83859f2017-07-03 16:34:14 +0100210 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100211 @VisibleForTesting
212 boolean isTaskLocked(TaskRecord task) {
213 return mLockTaskModeTasks.contains(task);
214 }
215
216 /**
217 * @return {@code true} whether this task first started the current LockTask session.
218 */
219 private boolean isRootTask(TaskRecord task) {
220 return mLockTaskModeTasks.indexOf(task) == 0;
221 }
222
223 /**
224 * @return whether the given activity is blocked from finishing, because it is the only activity
225 * of the last locked task and finishing it would mean that lock task mode is ended illegally.
226 */
227 boolean activityBlockedFromFinish(ActivityRecord activity) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800228 final TaskRecord task = activity.getTaskRecord();
Charles Heff9b4dff2017-09-22 10:18:37 +0100229 if (activity == task.getRootActivity()
230 && activity == task.getTopActivity()
231 && task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV
232 && isRootTask(task)) {
233 Slog.i(TAG, "Not finishing task in lock task mode");
Benjamin Franza83859f2017-07-03 16:34:14 +0100234 showLockTaskToast();
235 return true;
236 }
237 return false;
238 }
239
240 /**
Charles Heff9b4dff2017-09-22 10:18:37 +0100241 * @return whether the given task can be moved to the back of the stack with
242 * {@link ActivityStack#moveTaskToBackLocked(int)}
243 * @see #mLockTaskModeTasks
Benjamin Franza83859f2017-07-03 16:34:14 +0100244 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100245 boolean canMoveTaskToBack(TaskRecord task) {
246 if (isRootTask(task)) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100247 showLockTaskToast();
Charles Heff9b4dff2017-09-22 10:18:37 +0100248 return false;
Benjamin Franza83859f2017-07-03 16:34:14 +0100249 }
Charles Heff9b4dff2017-09-22 10:18:37 +0100250 return true;
Benjamin Franza83859f2017-07-03 16:34:14 +0100251 }
252
253 /**
Charles Hed62f9652017-11-01 10:05:51 +0000254 * @return whether the requested task is allowed to be locked (either whitelisted, or declares
255 * lockTaskMode="always" in the manifest).
256 */
257 boolean isTaskWhitelisted(TaskRecord task) {
258 switch(task.mLockTaskAuth) {
259 case LOCK_TASK_AUTH_WHITELISTED:
260 case LOCK_TASK_AUTH_LAUNCHABLE:
261 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
262 return true;
263 case LOCK_TASK_AUTH_PINNABLE:
264 case LOCK_TASK_AUTH_DONT_LOCK:
265 default:
266 return false;
267 }
268 }
269
270 /**
271 * @return whether the requested task is disallowed to be launched.
Benjamin Franza83859f2017-07-03 16:34:14 +0100272 */
273 boolean isLockTaskModeViolation(TaskRecord task) {
274 return isLockTaskModeViolation(task, false);
275 }
276
277 /**
278 * @param isNewClearTask whether the task would be cleared as part of the operation.
Charles Hed62f9652017-11-01 10:05:51 +0000279 * @return whether the requested task is disallowed to be launched.
Benjamin Franza83859f2017-07-03 16:34:14 +0100280 */
281 boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) {
282 if (isLockTaskModeViolationInternal(task, isNewClearTask)) {
283 showLockTaskToast();
284 return true;
285 }
286 return false;
287 }
288
Benjamin Franz7dcbfb02018-01-16 15:16:16 +0000289 /**
290 * @return the root task of the lock task.
291 */
292 TaskRecord getRootTask() {
293 if (mLockTaskModeTasks.isEmpty()) {
294 return null;
295 }
296 return mLockTaskModeTasks.get(0);
297 }
298
Benjamin Franza83859f2017-07-03 16:34:14 +0100299 private boolean isLockTaskModeViolationInternal(TaskRecord task, boolean isNewClearTask) {
300 // TODO: Double check what's going on here. If the task is already in lock task mode, it's
301 // likely whitelisted, so will return false below.
Charles Heff9b4dff2017-09-22 10:18:37 +0100302 if (isTaskLocked(task) && !isNewClearTask) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100303 // If the task is already at the top and won't be cleared, then allow the operation
304 return false;
305 }
Charles Hed62f9652017-11-01 10:05:51 +0000306
307 // Allow recents activity if enabled by policy
308 if (task.isActivityTypeRecents() && isRecentsAllowed(task.userId)) {
309 return false;
Benjamin Franza83859f2017-07-03 16:34:14 +0100310 }
Charles Hed62f9652017-11-01 10:05:51 +0000311
Charles He858f1322017-11-27 17:11:04 -0800312 // Allow emergency calling when the device is protected by a locked keyguard
313 if (isKeyguardAllowed(task.userId) && isEmergencyCallTask(task)) {
314 return false;
315 }
316
Charles Hed62f9652017-11-01 10:05:51 +0000317 return !(isTaskWhitelisted(task) || mLockTaskModeTasks.isEmpty());
318 }
319
320 private boolean isRecentsAllowed(int userId) {
321 return (getLockTaskFeaturesForUser(userId)
Benjamin Franzcaffa772018-02-05 16:36:10 +0000322 & DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW) != 0;
Benjamin Franza83859f2017-07-03 16:34:14 +0100323 }
324
Charles He858f1322017-11-27 17:11:04 -0800325 private boolean isKeyguardAllowed(int userId) {
326 return (getLockTaskFeaturesForUser(userId)
327 & DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD) != 0;
328 }
329
330 private boolean isEmergencyCallTask(TaskRecord task) {
331 final Intent intent = task.intent;
332 if (intent == null) {
333 return false;
334 }
335
336 // 1. The emergency keypad activity launched on top of the keyguard
337 if (EMERGENCY_DIALER_COMPONENT.equals(intent.getComponent())) {
338 return true;
339 }
340
341 // 2. The intent sent by the keypad, which is handled by Telephony
342 if (ACTION_CALL_EMERGENCY.equals(intent.getAction())) {
343 return true;
344 }
345
346 // 3. Telephony then starts the default package for making the call
347 final TelecomManager tm = getTelecomManager();
348 final String dialerPackage = tm != null ? tm.getSystemDialerPackage() : null;
349 if (dialerPackage != null && dialerPackage.equals(intent.getComponent().getPackageName())) {
350 return true;
351 }
352
353 return false;
354 }
355
Benjamin Franza83859f2017-07-03 16:34:14 +0100356 /**
357 * Stop the current lock task mode.
358 *
Charles Heff9b4dff2017-09-22 10:18:37 +0100359 * This is called by {@link ActivityManagerService} and performs various checks before actually
360 * finishing the locked task.
361 *
362 * @param task the task that requested the end of lock task mode ({@code null} for quitting app
363 * pinning mode)
364 * @param isSystemCaller indicates whether this request comes from the system via
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700365 * {@link ActivityTaskManagerService#stopSystemLockTaskMode()}. If
Charles Heff9b4dff2017-09-22 10:18:37 +0100366 * {@code true}, it means the user intends to stop pinned mode through UI;
367 * otherwise, it's called by an app and we need to stop locked or pinned
368 * mode, subject to checks.
Benjamin Franza83859f2017-07-03 16:34:14 +0100369 * @param callingUid the caller that requested the end of lock task mode.
Charles Heff9b4dff2017-09-22 10:18:37 +0100370 * @throws IllegalArgumentException if the calling task is invalid (e.g., {@code null} or not in
371 * foreground)
Benjamin Franza83859f2017-07-03 16:34:14 +0100372 * @throws SecurityException if the caller is not authorized to stop the lock task mode, i.e. if
373 * they differ from the one that launched lock task mode.
374 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100375 void stopLockTaskMode(@Nullable TaskRecord task, boolean isSystemCaller, int callingUid) {
376 if (mLockTaskModeState == LOCK_TASK_MODE_NONE) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100377 return;
378 }
379
Charles Heff9b4dff2017-09-22 10:18:37 +0100380 if (isSystemCaller) {
381 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
382 clearLockedTasks("stopAppPinning");
383 } else {
384 Slog.e(TAG_LOCKTASK, "Attempted to stop LockTask with isSystemCaller=true");
385 showLockTaskToast();
386 }
387
388 } else {
389 // Ensure calling activity is not null
390 if (task == null) {
391 throw new IllegalArgumentException("can't stop LockTask for null task");
392 }
393
394 // Ensure the same caller for startLockTaskMode and stopLockTaskMode.
395 // It is possible lockTaskMode was started by the system process because
396 // android:lockTaskMode is set to a locking value in the application manifest
397 // instead of the app calling startLockTaskMode. In this case
398 // {@link TaskRecord.mLockTaskUid} will be 0, so we compare the callingUid to the
399 // {@link TaskRecord.effectiveUid} instead. Also caller with
400 // {@link MANAGE_ACTIVITY_STACKS} can stop any lock task.
401 if (callingUid != task.mLockTaskUid
402 && (task.mLockTaskUid != 0 || callingUid != task.effectiveUid)) {
403 throw new SecurityException("Invalid uid, expected " + task.mLockTaskUid
404 + " callingUid=" + callingUid + " effectiveUid=" + task.effectiveUid);
405 }
406
407 // We don't care if it's pinned or locked mode; this will stop it anyways.
408 clearLockedTask(task);
409 }
410 }
411
412 /**
413 * Clear all locked tasks and request the end of LockTask mode.
414 *
Wale Ogunwale59507092018-10-29 09:00:30 -0700415 * This method is called by UserController when starting a new foreground user, and,
Charles Heff9b4dff2017-09-22 10:18:37 +0100416 * unlike {@link #stopLockTaskMode(TaskRecord, boolean, int)}, it doesn't perform the checks.
417 */
418 void clearLockedTasks(String reason) {
419 if (DEBUG_LOCKTASK) Slog.i(TAG_LOCKTASK, "clearLockedTasks: " + reason);
420 if (!mLockTaskModeTasks.isEmpty()) {
421 clearLockedTask(mLockTaskModeTasks.get(0));
422 }
423 }
424
425 /**
426 * Clear one locked task from LockTask mode.
427 *
428 * If the requested task is the root task (see {@link #mLockTaskModeTasks}), then all locked
429 * tasks are cleared. Otherwise, only the requested task is cleared. LockTask mode is stopped
430 * when the last locked task is cleared.
431 *
432 * @param task the task to be cleared from LockTask mode.
433 */
434 void clearLockedTask(final TaskRecord task) {
435 if (task == null || mLockTaskModeTasks.isEmpty()) return;
436
437 if (task == mLockTaskModeTasks.get(0)) {
438 // We're removing the root task while there are other locked tasks. Therefore we should
439 // clear all locked tasks in reverse order.
440 for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx > 0; --taskNdx) {
441 clearLockedTask(mLockTaskModeTasks.get(taskNdx));
442 }
443 }
444
445 removeLockedTask(task);
446 if (mLockTaskModeTasks.isEmpty()) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100447 return;
448 }
Charles Heff9b4dff2017-09-22 10:18:37 +0100449 task.performClearTaskLocked();
Wale Ogunwaled32da472018-11-16 07:19:28 -0800450 mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities();
Benjamin Franza83859f2017-07-03 16:34:14 +0100451 }
452
453 /**
454 * Remove the given task from the locked task list. If this was the last task in the list,
455 * lock task mode is stopped.
456 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100457 private void removeLockedTask(final TaskRecord task) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100458 if (!mLockTaskModeTasks.remove(task)) {
459 return;
460 }
Charles Heff9b4dff2017-09-22 10:18:37 +0100461 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: removed " + task);
Benjamin Franza83859f2017-07-03 16:34:14 +0100462 if (mLockTaskModeTasks.isEmpty()) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100463 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: task=" + task +
464 " last task, reverting locktask mode. Callers=" + Debug.getCallers(3));
465 mHandler.post(() -> performStopLockTask(task.userId));
466 }
467 }
468
Benjamin Franza83859f2017-07-03 16:34:14 +0100469 // This method should only be called on the handler thread
470 private void performStopLockTask(int userId) {
471 // When lock task ends, we enable the status bars.
472 try {
Charles Hee078db72017-10-19 18:03:20 +0100473 setStatusBarState(LOCK_TASK_MODE_NONE, userId);
474 setKeyguardState(LOCK_TASK_MODE_NONE, userId);
475 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
476 lockKeyguardIfNeeded();
Benjamin Franza83859f2017-07-03 16:34:14 +0100477 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100478 if (getDevicePolicyManager() != null) {
479 getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId);
480 }
Charles Hebfe82d12017-10-20 11:59:44 +0100481 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
Matthew Ng9c3bce52018-02-01 22:00:31 +0000482 getStatusBarService().showPinningEnterExitToast(false /* entering */);
Charles Hebfe82d12017-10-20 11:59:44 +0100483 }
Benjamin Franz3662b152018-01-16 17:23:44 +0000484 mWindowManager.onLockTaskStateChanged(LOCK_TASK_MODE_NONE);
Benjamin Franza83859f2017-07-03 16:34:14 +0100485 } catch (RemoteException ex) {
486 throw new RuntimeException(ex);
487 } finally {
488 mLockTaskModeState = LOCK_TASK_MODE_NONE;
489 }
490 }
491
492 /**
Charles Hebfe82d12017-10-20 11:59:44 +0100493 * Show the lock task violation toast. Currently we only show toast for screen pinning mode, and
494 * no-op if the device is in locked mode.
Benjamin Franza83859f2017-07-03 16:34:14 +0100495 */
496 void showLockTaskToast() {
Charles Hebfe82d12017-10-20 11:59:44 +0100497 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
Matthew Ng9c3bce52018-02-01 22:00:31 +0000498 try {
499 getStatusBarService().showPinningEscapeToast();
500 } catch (RemoteException e) {
501 Slog.e(TAG, "Failed to send pinning escape toast", e);
502 }
Charles Hebfe82d12017-10-20 11:59:44 +0100503 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100504 }
505
506 // Starting lock task
507
508 /**
509 * Method to start lock task mode on a given task.
510 *
511 * @param task the task that should be locked.
Charles Heff9b4dff2017-09-22 10:18:37 +0100512 * @param isSystemCaller indicates whether this request was initiated by the system via
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700513 * {@link ActivityTaskManagerService#startSystemLockTaskMode(int)}. If
Charles Heff9b4dff2017-09-22 10:18:37 +0100514 * {@code true}, this intends to start pinned mode; otherwise, we look
515 * at the calling task's mLockTaskAuth to decide which mode to start.
Benjamin Franza83859f2017-07-03 16:34:14 +0100516 * @param callingUid the caller that requested the launch of lock task mode.
517 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100518 void startLockTaskMode(@NonNull TaskRecord task, boolean isSystemCaller, int callingUid) {
519 if (!isSystemCaller) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100520 task.mLockTaskUid = callingUid;
521 if (task.mLockTaskAuth == LOCK_TASK_AUTH_PINNABLE) {
522 // startLockTask() called by app, but app is not part of lock task whitelist. Show
Charles Heff9b4dff2017-09-22 10:18:37 +0100523 // app pinning request. We will come back here with isSystemCaller true.
Benjamin Franza83859f2017-07-03 16:34:14 +0100524 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Mode default, asking user");
525 StatusBarManagerInternal statusBarManager = LocalServices.getService(
526 StatusBarManagerInternal.class);
527 if (statusBarManager != null) {
528 statusBarManager.showScreenPinningRequest(task.taskId);
529 }
530 return;
531 }
532 }
533
534 // System can only initiate screen pinning, not full lock task mode
Charles Heff9b4dff2017-09-22 10:18:37 +0100535 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
536 isSystemCaller ? "Locking pinned" : "Locking fully");
537 setLockTaskMode(task, isSystemCaller ? LOCK_TASK_MODE_PINNED : LOCK_TASK_MODE_LOCKED,
Benjamin Franza83859f2017-07-03 16:34:14 +0100538 "startLockTask", true);
539 }
540
541 /**
542 * Start lock task mode on the given task.
543 * @param lockTaskModeState whether fully locked or pinned mode.
544 * @param andResume whether the task should be brought to foreground as part of the operation.
545 */
546 private void setLockTaskMode(@NonNull TaskRecord task, int lockTaskModeState,
547 String reason, boolean andResume) {
548 // Should have already been checked, but do it again.
549 if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) {
550 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
551 "setLockTaskMode: Can't lock due to auth");
552 return;
553 }
554 if (isLockTaskModeViolation(task)) {
555 Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task.");
556 return;
557 }
558
Bryce Lee1a990e52018-04-23 10:54:11 -0700559 final Intent taskIntent = task.intent;
560 if (mLockTaskModeTasks.isEmpty() && taskIntent != null) {
Charles Hed62f9652017-11-01 10:05:51 +0000561 mSupervisor.mRecentTasks.onLockTaskModeStateChanged(lockTaskModeState, task.userId);
Benjamin Franza83859f2017-07-03 16:34:14 +0100562 // Start lock task on the handler thread
563 mHandler.post(() -> performStartLockTask(
Bryce Lee1a990e52018-04-23 10:54:11 -0700564 taskIntent.getComponent().getPackageName(),
Benjamin Franza83859f2017-07-03 16:34:14 +0100565 task.userId,
566 lockTaskModeState));
567 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100568 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskMode: Locking to " + task +
569 " Callers=" + Debug.getCallers(4));
Charles Heff9b4dff2017-09-22 10:18:37 +0100570
571 if (!mLockTaskModeTasks.contains(task)) {
572 mLockTaskModeTasks.add(task);
573 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100574
575 if (task.mLockTaskUid == -1) {
576 task.mLockTaskUid = task.effectiveUid;
577 }
578
579 if (andResume) {
Wale Ogunwale66e16852017-10-19 13:35:52 -0700580 mSupervisor.findTaskToMoveToFront(task, 0, null, reason,
Benjamin Franza83859f2017-07-03 16:34:14 +0100581 lockTaskModeState != LOCK_TASK_MODE_NONE);
Wale Ogunwaled32da472018-11-16 07:19:28 -0800582 mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities();
lumark588a3e82018-07-20 18:53:54 +0800583 final ActivityStack stack = task.getStack();
584 if (stack != null) {
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800585 stack.getDisplay().mDisplayContent.executeAppTransition();
lumark588a3e82018-07-20 18:53:54 +0800586 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100587 } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
Wale Ogunwale0568aed2017-09-08 13:29:37 -0700588 mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED,
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700589 DEFAULT_DISPLAY, task.getStack(), true /* forceNonResizable */);
Benjamin Franza83859f2017-07-03 16:34:14 +0100590 }
591 }
592
593 // This method should only be called on the handler thread
594 private void performStartLockTask(String packageName, int userId, int lockTaskModeState) {
595 // When lock task starts, we disable the status bars.
596 try {
Charles Hebfe82d12017-10-20 11:59:44 +0100597 if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
Matthew Ng9c3bce52018-02-01 22:00:31 +0000598 getStatusBarService().showPinningEnterExitToast(true /* entering */);
Charles Hebfe82d12017-10-20 11:59:44 +0100599 }
Benjamin Franz3662b152018-01-16 17:23:44 +0000600 mWindowManager.onLockTaskStateChanged(lockTaskModeState);
Benjamin Franza83859f2017-07-03 16:34:14 +0100601 mLockTaskModeState = lockTaskModeState;
Charles Hee078db72017-10-19 18:03:20 +0100602 setStatusBarState(lockTaskModeState, userId);
603 setKeyguardState(lockTaskModeState, userId);
Benjamin Franza83859f2017-07-03 16:34:14 +0100604 if (getDevicePolicyManager() != null) {
605 getDevicePolicyManager().notifyLockTaskModeChanged(true, packageName, userId);
606 }
607 } catch (RemoteException ex) {
608 throw new RuntimeException(ex);
609 }
610 }
611
612 /**
Charles He520b2832017-09-02 15:27:16 +0100613 * Update packages that are allowed to be launched in lock task mode.
614 * @param userId Which user this whitelist is associated with
615 * @param packages The whitelist of packages allowed in lock task mode
616 * @see #mLockTaskPackages
Benjamin Franza83859f2017-07-03 16:34:14 +0100617 */
Charles He520b2832017-09-02 15:27:16 +0100618 void updateLockTaskPackages(int userId, String[] packages) {
619 mLockTaskPackages.put(userId, packages);
620
621 boolean taskChanged = false;
Benjamin Franza83859f2017-07-03 16:34:14 +0100622 for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) {
623 final TaskRecord lockedTask = mLockTaskModeTasks.get(taskNdx);
Charles He520b2832017-09-02 15:27:16 +0100624 final boolean wasWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
625 || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
Benjamin Franza83859f2017-07-03 16:34:14 +0100626 lockedTask.setLockTaskAuth();
Charles He520b2832017-09-02 15:27:16 +0100627 final boolean isWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
628 || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
629
630 if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED
631 || lockedTask.userId != userId
632 || !wasWhitelisted || isWhitelisted) {
633 continue;
Benjamin Franza83859f2017-07-03 16:34:14 +0100634 }
Charles He520b2832017-09-02 15:27:16 +0100635
636 // Terminate locked tasks that have recently lost whitelist authorization.
637 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " +
638 lockedTask + " mLockTaskAuth()=" + lockedTask.lockTaskAuthToString());
639 removeLockedTask(lockedTask);
640 lockedTask.performClearTaskLocked();
641 taskChanged = true;
Benjamin Franza83859f2017-07-03 16:34:14 +0100642 }
643
Wale Ogunwaled32da472018-11-16 07:19:28 -0800644 for (int displayNdx = mSupervisor.mRootActivityContainer.getChildCount() - 1;
645 displayNdx >= 0; --displayNdx) {
646 mSupervisor.mRootActivityContainer.getChildAt(displayNdx).onLockTaskPackagesUpdated();
Benjamin Franza83859f2017-07-03 16:34:14 +0100647 }
Charles He520b2832017-09-02 15:27:16 +0100648
Wale Ogunwaled32da472018-11-16 07:19:28 -0800649 final ActivityRecord r = mSupervisor.mRootActivityContainer.topRunningActivity();
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800650 final TaskRecord task = (r != null) ? r.getTaskRecord() : null;
Charles He520b2832017-09-02 15:27:16 +0100651 if (mLockTaskModeTasks.isEmpty() && task!= null
Benjamin Franza83859f2017-07-03 16:34:14 +0100652 && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
653 // This task must have just been authorized.
654 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK,
655 "onLockTaskPackagesUpdated: starting new locktask task=" + task);
Charles He520b2832017-09-02 15:27:16 +0100656 setLockTaskMode(task, LOCK_TASK_MODE_LOCKED, "package updated", false);
657 taskChanged = true;
Benjamin Franza83859f2017-07-03 16:34:14 +0100658 }
Charles He520b2832017-09-02 15:27:16 +0100659
660 if (taskChanged) {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800661 mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities();
Benjamin Franza83859f2017-07-03 16:34:14 +0100662 }
663 }
664
Charles He520b2832017-09-02 15:27:16 +0100665 boolean isPackageWhitelisted(int userId, String pkg) {
666 if (pkg == null) {
667 return false;
668 }
669 String[] whitelist;
670 whitelist = mLockTaskPackages.get(userId);
671 if (whitelist == null) {
672 return false;
673 }
674 for (String whitelistedPkg : whitelist) {
675 if (pkg.equals(whitelistedPkg)) {
676 return true;
677 }
678 }
679 return false;
680 }
681
Benjamin Franza83859f2017-07-03 16:34:14 +0100682 /**
Charles Hee078db72017-10-19 18:03:20 +0100683 * Update the UI features that are enabled for LockTask mode.
684 * @param userId Which user these feature flags are associated with
685 * @param flags Bitfield of feature flags
686 * @see DevicePolicyManager#setLockTaskFeatures(ComponentName, int)
687 */
688 void updateLockTaskFeatures(int userId, int flags) {
689 int oldFlags = getLockTaskFeaturesForUser(userId);
690 if (flags == oldFlags) {
691 return;
692 }
693
694 mLockTaskFeatures.put(userId, flags);
Charles Heff9b4dff2017-09-22 10:18:37 +0100695 if (!mLockTaskModeTasks.isEmpty() && userId == mLockTaskModeTasks.get(0).userId) {
Charles Hee078db72017-10-19 18:03:20 +0100696 mHandler.post(() -> {
697 if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) {
698 setStatusBarState(mLockTaskModeState, userId);
699 setKeyguardState(mLockTaskModeState, userId);
700 }
701 });
702 }
703 }
704
705 /**
706 * Helper method for configuring the status bar disabled state.
707 * Should only be called on the handler thread to avoid race.
708 */
709 private void setStatusBarState(int lockTaskModeState, int userId) {
710 IStatusBarService statusBar = getStatusBarService();
711 if (statusBar == null) {
712 Slog.e(TAG, "Can't find StatusBarService");
713 return;
714 }
715
716 // Default state, when lockTaskModeState == LOCK_TASK_MODE_NONE
717 int flags1 = StatusBarManager.DISABLE_NONE;
718 int flags2 = StatusBarManager.DISABLE2_NONE;
719
720 if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
721 flags1 = STATUS_BAR_MASK_PINNED;
722
723 } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
724 int lockTaskFeatures = getLockTaskFeaturesForUser(userId);
725 Pair<Integer, Integer> statusBarFlags = getStatusBarDisableFlags(lockTaskFeatures);
726 flags1 = statusBarFlags.first;
727 flags2 = statusBarFlags.second;
728 }
729
730 try {
731 statusBar.disable(flags1, mToken, mContext.getPackageName());
732 statusBar.disable2(flags2, mToken, mContext.getPackageName());
733 } catch (RemoteException e) {
734 Slog.e(TAG, "Failed to set status bar flags", e);
735 }
736 }
737
738 /**
739 * Helper method for configuring the keyguard disabled state.
740 * Should only be called on the handler thread to avoid race.
741 */
742 private void setKeyguardState(int lockTaskModeState, int userId) {
743 if (lockTaskModeState == LOCK_TASK_MODE_NONE) {
744 mWindowManager.reenableKeyguard(mToken);
745
746 } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
Charles He858f1322017-11-27 17:11:04 -0800747 if (isKeyguardAllowed(userId)) {
Charles Hee078db72017-10-19 18:03:20 +0100748 mWindowManager.reenableKeyguard(mToken);
Charles He858f1322017-11-27 17:11:04 -0800749 } else {
Tony Mak2bf36912018-03-21 15:45:52 +0000750 // If keyguard is not secure and it is locked, dismiss the keyguard before
751 // disabling it, which avoids the platform to think the keyguard is still on.
752 if (mWindowManager.isKeyguardLocked() && !mWindowManager.isKeyguardSecure()) {
753 mWindowManager.dismissKeyguard(new IKeyguardDismissCallback.Stub() {
754 @Override
755 public void onDismissError() throws RemoteException {
756 Slog.i(TAG, "setKeyguardState: failed to dismiss keyguard");
757 }
758
759 @Override
760 public void onDismissSucceeded() throws RemoteException {
761 mHandler.post(
762 () -> mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG));
763 }
764
765 @Override
766 public void onDismissCancelled() throws RemoteException {
767 Slog.i(TAG, "setKeyguardState: dismiss cancelled");
768 }
769 }, null);
770 } else {
771 mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
772 }
Charles Hee078db72017-10-19 18:03:20 +0100773 }
774
775 } else { // lockTaskModeState == LOCK_TASK_MODE_PINNED
776 mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
777 }
778 }
779
780 /**
781 * Helper method for locking the device immediately. This may be necessary when the device
782 * leaves the pinned mode.
783 */
784 private void lockKeyguardIfNeeded() {
785 try {
786 boolean shouldLockKeyguard = Settings.Secure.getIntForUser(
787 mContext.getContentResolver(),
788 Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
789 USER_CURRENT) != 0;
790 if (shouldLockKeyguard) {
791 mWindowManager.lockNow(null);
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800792 mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
Charles Hee078db72017-10-19 18:03:20 +0100793 getLockPatternUtils().requireCredentialEntry(USER_ALL);
794 }
795 } catch (Settings.SettingNotFoundException e) {
796 // No setting, don't lock.
797 }
798 }
799
800 /**
801 * Translates from LockTask feature flags to StatusBarManager disable and disable2 flags.
802 * @param lockTaskFlags Bitfield of flags as per
803 * {@link DevicePolicyManager#setLockTaskFeatures(ComponentName, int)}
804 * @return A {@link Pair} of {@link StatusBarManager#disable(int)} and
805 * {@link StatusBarManager#disable2(int)} flags
806 */
807 @VisibleForTesting
808 Pair<Integer, Integer> getStatusBarDisableFlags(int lockTaskFlags) {
809 // Everything is disabled by default
810 int flags1 = StatusBarManager.DISABLE_MASK;
811 int flags2 = StatusBarManager.DISABLE2_MASK;
812 for (int i = STATUS_BAR_FLAG_MAP_LOCKED.size() - 1; i >= 0; i--) {
813 Pair<Integer, Integer> statusBarFlags = STATUS_BAR_FLAG_MAP_LOCKED.valueAt(i);
814 if ((STATUS_BAR_FLAG_MAP_LOCKED.keyAt(i) & lockTaskFlags) != 0) {
815 flags1 &= ~statusBarFlags.first;
816 flags2 &= ~statusBarFlags.second;
817 }
818 }
819 // Some flags are not used for LockTask purposes, so we mask them
820 flags1 &= STATUS_BAR_MASK_LOCKED;
821 return new Pair<>(flags1, flags2);
822 }
823
824 /**
825 * Gets the cached value of LockTask feature flags for a specific user.
826 */
827 private int getLockTaskFeaturesForUser(int userId) {
828 return mLockTaskFeatures.get(userId, DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
829 }
830
Benjamin Franza83859f2017-07-03 16:34:14 +0100831 // Should only be called on the handler thread
832 @Nullable
833 private IStatusBarService getStatusBarService() {
834 if (mStatusBarService == null) {
835 mStatusBarService = IStatusBarService.Stub.asInterface(
836 ServiceManager.checkService(STATUS_BAR_SERVICE));
837 if (mStatusBarService == null) {
838 Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE");
839 }
840 }
841 return mStatusBarService;
842 }
843
844 // Should only be called on the handler thread
845 @Nullable
846 private IDevicePolicyManager getDevicePolicyManager() {
847 if (mDevicePolicyManager == null) {
848 mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface(
849 ServiceManager.checkService(DEVICE_POLICY_SERVICE));
850 if (mDevicePolicyManager == null) {
851 Slog.w(TAG, "warning: no DEVICE_POLICY_SERVICE");
852 }
853 }
854 return mDevicePolicyManager;
855 }
856
857 @NonNull
858 private LockPatternUtils getLockPatternUtils() {
859 if (mLockPatternUtils == null) {
860 // We don't preserve the LPU object to save memory
861 return new LockPatternUtils(mContext);
862 }
863 return mLockPatternUtils;
864 }
865
Charles He858f1322017-11-27 17:11:04 -0800866 @Nullable
867 private TelecomManager getTelecomManager() {
868 if (mTelecomManager == null) {
869 // We don't preserve the TelecomManager object to save memory
870 return mContext.getSystemService(TelecomManager.class);
871 }
872 return mTelecomManager;
873 }
874
Benjamin Franza83859f2017-07-03 16:34:14 +0100875 public void dump(PrintWriter pw, String prefix) {
Charles He520b2832017-09-02 15:27:16 +0100876 pw.println(prefix + "LockTaskController");
877 prefix = prefix + " ";
878 pw.println(prefix + "mLockTaskModeState=" + lockTaskModeToString());
879 pw.println(prefix + "mLockTaskModeTasks=");
880 for (int i = 0; i < mLockTaskModeTasks.size(); ++i) {
881 pw.println(prefix + " #" + i + " " + mLockTaskModeTasks.get(i));
882 }
883 pw.println(prefix + "mLockTaskPackages (userId:packages)=");
884 for (int i = 0; i < mLockTaskPackages.size(); ++i) {
885 pw.println(prefix + " u" + mLockTaskPackages.keyAt(i)
886 + ":" + Arrays.toString(mLockTaskPackages.valueAt(i)));
887 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100888 }
889
890 private String lockTaskModeToString() {
891 switch (mLockTaskModeState) {
892 case LOCK_TASK_MODE_LOCKED:
893 return "LOCKED";
894 case LOCK_TASK_MODE_PINNED:
895 return "PINNED";
896 case LOCK_TASK_MODE_NONE:
897 return "NONE";
898 default: return "unknown=" + mLockTaskModeState;
899 }
900 }
901}