blob: ef2a21d919e155fa67ab07e3b72cde172543642c [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;
Adrian Roos1c8e3c02018-11-20 20:07:55 +010057import android.os.UserHandle;
Benjamin Franza83859f2017-07-03 16:34:14 +010058import android.provider.Settings;
Charles He858f1322017-11-27 17:11:04 -080059import android.telecom.TelecomManager;
Charles Hee078db72017-10-19 18:03:20 +010060import android.util.Pair;
Benjamin Franza83859f2017-07-03 16:34:14 +010061import android.util.Slog;
Charles He520b2832017-09-02 15:27:16 +010062import android.util.SparseArray;
Charles He858f1322017-11-27 17:11:04 -080063import android.util.SparseIntArray;
Benjamin Franza83859f2017-07-03 16:34:14 +010064
65import com.android.internal.annotations.VisibleForTesting;
Tony Mak2bf36912018-03-21 15:45:52 +000066import com.android.internal.policy.IKeyguardDismissCallback;
Benjamin Franza83859f2017-07-03 16:34:14 +010067import com.android.internal.statusbar.IStatusBarService;
68import com.android.internal.widget.LockPatternUtils;
69import com.android.server.LocalServices;
Wale Ogunwale59507092018-10-29 09:00:30 -070070import com.android.server.am.ActivityManagerService;
Benjamin Franza83859f2017-07-03 16:34:14 +010071import com.android.server.statusbar.StatusBarManagerInternal;
Benjamin Franza83859f2017-07-03 16:34:14 +010072
73import java.io.PrintWriter;
74import java.util.ArrayList;
Charles He520b2832017-09-02 15:27:16 +010075import java.util.Arrays;
Benjamin Franza83859f2017-07-03 16:34:14 +010076
77/**
78 * Helper class that deals with all things related to task locking. This includes the screen pinning
79 * mode that can be launched via System UI as well as the fully locked mode that can be achieved
80 * on fully managed devices.
81 *
Wale Ogunwale27c48ae2018-10-25 19:01:01 -070082 * Note: All methods in this class should only be called with the ActivityTaskManagerService lock
83 * held.
Benjamin Franza83859f2017-07-03 16:34:14 +010084 *
85 * @see Activity#startLockTask()
86 * @see Activity#stopLockTask()
87 */
88public class LockTaskController {
Wale Ogunwale98875612018-10-12 07:53:02 -070089 private static final String TAG = TAG_WITH_CLASS_NAME ? "LockTaskController" : TAG_ATM;
Benjamin Franza83859f2017-07-03 16:34:14 +010090 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
91
92 @VisibleForTesting
Charles Hee078db72017-10-19 18:03:20 +010093 static final int STATUS_BAR_MASK_LOCKED = StatusBarManager.DISABLE_MASK
94 & (~StatusBarManager.DISABLE_EXPAND)
95 & (~StatusBarManager.DISABLE_NOTIFICATION_TICKER)
96 & (~StatusBarManager.DISABLE_SYSTEM_INFO)
97 & (~StatusBarManager.DISABLE_BACK);
Benjamin Franza83859f2017-07-03 16:34:14 +010098 @VisibleForTesting
Charles Hee078db72017-10-19 18:03:20 +010099 static final int STATUS_BAR_MASK_PINNED = StatusBarManager.DISABLE_MASK
100 & (~StatusBarManager.DISABLE_BACK)
101 & (~StatusBarManager.DISABLE_HOME)
102 & (~StatusBarManager.DISABLE_RECENT);
103
104 private static final SparseArray<Pair<Integer, Integer>> STATUS_BAR_FLAG_MAP_LOCKED;
105 static {
106 STATUS_BAR_FLAG_MAP_LOCKED = new SparseArray<>();
107
108 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO,
109 new Pair<>(StatusBarManager.DISABLE_CLOCK, StatusBarManager.DISABLE2_SYSTEM_ICONS));
110
111 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS,
112 new Pair<>(StatusBarManager.DISABLE_NOTIFICATION_ICONS
113 | StatusBarManager.DISABLE_NOTIFICATION_ALERTS,
114 StatusBarManager.DISABLE2_NOTIFICATION_SHADE));
115
116 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_HOME,
117 new Pair<>(StatusBarManager.DISABLE_HOME, StatusBarManager.DISABLE2_NONE));
118
Benjamin Franzcaffa772018-02-05 16:36:10 +0000119 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW,
Charles Hee078db72017-10-19 18:03:20 +0100120 new Pair<>(StatusBarManager.DISABLE_RECENT, StatusBarManager.DISABLE2_NONE));
121
122 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS,
123 new Pair<>(StatusBarManager.DISABLE_NONE,
124 StatusBarManager.DISABLE2_GLOBAL_ACTIONS));
125 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100126
127 /** Tag used for disabling of keyguard */
128 private static final String LOCK_TASK_TAG = "Lock-to-App";
129
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100130 private final IBinder mToken = new LockTaskToken();
Benjamin Franza83859f2017-07-03 16:34:14 +0100131 private final ActivityStackSupervisor mSupervisor;
132 private final Context mContext;
133
134 // The following system services cannot be final, because they do not exist when this class
135 // is instantiated during device boot
136 @VisibleForTesting
137 IStatusBarService mStatusBarService;
138 @VisibleForTesting
139 IDevicePolicyManager mDevicePolicyManager;
140 @VisibleForTesting
141 WindowManagerService mWindowManager;
142 @VisibleForTesting
143 LockPatternUtils mLockPatternUtils;
Charles He858f1322017-11-27 17:11:04 -0800144 @VisibleForTesting
145 TelecomManager mTelecomManager;
Benjamin Franza83859f2017-07-03 16:34:14 +0100146
147 /**
Charles Heff9b4dff2017-09-22 10:18:37 +0100148 * The chain of tasks in LockTask mode, in the order of when they first entered LockTask mode.
149 *
150 * The first task in the list, which started the current LockTask session, is called the root
151 * task. It coincides with the Home task in a typical multi-app kiosk deployment. When there are
152 * more than one locked tasks, the root task can't be finished. Nor can it be moved to the back
153 * of the stack by {@link ActivityStack#moveTaskToBackLocked(int)};
154 *
155 * Calling {@link Activity#stopLockTask()} on the root task will finish all tasks but itself in
156 * this list, and the device will exit LockTask mode.
157 *
158 * The list is empty if LockTask is inactive.
Benjamin Franza83859f2017-07-03 16:34:14 +0100159 */
160 private final ArrayList<TaskRecord> mLockTaskModeTasks = new ArrayList<>();
161
162 /**
Charles He520b2832017-09-02 15:27:16 +0100163 * Packages that are allowed to be launched into the lock task mode for each user.
164 */
165 private final SparseArray<String[]> mLockTaskPackages = new SparseArray<>();
166
167 /**
Charles Hee078db72017-10-19 18:03:20 +0100168 * Features that are allowed by DPC to show during LockTask mode.
169 */
Charles He858f1322017-11-27 17:11:04 -0800170 private final SparseIntArray mLockTaskFeatures = new SparseIntArray();
Charles Hee078db72017-10-19 18:03:20 +0100171
172 /**
Benjamin Franza83859f2017-07-03 16:34:14 +0100173 * Store the current lock task mode. Possible values:
174 * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
175 * {@link ActivityManager#LOCK_TASK_MODE_PINNED}
176 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100177 private int mLockTaskModeState = LOCK_TASK_MODE_NONE;
Benjamin Franza83859f2017-07-03 16:34:14 +0100178
179 /**
180 * This is ActivityStackSupervisor's Handler.
181 */
182 private final Handler mHandler;
183
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100184 /**
185 * Stores the user for which we're trying to dismiss the keyguard and then subsequently
186 * disable it.
187 *
188 * Tracking this ensures we don't mistakenly disable the keyguard if we've stopped trying to
189 * between the dismiss request and when it succeeds.
190 *
191 * Must only be accessed from the Handler thread.
192 */
193 private int mPendingDisableFromDismiss = UserHandle.USER_NULL;
194
Benjamin Franza83859f2017-07-03 16:34:14 +0100195 LockTaskController(Context context, ActivityStackSupervisor supervisor,
196 Handler handler) {
197 mContext = context;
198 mSupervisor = supervisor;
199 mHandler = handler;
200 }
201
202 /**
203 * Set the window manager instance used in this class. This is necessary, because the window
204 * manager does not exist during instantiation of this class.
205 */
206 void setWindowManager(WindowManagerService windowManager) {
207 mWindowManager = windowManager;
208 }
209
210 /**
211 * @return the current lock task state. This can be any of
212 * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
213 * {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
214 */
215 int getLockTaskModeState() {
216 return mLockTaskModeState;
217 }
218
219 /**
Charles He520b2832017-09-02 15:27:16 +0100220 * @return whether the given task is locked at the moment. Locked tasks cannot be moved to the
221 * back of the stack.
Benjamin Franza83859f2017-07-03 16:34:14 +0100222 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100223 @VisibleForTesting
224 boolean isTaskLocked(TaskRecord task) {
225 return mLockTaskModeTasks.contains(task);
226 }
227
228 /**
229 * @return {@code true} whether this task first started the current LockTask session.
230 */
231 private boolean isRootTask(TaskRecord task) {
232 return mLockTaskModeTasks.indexOf(task) == 0;
233 }
234
235 /**
236 * @return whether the given activity is blocked from finishing, because it is the only activity
237 * of the last locked task and finishing it would mean that lock task mode is ended illegally.
238 */
239 boolean activityBlockedFromFinish(ActivityRecord activity) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800240 final TaskRecord task = activity.getTaskRecord();
Charles Heff9b4dff2017-09-22 10:18:37 +0100241 if (activity == task.getRootActivity()
242 && activity == task.getTopActivity()
243 && task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV
244 && isRootTask(task)) {
245 Slog.i(TAG, "Not finishing task in lock task mode");
Benjamin Franza83859f2017-07-03 16:34:14 +0100246 showLockTaskToast();
247 return true;
248 }
249 return false;
250 }
251
252 /**
Charles Heff9b4dff2017-09-22 10:18:37 +0100253 * @return whether the given task can be moved to the back of the stack with
254 * {@link ActivityStack#moveTaskToBackLocked(int)}
255 * @see #mLockTaskModeTasks
Benjamin Franza83859f2017-07-03 16:34:14 +0100256 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100257 boolean canMoveTaskToBack(TaskRecord task) {
258 if (isRootTask(task)) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100259 showLockTaskToast();
Charles Heff9b4dff2017-09-22 10:18:37 +0100260 return false;
Benjamin Franza83859f2017-07-03 16:34:14 +0100261 }
Charles Heff9b4dff2017-09-22 10:18:37 +0100262 return true;
Benjamin Franza83859f2017-07-03 16:34:14 +0100263 }
264
265 /**
Charles Hed62f9652017-11-01 10:05:51 +0000266 * @return whether the requested task is allowed to be locked (either whitelisted, or declares
267 * lockTaskMode="always" in the manifest).
268 */
269 boolean isTaskWhitelisted(TaskRecord task) {
270 switch(task.mLockTaskAuth) {
271 case LOCK_TASK_AUTH_WHITELISTED:
272 case LOCK_TASK_AUTH_LAUNCHABLE:
273 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
274 return true;
275 case LOCK_TASK_AUTH_PINNABLE:
276 case LOCK_TASK_AUTH_DONT_LOCK:
277 default:
278 return false;
279 }
280 }
281
282 /**
283 * @return whether the requested task is disallowed to be launched.
Benjamin Franza83859f2017-07-03 16:34:14 +0100284 */
285 boolean isLockTaskModeViolation(TaskRecord task) {
286 return isLockTaskModeViolation(task, false);
287 }
288
289 /**
290 * @param isNewClearTask whether the task would be cleared as part of the operation.
Charles Hed62f9652017-11-01 10:05:51 +0000291 * @return whether the requested task is disallowed to be launched.
Benjamin Franza83859f2017-07-03 16:34:14 +0100292 */
293 boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) {
294 if (isLockTaskModeViolationInternal(task, isNewClearTask)) {
295 showLockTaskToast();
296 return true;
297 }
298 return false;
299 }
300
Benjamin Franz7dcbfb02018-01-16 15:16:16 +0000301 /**
302 * @return the root task of the lock task.
303 */
304 TaskRecord getRootTask() {
305 if (mLockTaskModeTasks.isEmpty()) {
306 return null;
307 }
308 return mLockTaskModeTasks.get(0);
309 }
310
Benjamin Franza83859f2017-07-03 16:34:14 +0100311 private boolean isLockTaskModeViolationInternal(TaskRecord task, boolean isNewClearTask) {
312 // TODO: Double check what's going on here. If the task is already in lock task mode, it's
313 // likely whitelisted, so will return false below.
Charles Heff9b4dff2017-09-22 10:18:37 +0100314 if (isTaskLocked(task) && !isNewClearTask) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100315 // If the task is already at the top and won't be cleared, then allow the operation
316 return false;
317 }
Charles Hed62f9652017-11-01 10:05:51 +0000318
319 // Allow recents activity if enabled by policy
320 if (task.isActivityTypeRecents() && isRecentsAllowed(task.userId)) {
321 return false;
Benjamin Franza83859f2017-07-03 16:34:14 +0100322 }
Charles Hed62f9652017-11-01 10:05:51 +0000323
Charles He858f1322017-11-27 17:11:04 -0800324 // Allow emergency calling when the device is protected by a locked keyguard
325 if (isKeyguardAllowed(task.userId) && isEmergencyCallTask(task)) {
326 return false;
327 }
328
Charles Hed62f9652017-11-01 10:05:51 +0000329 return !(isTaskWhitelisted(task) || mLockTaskModeTasks.isEmpty());
330 }
331
332 private boolean isRecentsAllowed(int userId) {
333 return (getLockTaskFeaturesForUser(userId)
Benjamin Franzcaffa772018-02-05 16:36:10 +0000334 & DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW) != 0;
Benjamin Franza83859f2017-07-03 16:34:14 +0100335 }
336
Charles He858f1322017-11-27 17:11:04 -0800337 private boolean isKeyguardAllowed(int userId) {
338 return (getLockTaskFeaturesForUser(userId)
339 & DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD) != 0;
340 }
341
342 private boolean isEmergencyCallTask(TaskRecord task) {
343 final Intent intent = task.intent;
344 if (intent == null) {
345 return false;
346 }
347
348 // 1. The emergency keypad activity launched on top of the keyguard
349 if (EMERGENCY_DIALER_COMPONENT.equals(intent.getComponent())) {
350 return true;
351 }
352
353 // 2. The intent sent by the keypad, which is handled by Telephony
354 if (ACTION_CALL_EMERGENCY.equals(intent.getAction())) {
355 return true;
356 }
357
358 // 3. Telephony then starts the default package for making the call
359 final TelecomManager tm = getTelecomManager();
360 final String dialerPackage = tm != null ? tm.getSystemDialerPackage() : null;
361 if (dialerPackage != null && dialerPackage.equals(intent.getComponent().getPackageName())) {
362 return true;
363 }
364
365 return false;
366 }
367
Benjamin Franza83859f2017-07-03 16:34:14 +0100368 /**
369 * Stop the current lock task mode.
370 *
Charles Heff9b4dff2017-09-22 10:18:37 +0100371 * This is called by {@link ActivityManagerService} and performs various checks before actually
372 * finishing the locked task.
373 *
374 * @param task the task that requested the end of lock task mode ({@code null} for quitting app
375 * pinning mode)
376 * @param isSystemCaller indicates whether this request comes from the system via
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700377 * {@link ActivityTaskManagerService#stopSystemLockTaskMode()}. If
Charles Heff9b4dff2017-09-22 10:18:37 +0100378 * {@code true}, it means the user intends to stop pinned mode through UI;
379 * otherwise, it's called by an app and we need to stop locked or pinned
380 * mode, subject to checks.
Benjamin Franza83859f2017-07-03 16:34:14 +0100381 * @param callingUid the caller that requested the end of lock task mode.
Charles Heff9b4dff2017-09-22 10:18:37 +0100382 * @throws IllegalArgumentException if the calling task is invalid (e.g., {@code null} or not in
383 * foreground)
Benjamin Franza83859f2017-07-03 16:34:14 +0100384 * @throws SecurityException if the caller is not authorized to stop the lock task mode, i.e. if
385 * they differ from the one that launched lock task mode.
386 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100387 void stopLockTaskMode(@Nullable TaskRecord task, boolean isSystemCaller, int callingUid) {
388 if (mLockTaskModeState == LOCK_TASK_MODE_NONE) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100389 return;
390 }
391
Charles Heff9b4dff2017-09-22 10:18:37 +0100392 if (isSystemCaller) {
393 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
394 clearLockedTasks("stopAppPinning");
395 } else {
396 Slog.e(TAG_LOCKTASK, "Attempted to stop LockTask with isSystemCaller=true");
397 showLockTaskToast();
398 }
399
400 } else {
401 // Ensure calling activity is not null
402 if (task == null) {
403 throw new IllegalArgumentException("can't stop LockTask for null task");
404 }
405
406 // Ensure the same caller for startLockTaskMode and stopLockTaskMode.
407 // It is possible lockTaskMode was started by the system process because
408 // android:lockTaskMode is set to a locking value in the application manifest
409 // instead of the app calling startLockTaskMode. In this case
410 // {@link TaskRecord.mLockTaskUid} will be 0, so we compare the callingUid to the
411 // {@link TaskRecord.effectiveUid} instead. Also caller with
412 // {@link MANAGE_ACTIVITY_STACKS} can stop any lock task.
413 if (callingUid != task.mLockTaskUid
414 && (task.mLockTaskUid != 0 || callingUid != task.effectiveUid)) {
415 throw new SecurityException("Invalid uid, expected " + task.mLockTaskUid
416 + " callingUid=" + callingUid + " effectiveUid=" + task.effectiveUid);
417 }
418
419 // We don't care if it's pinned or locked mode; this will stop it anyways.
420 clearLockedTask(task);
421 }
422 }
423
424 /**
425 * Clear all locked tasks and request the end of LockTask mode.
426 *
Wale Ogunwale59507092018-10-29 09:00:30 -0700427 * This method is called by UserController when starting a new foreground user, and,
Charles Heff9b4dff2017-09-22 10:18:37 +0100428 * unlike {@link #stopLockTaskMode(TaskRecord, boolean, int)}, it doesn't perform the checks.
429 */
430 void clearLockedTasks(String reason) {
431 if (DEBUG_LOCKTASK) Slog.i(TAG_LOCKTASK, "clearLockedTasks: " + reason);
432 if (!mLockTaskModeTasks.isEmpty()) {
433 clearLockedTask(mLockTaskModeTasks.get(0));
434 }
435 }
436
437 /**
438 * Clear one locked task from LockTask mode.
439 *
440 * If the requested task is the root task (see {@link #mLockTaskModeTasks}), then all locked
441 * tasks are cleared. Otherwise, only the requested task is cleared. LockTask mode is stopped
442 * when the last locked task is cleared.
443 *
444 * @param task the task to be cleared from LockTask mode.
445 */
446 void clearLockedTask(final TaskRecord task) {
447 if (task == null || mLockTaskModeTasks.isEmpty()) return;
448
449 if (task == mLockTaskModeTasks.get(0)) {
450 // We're removing the root task while there are other locked tasks. Therefore we should
451 // clear all locked tasks in reverse order.
452 for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx > 0; --taskNdx) {
453 clearLockedTask(mLockTaskModeTasks.get(taskNdx));
454 }
455 }
456
457 removeLockedTask(task);
458 if (mLockTaskModeTasks.isEmpty()) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100459 return;
460 }
Charles Heff9b4dff2017-09-22 10:18:37 +0100461 task.performClearTaskLocked();
Wale Ogunwaled32da472018-11-16 07:19:28 -0800462 mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities();
Benjamin Franza83859f2017-07-03 16:34:14 +0100463 }
464
465 /**
466 * Remove the given task from the locked task list. If this was the last task in the list,
467 * lock task mode is stopped.
468 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100469 private void removeLockedTask(final TaskRecord task) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100470 if (!mLockTaskModeTasks.remove(task)) {
471 return;
472 }
Charles Heff9b4dff2017-09-22 10:18:37 +0100473 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: removed " + task);
Benjamin Franza83859f2017-07-03 16:34:14 +0100474 if (mLockTaskModeTasks.isEmpty()) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100475 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: task=" + task +
476 " last task, reverting locktask mode. Callers=" + Debug.getCallers(3));
477 mHandler.post(() -> performStopLockTask(task.userId));
478 }
479 }
480
Benjamin Franza83859f2017-07-03 16:34:14 +0100481 // This method should only be called on the handler thread
482 private void performStopLockTask(int userId) {
483 // When lock task ends, we enable the status bars.
484 try {
Charles Hee078db72017-10-19 18:03:20 +0100485 setStatusBarState(LOCK_TASK_MODE_NONE, userId);
486 setKeyguardState(LOCK_TASK_MODE_NONE, userId);
487 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
488 lockKeyguardIfNeeded();
Benjamin Franza83859f2017-07-03 16:34:14 +0100489 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100490 if (getDevicePolicyManager() != null) {
491 getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId);
492 }
Charles Hebfe82d12017-10-20 11:59:44 +0100493 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
Matthew Ng9c3bce52018-02-01 22:00:31 +0000494 getStatusBarService().showPinningEnterExitToast(false /* entering */);
Charles Hebfe82d12017-10-20 11:59:44 +0100495 }
Benjamin Franz3662b152018-01-16 17:23:44 +0000496 mWindowManager.onLockTaskStateChanged(LOCK_TASK_MODE_NONE);
Benjamin Franza83859f2017-07-03 16:34:14 +0100497 } catch (RemoteException ex) {
498 throw new RuntimeException(ex);
499 } finally {
500 mLockTaskModeState = LOCK_TASK_MODE_NONE;
501 }
502 }
503
504 /**
Charles Hebfe82d12017-10-20 11:59:44 +0100505 * Show the lock task violation toast. Currently we only show toast for screen pinning mode, and
506 * no-op if the device is in locked mode.
Benjamin Franza83859f2017-07-03 16:34:14 +0100507 */
508 void showLockTaskToast() {
Charles Hebfe82d12017-10-20 11:59:44 +0100509 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
Matthew Ng9c3bce52018-02-01 22:00:31 +0000510 try {
511 getStatusBarService().showPinningEscapeToast();
512 } catch (RemoteException e) {
513 Slog.e(TAG, "Failed to send pinning escape toast", e);
514 }
Charles Hebfe82d12017-10-20 11:59:44 +0100515 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100516 }
517
518 // Starting lock task
519
520 /**
521 * Method to start lock task mode on a given task.
522 *
523 * @param task the task that should be locked.
Charles Heff9b4dff2017-09-22 10:18:37 +0100524 * @param isSystemCaller indicates whether this request was initiated by the system via
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700525 * {@link ActivityTaskManagerService#startSystemLockTaskMode(int)}. If
Charles Heff9b4dff2017-09-22 10:18:37 +0100526 * {@code true}, this intends to start pinned mode; otherwise, we look
527 * at the calling task's mLockTaskAuth to decide which mode to start.
Benjamin Franza83859f2017-07-03 16:34:14 +0100528 * @param callingUid the caller that requested the launch of lock task mode.
529 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100530 void startLockTaskMode(@NonNull TaskRecord task, boolean isSystemCaller, int callingUid) {
531 if (!isSystemCaller) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100532 task.mLockTaskUid = callingUid;
533 if (task.mLockTaskAuth == LOCK_TASK_AUTH_PINNABLE) {
534 // startLockTask() called by app, but app is not part of lock task whitelist. Show
Charles Heff9b4dff2017-09-22 10:18:37 +0100535 // app pinning request. We will come back here with isSystemCaller true.
Benjamin Franza83859f2017-07-03 16:34:14 +0100536 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Mode default, asking user");
537 StatusBarManagerInternal statusBarManager = LocalServices.getService(
538 StatusBarManagerInternal.class);
539 if (statusBarManager != null) {
540 statusBarManager.showScreenPinningRequest(task.taskId);
541 }
542 return;
543 }
544 }
545
546 // System can only initiate screen pinning, not full lock task mode
Charles Heff9b4dff2017-09-22 10:18:37 +0100547 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
548 isSystemCaller ? "Locking pinned" : "Locking fully");
549 setLockTaskMode(task, isSystemCaller ? LOCK_TASK_MODE_PINNED : LOCK_TASK_MODE_LOCKED,
Benjamin Franza83859f2017-07-03 16:34:14 +0100550 "startLockTask", true);
551 }
552
553 /**
554 * Start lock task mode on the given task.
555 * @param lockTaskModeState whether fully locked or pinned mode.
556 * @param andResume whether the task should be brought to foreground as part of the operation.
557 */
558 private void setLockTaskMode(@NonNull TaskRecord task, int lockTaskModeState,
559 String reason, boolean andResume) {
560 // Should have already been checked, but do it again.
561 if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) {
562 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
563 "setLockTaskMode: Can't lock due to auth");
564 return;
565 }
566 if (isLockTaskModeViolation(task)) {
567 Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task.");
568 return;
569 }
570
Bryce Lee1a990e52018-04-23 10:54:11 -0700571 final Intent taskIntent = task.intent;
572 if (mLockTaskModeTasks.isEmpty() && taskIntent != null) {
Charles Hed62f9652017-11-01 10:05:51 +0000573 mSupervisor.mRecentTasks.onLockTaskModeStateChanged(lockTaskModeState, task.userId);
Benjamin Franza83859f2017-07-03 16:34:14 +0100574 // Start lock task on the handler thread
575 mHandler.post(() -> performStartLockTask(
Bryce Lee1a990e52018-04-23 10:54:11 -0700576 taskIntent.getComponent().getPackageName(),
Benjamin Franza83859f2017-07-03 16:34:14 +0100577 task.userId,
578 lockTaskModeState));
579 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100580 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskMode: Locking to " + task +
581 " Callers=" + Debug.getCallers(4));
Charles Heff9b4dff2017-09-22 10:18:37 +0100582
583 if (!mLockTaskModeTasks.contains(task)) {
584 mLockTaskModeTasks.add(task);
585 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100586
587 if (task.mLockTaskUid == -1) {
588 task.mLockTaskUid = task.effectiveUid;
589 }
590
591 if (andResume) {
Wale Ogunwale66e16852017-10-19 13:35:52 -0700592 mSupervisor.findTaskToMoveToFront(task, 0, null, reason,
Benjamin Franza83859f2017-07-03 16:34:14 +0100593 lockTaskModeState != LOCK_TASK_MODE_NONE);
Wale Ogunwaled32da472018-11-16 07:19:28 -0800594 mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities();
lumark588a3e82018-07-20 18:53:54 +0800595 final ActivityStack stack = task.getStack();
596 if (stack != null) {
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800597 stack.getDisplay().mDisplayContent.executeAppTransition();
lumark588a3e82018-07-20 18:53:54 +0800598 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100599 } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
Wale Ogunwale0568aed2017-09-08 13:29:37 -0700600 mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED,
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700601 DEFAULT_DISPLAY, task.getStack(), true /* forceNonResizable */);
Benjamin Franza83859f2017-07-03 16:34:14 +0100602 }
603 }
604
605 // This method should only be called on the handler thread
606 private void performStartLockTask(String packageName, int userId, int lockTaskModeState) {
607 // When lock task starts, we disable the status bars.
608 try {
Charles Hebfe82d12017-10-20 11:59:44 +0100609 if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
Matthew Ng9c3bce52018-02-01 22:00:31 +0000610 getStatusBarService().showPinningEnterExitToast(true /* entering */);
Charles Hebfe82d12017-10-20 11:59:44 +0100611 }
Benjamin Franz3662b152018-01-16 17:23:44 +0000612 mWindowManager.onLockTaskStateChanged(lockTaskModeState);
Benjamin Franza83859f2017-07-03 16:34:14 +0100613 mLockTaskModeState = lockTaskModeState;
Charles Hee078db72017-10-19 18:03:20 +0100614 setStatusBarState(lockTaskModeState, userId);
615 setKeyguardState(lockTaskModeState, userId);
Benjamin Franza83859f2017-07-03 16:34:14 +0100616 if (getDevicePolicyManager() != null) {
617 getDevicePolicyManager().notifyLockTaskModeChanged(true, packageName, userId);
618 }
619 } catch (RemoteException ex) {
620 throw new RuntimeException(ex);
621 }
622 }
623
624 /**
Charles He520b2832017-09-02 15:27:16 +0100625 * Update packages that are allowed to be launched in lock task mode.
626 * @param userId Which user this whitelist is associated with
627 * @param packages The whitelist of packages allowed in lock task mode
628 * @see #mLockTaskPackages
Benjamin Franza83859f2017-07-03 16:34:14 +0100629 */
Charles He520b2832017-09-02 15:27:16 +0100630 void updateLockTaskPackages(int userId, String[] packages) {
631 mLockTaskPackages.put(userId, packages);
632
633 boolean taskChanged = false;
Benjamin Franza83859f2017-07-03 16:34:14 +0100634 for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) {
635 final TaskRecord lockedTask = mLockTaskModeTasks.get(taskNdx);
Charles He520b2832017-09-02 15:27:16 +0100636 final boolean wasWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
637 || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
Benjamin Franza83859f2017-07-03 16:34:14 +0100638 lockedTask.setLockTaskAuth();
Charles He520b2832017-09-02 15:27:16 +0100639 final boolean isWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
640 || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
641
642 if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED
643 || lockedTask.userId != userId
644 || !wasWhitelisted || isWhitelisted) {
645 continue;
Benjamin Franza83859f2017-07-03 16:34:14 +0100646 }
Charles He520b2832017-09-02 15:27:16 +0100647
648 // Terminate locked tasks that have recently lost whitelist authorization.
649 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " +
650 lockedTask + " mLockTaskAuth()=" + lockedTask.lockTaskAuthToString());
651 removeLockedTask(lockedTask);
652 lockedTask.performClearTaskLocked();
653 taskChanged = true;
Benjamin Franza83859f2017-07-03 16:34:14 +0100654 }
655
Wale Ogunwaled32da472018-11-16 07:19:28 -0800656 for (int displayNdx = mSupervisor.mRootActivityContainer.getChildCount() - 1;
657 displayNdx >= 0; --displayNdx) {
658 mSupervisor.mRootActivityContainer.getChildAt(displayNdx).onLockTaskPackagesUpdated();
Benjamin Franza83859f2017-07-03 16:34:14 +0100659 }
Charles He520b2832017-09-02 15:27:16 +0100660
Wale Ogunwaled32da472018-11-16 07:19:28 -0800661 final ActivityRecord r = mSupervisor.mRootActivityContainer.topRunningActivity();
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800662 final TaskRecord task = (r != null) ? r.getTaskRecord() : null;
Charles He520b2832017-09-02 15:27:16 +0100663 if (mLockTaskModeTasks.isEmpty() && task!= null
Benjamin Franza83859f2017-07-03 16:34:14 +0100664 && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
665 // This task must have just been authorized.
666 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK,
667 "onLockTaskPackagesUpdated: starting new locktask task=" + task);
Charles He520b2832017-09-02 15:27:16 +0100668 setLockTaskMode(task, LOCK_TASK_MODE_LOCKED, "package updated", false);
669 taskChanged = true;
Benjamin Franza83859f2017-07-03 16:34:14 +0100670 }
Charles He520b2832017-09-02 15:27:16 +0100671
672 if (taskChanged) {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800673 mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities();
Benjamin Franza83859f2017-07-03 16:34:14 +0100674 }
675 }
676
Charles He520b2832017-09-02 15:27:16 +0100677 boolean isPackageWhitelisted(int userId, String pkg) {
678 if (pkg == null) {
679 return false;
680 }
681 String[] whitelist;
682 whitelist = mLockTaskPackages.get(userId);
683 if (whitelist == null) {
684 return false;
685 }
686 for (String whitelistedPkg : whitelist) {
687 if (pkg.equals(whitelistedPkg)) {
688 return true;
689 }
690 }
691 return false;
692 }
693
Benjamin Franza83859f2017-07-03 16:34:14 +0100694 /**
Charles Hee078db72017-10-19 18:03:20 +0100695 * Update the UI features that are enabled for LockTask mode.
696 * @param userId Which user these feature flags are associated with
697 * @param flags Bitfield of feature flags
698 * @see DevicePolicyManager#setLockTaskFeatures(ComponentName, int)
699 */
700 void updateLockTaskFeatures(int userId, int flags) {
701 int oldFlags = getLockTaskFeaturesForUser(userId);
702 if (flags == oldFlags) {
703 return;
704 }
705
706 mLockTaskFeatures.put(userId, flags);
Charles Heff9b4dff2017-09-22 10:18:37 +0100707 if (!mLockTaskModeTasks.isEmpty() && userId == mLockTaskModeTasks.get(0).userId) {
Charles Hee078db72017-10-19 18:03:20 +0100708 mHandler.post(() -> {
709 if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) {
710 setStatusBarState(mLockTaskModeState, userId);
711 setKeyguardState(mLockTaskModeState, userId);
712 }
713 });
714 }
715 }
716
717 /**
718 * Helper method for configuring the status bar disabled state.
719 * Should only be called on the handler thread to avoid race.
720 */
721 private void setStatusBarState(int lockTaskModeState, int userId) {
722 IStatusBarService statusBar = getStatusBarService();
723 if (statusBar == null) {
724 Slog.e(TAG, "Can't find StatusBarService");
725 return;
726 }
727
728 // Default state, when lockTaskModeState == LOCK_TASK_MODE_NONE
729 int flags1 = StatusBarManager.DISABLE_NONE;
730 int flags2 = StatusBarManager.DISABLE2_NONE;
731
732 if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
733 flags1 = STATUS_BAR_MASK_PINNED;
734
735 } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
736 int lockTaskFeatures = getLockTaskFeaturesForUser(userId);
737 Pair<Integer, Integer> statusBarFlags = getStatusBarDisableFlags(lockTaskFeatures);
738 flags1 = statusBarFlags.first;
739 flags2 = statusBarFlags.second;
740 }
741
742 try {
743 statusBar.disable(flags1, mToken, mContext.getPackageName());
744 statusBar.disable2(flags2, mToken, mContext.getPackageName());
745 } catch (RemoteException e) {
746 Slog.e(TAG, "Failed to set status bar flags", e);
747 }
748 }
749
750 /**
751 * Helper method for configuring the keyguard disabled state.
752 * Should only be called on the handler thread to avoid race.
753 */
754 private void setKeyguardState(int lockTaskModeState, int userId) {
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100755 mPendingDisableFromDismiss = UserHandle.USER_NULL;
Charles Hee078db72017-10-19 18:03:20 +0100756 if (lockTaskModeState == LOCK_TASK_MODE_NONE) {
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100757 mWindowManager.reenableKeyguard(mToken, userId);
Charles Hee078db72017-10-19 18:03:20 +0100758
759 } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
Charles He858f1322017-11-27 17:11:04 -0800760 if (isKeyguardAllowed(userId)) {
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100761 mWindowManager.reenableKeyguard(mToken, userId);
Charles He858f1322017-11-27 17:11:04 -0800762 } else {
Tony Mak2bf36912018-03-21 15:45:52 +0000763 // If keyguard is not secure and it is locked, dismiss the keyguard before
764 // disabling it, which avoids the platform to think the keyguard is still on.
Brad Stenning2bdc21e2019-03-11 14:33:22 -0700765 if (mWindowManager.isKeyguardLocked() && !mWindowManager.isKeyguardSecure(userId)) {
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100766 mPendingDisableFromDismiss = userId;
Tony Mak2bf36912018-03-21 15:45:52 +0000767 mWindowManager.dismissKeyguard(new IKeyguardDismissCallback.Stub() {
768 @Override
769 public void onDismissError() throws RemoteException {
770 Slog.i(TAG, "setKeyguardState: failed to dismiss keyguard");
771 }
772
773 @Override
774 public void onDismissSucceeded() throws RemoteException {
775 mHandler.post(
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100776 () -> {
777 if (mPendingDisableFromDismiss == userId) {
778 mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG,
779 userId);
780 mPendingDisableFromDismiss = UserHandle.USER_NULL;
781 }
782 });
Tony Mak2bf36912018-03-21 15:45:52 +0000783 }
784
785 @Override
786 public void onDismissCancelled() throws RemoteException {
787 Slog.i(TAG, "setKeyguardState: dismiss cancelled");
788 }
789 }, null);
790 } else {
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100791 mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG, userId);
Tony Mak2bf36912018-03-21 15:45:52 +0000792 }
Charles Hee078db72017-10-19 18:03:20 +0100793 }
794
795 } else { // lockTaskModeState == LOCK_TASK_MODE_PINNED
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100796 mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG, userId);
Charles Hee078db72017-10-19 18:03:20 +0100797 }
798 }
799
800 /**
801 * Helper method for locking the device immediately. This may be necessary when the device
802 * leaves the pinned mode.
803 */
804 private void lockKeyguardIfNeeded() {
Jonathan Scott851d4692019-04-29 18:03:58 +0100805 if (shouldLockKeyguard()) {
806 mWindowManager.lockNow(null);
807 mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
808 getLockPatternUtils().requireCredentialEntry(USER_ALL);
809 }
810 }
811
812 private boolean shouldLockKeyguard() {
813 // This functionality should be kept consistent with
814 // com.android.settings.security.ScreenPinningSettings (see b/127605586)
Charles Hee078db72017-10-19 18:03:20 +0100815 try {
Jonathan Scott851d4692019-04-29 18:03:58 +0100816 return Settings.Secure.getIntForUser(
Charles Hee078db72017-10-19 18:03:20 +0100817 mContext.getContentResolver(),
Jonathan Scott851d4692019-04-29 18:03:58 +0100818 Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, USER_CURRENT) != 0;
Charles Hee078db72017-10-19 18:03:20 +0100819 } catch (Settings.SettingNotFoundException e) {
Jonathan Scott851d4692019-04-29 18:03:58 +0100820 // Log to SafetyNet for b/127605586
821 android.util.EventLog.writeEvent(0x534e4554, "127605586", -1, "");
822 return mLockPatternUtils.isSecure(USER_CURRENT);
Charles Hee078db72017-10-19 18:03:20 +0100823 }
824 }
825
826 /**
827 * Translates from LockTask feature flags to StatusBarManager disable and disable2 flags.
828 * @param lockTaskFlags Bitfield of flags as per
829 * {@link DevicePolicyManager#setLockTaskFeatures(ComponentName, int)}
830 * @return A {@link Pair} of {@link StatusBarManager#disable(int)} and
831 * {@link StatusBarManager#disable2(int)} flags
832 */
833 @VisibleForTesting
834 Pair<Integer, Integer> getStatusBarDisableFlags(int lockTaskFlags) {
835 // Everything is disabled by default
836 int flags1 = StatusBarManager.DISABLE_MASK;
837 int flags2 = StatusBarManager.DISABLE2_MASK;
838 for (int i = STATUS_BAR_FLAG_MAP_LOCKED.size() - 1; i >= 0; i--) {
839 Pair<Integer, Integer> statusBarFlags = STATUS_BAR_FLAG_MAP_LOCKED.valueAt(i);
840 if ((STATUS_BAR_FLAG_MAP_LOCKED.keyAt(i) & lockTaskFlags) != 0) {
841 flags1 &= ~statusBarFlags.first;
842 flags2 &= ~statusBarFlags.second;
843 }
844 }
845 // Some flags are not used for LockTask purposes, so we mask them
846 flags1 &= STATUS_BAR_MASK_LOCKED;
847 return new Pair<>(flags1, flags2);
848 }
849
850 /**
851 * Gets the cached value of LockTask feature flags for a specific user.
852 */
853 private int getLockTaskFeaturesForUser(int userId) {
854 return mLockTaskFeatures.get(userId, DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
855 }
856
Benjamin Franza83859f2017-07-03 16:34:14 +0100857 // Should only be called on the handler thread
858 @Nullable
859 private IStatusBarService getStatusBarService() {
860 if (mStatusBarService == null) {
861 mStatusBarService = IStatusBarService.Stub.asInterface(
862 ServiceManager.checkService(STATUS_BAR_SERVICE));
863 if (mStatusBarService == null) {
864 Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE");
865 }
866 }
867 return mStatusBarService;
868 }
869
870 // Should only be called on the handler thread
871 @Nullable
872 private IDevicePolicyManager getDevicePolicyManager() {
873 if (mDevicePolicyManager == null) {
874 mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface(
875 ServiceManager.checkService(DEVICE_POLICY_SERVICE));
876 if (mDevicePolicyManager == null) {
877 Slog.w(TAG, "warning: no DEVICE_POLICY_SERVICE");
878 }
879 }
880 return mDevicePolicyManager;
881 }
882
883 @NonNull
884 private LockPatternUtils getLockPatternUtils() {
885 if (mLockPatternUtils == null) {
886 // We don't preserve the LPU object to save memory
887 return new LockPatternUtils(mContext);
888 }
889 return mLockPatternUtils;
890 }
891
Charles He858f1322017-11-27 17:11:04 -0800892 @Nullable
893 private TelecomManager getTelecomManager() {
894 if (mTelecomManager == null) {
895 // We don't preserve the TelecomManager object to save memory
896 return mContext.getSystemService(TelecomManager.class);
897 }
898 return mTelecomManager;
899 }
900
Benjamin Franza83859f2017-07-03 16:34:14 +0100901 public void dump(PrintWriter pw, String prefix) {
Charles He520b2832017-09-02 15:27:16 +0100902 pw.println(prefix + "LockTaskController");
903 prefix = prefix + " ";
904 pw.println(prefix + "mLockTaskModeState=" + lockTaskModeToString());
905 pw.println(prefix + "mLockTaskModeTasks=");
906 for (int i = 0; i < mLockTaskModeTasks.size(); ++i) {
907 pw.println(prefix + " #" + i + " " + mLockTaskModeTasks.get(i));
908 }
909 pw.println(prefix + "mLockTaskPackages (userId:packages)=");
910 for (int i = 0; i < mLockTaskPackages.size(); ++i) {
911 pw.println(prefix + " u" + mLockTaskPackages.keyAt(i)
912 + ":" + Arrays.toString(mLockTaskPackages.valueAt(i)));
913 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100914 }
915
916 private String lockTaskModeToString() {
917 switch (mLockTaskModeState) {
918 case LOCK_TASK_MODE_LOCKED:
919 return "LOCKED";
920 case LOCK_TASK_MODE_PINNED:
921 return "PINNED";
922 case LOCK_TASK_MODE_NONE:
923 return "NONE";
924 default: return "unknown=" + mLockTaskModeState;
925 }
926 }
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100927
928 /** Marker class for the token used to disable keyguard. */
929 static class LockTaskToken extends Binder {
930 private LockTaskToken() {
931 }
932 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100933}