blob: 892ee717e21f581b3b8cf3b9fb21dcdeef0cb3c9 [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;
Yuhan Zhaof3b3d412020-01-24 23:37:13 +000026import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
27import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
Benjamin Franza83859f2017-07-03 16:34:14 +010028import static android.os.UserHandle.USER_ALL;
Amith Yamasani7cbbf2222017-08-30 14:22:37 -070029import static android.os.UserHandle.USER_CURRENT;
Charles He858f1322017-11-27 17:11:04 -080030import static android.telecom.TelecomManager.EMERGENCY_DIALER_COMPONENT;
Charles He520b2832017-09-02 15:27:16 +010031
Wale Ogunwale59507092018-10-29 09:00:30 -070032import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
33import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
34import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
35import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Louis Changcdec0802019-11-11 11:45:07 +080036import static com.android.server.wm.Task.LOCK_TASK_AUTH_DONT_LOCK;
37import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE;
38import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
39import static com.android.server.wm.Task.LOCK_TASK_AUTH_PINNABLE;
40import static com.android.server.wm.Task.LOCK_TASK_AUTH_WHITELISTED;
Benjamin Franza83859f2017-07-03 16:34:14 +010041
42import android.annotation.NonNull;
43import android.annotation.Nullable;
44import android.app.Activity;
45import android.app.ActivityManager;
Charles Hee078db72017-10-19 18:03:20 +010046import android.app.StatusBarManager;
47import android.app.admin.DevicePolicyManager;
Benjamin Franza83859f2017-07-03 16:34:14 +010048import android.app.admin.IDevicePolicyManager;
Charles Hee078db72017-10-19 18:03:20 +010049import android.content.ComponentName;
Benjamin Franza83859f2017-07-03 16:34:14 +010050import android.content.Context;
Charles He858f1322017-11-27 17:11:04 -080051import android.content.Intent;
Benjamin Franza83859f2017-07-03 16:34:14 +010052import android.os.Binder;
53import android.os.Debug;
54import android.os.Handler;
55import android.os.IBinder;
56import android.os.RemoteException;
57import android.os.ServiceManager;
Adrian Roos1c8e3c02018-11-20 20:07:55 +010058import android.os.UserHandle;
Benjamin Franza83859f2017-07-03 16:34:14 +010059import android.provider.Settings;
Charles He858f1322017-11-27 17:11:04 -080060import android.telecom.TelecomManager;
Charles Hee078db72017-10-19 18:03:20 +010061import android.util.Pair;
Benjamin Franza83859f2017-07-03 16:34:14 +010062import android.util.Slog;
Charles He520b2832017-09-02 15:27:16 +010063import android.util.SparseArray;
Charles He858f1322017-11-27 17:11:04 -080064import android.util.SparseIntArray;
Benjamin Franza83859f2017-07-03 16:34:14 +010065
66import com.android.internal.annotations.VisibleForTesting;
Tony Mak2bf36912018-03-21 15:45:52 +000067import com.android.internal.policy.IKeyguardDismissCallback;
Benjamin Franza83859f2017-07-03 16:34:14 +010068import com.android.internal.statusbar.IStatusBarService;
69import com.android.internal.widget.LockPatternUtils;
70import com.android.server.LocalServices;
Wale Ogunwale59507092018-10-29 09:00:30 -070071import com.android.server.am.ActivityManagerService;
Benjamin Franza83859f2017-07-03 16:34:14 +010072import com.android.server.statusbar.StatusBarManagerInternal;
Benjamin Franza83859f2017-07-03 16:34:14 +010073
74import java.io.PrintWriter;
75import java.util.ArrayList;
Charles He520b2832017-09-02 15:27:16 +010076import java.util.Arrays;
Benjamin Franza83859f2017-07-03 16:34:14 +010077
78/**
79 * Helper class that deals with all things related to task locking. This includes the screen pinning
80 * mode that can be launched via System UI as well as the fully locked mode that can be achieved
81 * on fully managed devices.
82 *
Wale Ogunwale27c48ae2018-10-25 19:01:01 -070083 * Note: All methods in this class should only be called with the ActivityTaskManagerService lock
84 * held.
Benjamin Franza83859f2017-07-03 16:34:14 +010085 *
86 * @see Activity#startLockTask()
87 * @see Activity#stopLockTask()
88 */
89public class LockTaskController {
Wale Ogunwale98875612018-10-12 07:53:02 -070090 private static final String TAG = TAG_WITH_CLASS_NAME ? "LockTaskController" : TAG_ATM;
Benjamin Franza83859f2017-07-03 16:34:14 +010091 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
92
93 @VisibleForTesting
Charles Hee078db72017-10-19 18:03:20 +010094 static final int STATUS_BAR_MASK_LOCKED = StatusBarManager.DISABLE_MASK
95 & (~StatusBarManager.DISABLE_EXPAND)
96 & (~StatusBarManager.DISABLE_NOTIFICATION_TICKER)
97 & (~StatusBarManager.DISABLE_SYSTEM_INFO)
98 & (~StatusBarManager.DISABLE_BACK);
Benjamin Franza83859f2017-07-03 16:34:14 +010099 @VisibleForTesting
Charles Hee078db72017-10-19 18:03:20 +0100100 static final int STATUS_BAR_MASK_PINNED = StatusBarManager.DISABLE_MASK
101 & (~StatusBarManager.DISABLE_BACK)
102 & (~StatusBarManager.DISABLE_HOME)
103 & (~StatusBarManager.DISABLE_RECENT);
104
105 private static final SparseArray<Pair<Integer, Integer>> STATUS_BAR_FLAG_MAP_LOCKED;
106 static {
107 STATUS_BAR_FLAG_MAP_LOCKED = new SparseArray<>();
108
109 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO,
110 new Pair<>(StatusBarManager.DISABLE_CLOCK, StatusBarManager.DISABLE2_SYSTEM_ICONS));
111
112 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS,
113 new Pair<>(StatusBarManager.DISABLE_NOTIFICATION_ICONS
114 | StatusBarManager.DISABLE_NOTIFICATION_ALERTS,
115 StatusBarManager.DISABLE2_NOTIFICATION_SHADE));
116
117 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_HOME,
118 new Pair<>(StatusBarManager.DISABLE_HOME, StatusBarManager.DISABLE2_NONE));
119
Benjamin Franzcaffa772018-02-05 16:36:10 +0000120 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW,
Charles Hee078db72017-10-19 18:03:20 +0100121 new Pair<>(StatusBarManager.DISABLE_RECENT, StatusBarManager.DISABLE2_NONE));
122
123 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS,
124 new Pair<>(StatusBarManager.DISABLE_NONE,
125 StatusBarManager.DISABLE2_GLOBAL_ACTIONS));
126 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100127
128 /** Tag used for disabling of keyguard */
129 private static final String LOCK_TASK_TAG = "Lock-to-App";
130
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100131 private final IBinder mToken = new LockTaskToken();
Benjamin Franza83859f2017-07-03 16:34:14 +0100132 private final ActivityStackSupervisor mSupervisor;
133 private final Context mContext;
134
135 // The following system services cannot be final, because they do not exist when this class
136 // is instantiated during device boot
137 @VisibleForTesting
138 IStatusBarService mStatusBarService;
139 @VisibleForTesting
140 IDevicePolicyManager mDevicePolicyManager;
141 @VisibleForTesting
142 WindowManagerService mWindowManager;
143 @VisibleForTesting
144 LockPatternUtils mLockPatternUtils;
Charles He858f1322017-11-27 17:11:04 -0800145 @VisibleForTesting
146 TelecomManager mTelecomManager;
Benjamin Franza83859f2017-07-03 16:34:14 +0100147
148 /**
Charles Heff9b4dff2017-09-22 10:18:37 +0100149 * The chain of tasks in LockTask mode, in the order of when they first entered LockTask mode.
150 *
151 * The first task in the list, which started the current LockTask session, is called the root
152 * task. It coincides with the Home task in a typical multi-app kiosk deployment. When there are
153 * more than one locked tasks, the root task can't be finished. Nor can it be moved to the back
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900154 * of the stack by {@link ActivityStack#moveTaskToBack(Task)};
Charles Heff9b4dff2017-09-22 10:18:37 +0100155 *
156 * Calling {@link Activity#stopLockTask()} on the root task will finish all tasks but itself in
157 * this list, and the device will exit LockTask mode.
158 *
159 * The list is empty if LockTask is inactive.
Benjamin Franza83859f2017-07-03 16:34:14 +0100160 */
Louis Changcdec0802019-11-11 11:45:07 +0800161 private final ArrayList<Task> mLockTaskModeTasks = new ArrayList<>();
Benjamin Franza83859f2017-07-03 16:34:14 +0100162
163 /**
Charles He520b2832017-09-02 15:27:16 +0100164 * Packages that are allowed to be launched into the lock task mode for each user.
165 */
166 private final SparseArray<String[]> mLockTaskPackages = new SparseArray<>();
167
168 /**
Charles Hee078db72017-10-19 18:03:20 +0100169 * Features that are allowed by DPC to show during LockTask mode.
170 */
Charles He858f1322017-11-27 17:11:04 -0800171 private final SparseIntArray mLockTaskFeatures = new SparseIntArray();
Charles Hee078db72017-10-19 18:03:20 +0100172
173 /**
Benjamin Franza83859f2017-07-03 16:34:14 +0100174 * Store the current lock task mode. Possible values:
175 * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
176 * {@link ActivityManager#LOCK_TASK_MODE_PINNED}
177 */
Hongwei Wangd8163292020-06-20 00:19:34 -0700178 private volatile int mLockTaskModeState = LOCK_TASK_MODE_NONE;
Benjamin Franza83859f2017-07-03 16:34:14 +0100179
180 /**
181 * This is ActivityStackSupervisor's Handler.
182 */
183 private final Handler mHandler;
184
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100185 /**
186 * Stores the user for which we're trying to dismiss the keyguard and then subsequently
187 * disable it.
188 *
189 * Tracking this ensures we don't mistakenly disable the keyguard if we've stopped trying to
190 * between the dismiss request and when it succeeds.
191 *
192 * Must only be accessed from the Handler thread.
193 */
194 private int mPendingDisableFromDismiss = UserHandle.USER_NULL;
195
Benjamin Franza83859f2017-07-03 16:34:14 +0100196 LockTaskController(Context context, ActivityStackSupervisor supervisor,
197 Handler handler) {
198 mContext = context;
199 mSupervisor = supervisor;
200 mHandler = handler;
201 }
202
203 /**
204 * Set the window manager instance used in this class. This is necessary, because the window
205 * manager does not exist during instantiation of this class.
206 */
207 void setWindowManager(WindowManagerService windowManager) {
208 mWindowManager = windowManager;
209 }
210
211 /**
212 * @return the current lock task state. This can be any of
213 * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
214 * {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
215 */
216 int getLockTaskModeState() {
217 return mLockTaskModeState;
218 }
219
220 /**
Charles He520b2832017-09-02 15:27:16 +0100221 * @return whether the given task is locked at the moment. Locked tasks cannot be moved to the
222 * back of the stack.
Benjamin Franza83859f2017-07-03 16:34:14 +0100223 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100224 @VisibleForTesting
Louis Changcdec0802019-11-11 11:45:07 +0800225 boolean isTaskLocked(Task task) {
Charles Heff9b4dff2017-09-22 10:18:37 +0100226 return mLockTaskModeTasks.contains(task);
227 }
228
229 /**
230 * @return {@code true} whether this task first started the current LockTask session.
231 */
Louis Changcdec0802019-11-11 11:45:07 +0800232 private boolean isRootTask(Task task) {
Charles Heff9b4dff2017-09-22 10:18:37 +0100233 return mLockTaskModeTasks.indexOf(task) == 0;
234 }
235
236 /**
237 * @return whether the given activity is blocked from finishing, because it is the only activity
238 * of the last locked task and finishing it would mean that lock task mode is ended illegally.
239 */
240 boolean activityBlockedFromFinish(ActivityRecord activity) {
Louis Changcdec0802019-11-11 11:45:07 +0800241 final Task task = activity.getTask();
Charles Heff9b4dff2017-09-22 10:18:37 +0100242 if (activity == task.getRootActivity()
Wale Ogunwale21e06482019-11-18 05:14:15 -0800243 && activity == task.getTopNonFinishingActivity()
Charles Heff9b4dff2017-09-22 10:18:37 +0100244 && task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV
245 && isRootTask(task)) {
246 Slog.i(TAG, "Not finishing task in lock task mode");
Benjamin Franza83859f2017-07-03 16:34:14 +0100247 showLockTaskToast();
248 return true;
249 }
250 return false;
251 }
252
253 /**
Charles Heff9b4dff2017-09-22 10:18:37 +0100254 * @return whether the given task can be moved to the back of the stack with
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900255 * {@link ActivityStack#moveTaskToBack(Task)}
Charles Heff9b4dff2017-09-22 10:18:37 +0100256 * @see #mLockTaskModeTasks
Benjamin Franza83859f2017-07-03 16:34:14 +0100257 */
Louis Changcdec0802019-11-11 11:45:07 +0800258 boolean canMoveTaskToBack(Task task) {
Charles Heff9b4dff2017-09-22 10:18:37 +0100259 if (isRootTask(task)) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100260 showLockTaskToast();
Charles Heff9b4dff2017-09-22 10:18:37 +0100261 return false;
Benjamin Franza83859f2017-07-03 16:34:14 +0100262 }
Charles Heff9b4dff2017-09-22 10:18:37 +0100263 return true;
Benjamin Franza83859f2017-07-03 16:34:14 +0100264 }
265
266 /**
Charles Hed62f9652017-11-01 10:05:51 +0000267 * @return whether the requested task is allowed to be locked (either whitelisted, or declares
268 * lockTaskMode="always" in the manifest).
269 */
Louis Changcdec0802019-11-11 11:45:07 +0800270 boolean isTaskWhitelisted(Task task) {
Charles Hed62f9652017-11-01 10:05:51 +0000271 switch(task.mLockTaskAuth) {
272 case LOCK_TASK_AUTH_WHITELISTED:
273 case LOCK_TASK_AUTH_LAUNCHABLE:
274 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
275 return true;
276 case LOCK_TASK_AUTH_PINNABLE:
277 case LOCK_TASK_AUTH_DONT_LOCK:
278 default:
279 return false;
280 }
281 }
282
283 /**
284 * @return whether the requested task is disallowed to be launched.
Benjamin Franza83859f2017-07-03 16:34:14 +0100285 */
Louis Changcdec0802019-11-11 11:45:07 +0800286 boolean isLockTaskModeViolation(Task task) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100287 return isLockTaskModeViolation(task, false);
288 }
289
290 /**
291 * @param isNewClearTask whether the task would be cleared as part of the operation.
Charles Hed62f9652017-11-01 10:05:51 +0000292 * @return whether the requested task is disallowed to be launched.
Benjamin Franza83859f2017-07-03 16:34:14 +0100293 */
Louis Changcdec0802019-11-11 11:45:07 +0800294 boolean isLockTaskModeViolation(Task task, boolean isNewClearTask) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100295 if (isLockTaskModeViolationInternal(task, isNewClearTask)) {
296 showLockTaskToast();
297 return true;
298 }
299 return false;
300 }
301
Benjamin Franz7dcbfb02018-01-16 15:16:16 +0000302 /**
303 * @return the root task of the lock task.
304 */
Louis Changcdec0802019-11-11 11:45:07 +0800305 Task getRootTask() {
Benjamin Franz7dcbfb02018-01-16 15:16:16 +0000306 if (mLockTaskModeTasks.isEmpty()) {
307 return null;
308 }
309 return mLockTaskModeTasks.get(0);
310 }
311
Louis Changcdec0802019-11-11 11:45:07 +0800312 private boolean isLockTaskModeViolationInternal(Task task, boolean isNewClearTask) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100313 // TODO: Double check what's going on here. If the task is already in lock task mode, it's
314 // likely whitelisted, so will return false below.
Charles Heff9b4dff2017-09-22 10:18:37 +0100315 if (isTaskLocked(task) && !isNewClearTask) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100316 // If the task is already at the top and won't be cleared, then allow the operation
317 return false;
318 }
Charles Hed62f9652017-11-01 10:05:51 +0000319
320 // Allow recents activity if enabled by policy
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700321 if (task.isActivityTypeRecents() && isRecentsAllowed(task.mUserId)) {
Charles Hed62f9652017-11-01 10:05:51 +0000322 return false;
Benjamin Franza83859f2017-07-03 16:34:14 +0100323 }
Charles Hed62f9652017-11-01 10:05:51 +0000324
Charles He858f1322017-11-27 17:11:04 -0800325 // Allow emergency calling when the device is protected by a locked keyguard
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700326 if (isKeyguardAllowed(task.mUserId) && isEmergencyCallTask(task)) {
Charles He858f1322017-11-27 17:11:04 -0800327 return false;
328 }
329
Charles Hed62f9652017-11-01 10:05:51 +0000330 return !(isTaskWhitelisted(task) || mLockTaskModeTasks.isEmpty());
331 }
332
333 private boolean isRecentsAllowed(int userId) {
334 return (getLockTaskFeaturesForUser(userId)
Benjamin Franzcaffa772018-02-05 16:36:10 +0000335 & DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW) != 0;
Benjamin Franza83859f2017-07-03 16:34:14 +0100336 }
337
Charles He858f1322017-11-27 17:11:04 -0800338 private boolean isKeyguardAllowed(int userId) {
339 return (getLockTaskFeaturesForUser(userId)
340 & DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD) != 0;
341 }
342
Yuhan Zhaof3b3d412020-01-24 23:37:13 +0000343 private boolean isBlockingInTaskEnabled(int userId) {
344 return (getLockTaskFeaturesForUser(userId)
345 & DevicePolicyManager.LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK) != 0;
346 }
347
348 boolean isActivityAllowed(int userId, String packageName, int lockTaskLaunchMode) {
349 if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED || !isBlockingInTaskEnabled(userId)) {
350 return true;
351 }
352 switch (lockTaskLaunchMode) {
353 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
354 return true;
355 case LOCK_TASK_LAUNCH_MODE_NEVER:
356 return false;
357 default:
358 }
359 return isPackageWhitelisted(userId, packageName);
360 }
361
Louis Changcdec0802019-11-11 11:45:07 +0800362 private boolean isEmergencyCallTask(Task task) {
Charles He858f1322017-11-27 17:11:04 -0800363 final Intent intent = task.intent;
364 if (intent == null) {
365 return false;
366 }
367
368 // 1. The emergency keypad activity launched on top of the keyguard
369 if (EMERGENCY_DIALER_COMPONENT.equals(intent.getComponent())) {
370 return true;
371 }
372
373 // 2. The intent sent by the keypad, which is handled by Telephony
374 if (ACTION_CALL_EMERGENCY.equals(intent.getAction())) {
375 return true;
376 }
377
378 // 3. Telephony then starts the default package for making the call
379 final TelecomManager tm = getTelecomManager();
380 final String dialerPackage = tm != null ? tm.getSystemDialerPackage() : null;
381 if (dialerPackage != null && dialerPackage.equals(intent.getComponent().getPackageName())) {
382 return true;
383 }
384
385 return false;
386 }
387
Benjamin Franza83859f2017-07-03 16:34:14 +0100388 /**
389 * Stop the current lock task mode.
390 *
Charles Heff9b4dff2017-09-22 10:18:37 +0100391 * This is called by {@link ActivityManagerService} and performs various checks before actually
392 * finishing the locked task.
393 *
394 * @param task the task that requested the end of lock task mode ({@code null} for quitting app
395 * pinning mode)
396 * @param isSystemCaller indicates whether this request comes from the system via
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700397 * {@link ActivityTaskManagerService#stopSystemLockTaskMode()}. If
Charles Heff9b4dff2017-09-22 10:18:37 +0100398 * {@code true}, it means the user intends to stop pinned mode through UI;
399 * otherwise, it's called by an app and we need to stop locked or pinned
400 * mode, subject to checks.
Benjamin Franza83859f2017-07-03 16:34:14 +0100401 * @param callingUid the caller that requested the end of lock task mode.
Charles Heff9b4dff2017-09-22 10:18:37 +0100402 * @throws IllegalArgumentException if the calling task is invalid (e.g., {@code null} or not in
403 * foreground)
Benjamin Franza83859f2017-07-03 16:34:14 +0100404 * @throws SecurityException if the caller is not authorized to stop the lock task mode, i.e. if
405 * they differ from the one that launched lock task mode.
406 */
Louis Changcdec0802019-11-11 11:45:07 +0800407 void stopLockTaskMode(@Nullable Task task, boolean isSystemCaller, int callingUid) {
Charles Heff9b4dff2017-09-22 10:18:37 +0100408 if (mLockTaskModeState == LOCK_TASK_MODE_NONE) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100409 return;
410 }
411
Charles Heff9b4dff2017-09-22 10:18:37 +0100412 if (isSystemCaller) {
413 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
414 clearLockedTasks("stopAppPinning");
415 } else {
416 Slog.e(TAG_LOCKTASK, "Attempted to stop LockTask with isSystemCaller=true");
417 showLockTaskToast();
418 }
419
420 } else {
421 // Ensure calling activity is not null
422 if (task == null) {
423 throw new IllegalArgumentException("can't stop LockTask for null task");
424 }
425
426 // Ensure the same caller for startLockTaskMode and stopLockTaskMode.
427 // It is possible lockTaskMode was started by the system process because
428 // android:lockTaskMode is set to a locking value in the application manifest
429 // instead of the app calling startLockTaskMode. In this case
Louis Changcdec0802019-11-11 11:45:07 +0800430 // {@link Task.mLockTaskUid} will be 0, so we compare the callingUid to the
431 // {@link Task.effectiveUid} instead. Also caller with
Charles Heff9b4dff2017-09-22 10:18:37 +0100432 // {@link MANAGE_ACTIVITY_STACKS} can stop any lock task.
433 if (callingUid != task.mLockTaskUid
434 && (task.mLockTaskUid != 0 || callingUid != task.effectiveUid)) {
435 throw new SecurityException("Invalid uid, expected " + task.mLockTaskUid
436 + " callingUid=" + callingUid + " effectiveUid=" + task.effectiveUid);
437 }
438
439 // We don't care if it's pinned or locked mode; this will stop it anyways.
440 clearLockedTask(task);
441 }
442 }
443
444 /**
445 * Clear all locked tasks and request the end of LockTask mode.
446 *
Wale Ogunwale59507092018-10-29 09:00:30 -0700447 * This method is called by UserController when starting a new foreground user, and,
Louis Changcdec0802019-11-11 11:45:07 +0800448 * unlike {@link #stopLockTaskMode(Task, boolean, int)}, it doesn't perform the checks.
Charles Heff9b4dff2017-09-22 10:18:37 +0100449 */
450 void clearLockedTasks(String reason) {
451 if (DEBUG_LOCKTASK) Slog.i(TAG_LOCKTASK, "clearLockedTasks: " + reason);
452 if (!mLockTaskModeTasks.isEmpty()) {
453 clearLockedTask(mLockTaskModeTasks.get(0));
454 }
455 }
456
457 /**
458 * Clear one locked task from LockTask mode.
459 *
460 * If the requested task is the root task (see {@link #mLockTaskModeTasks}), then all locked
461 * tasks are cleared. Otherwise, only the requested task is cleared. LockTask mode is stopped
462 * when the last locked task is cleared.
463 *
464 * @param task the task to be cleared from LockTask mode.
465 */
Louis Changcdec0802019-11-11 11:45:07 +0800466 void clearLockedTask(final Task task) {
Charles Heff9b4dff2017-09-22 10:18:37 +0100467 if (task == null || mLockTaskModeTasks.isEmpty()) return;
468
469 if (task == mLockTaskModeTasks.get(0)) {
470 // We're removing the root task while there are other locked tasks. Therefore we should
471 // clear all locked tasks in reverse order.
472 for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx > 0; --taskNdx) {
473 clearLockedTask(mLockTaskModeTasks.get(taskNdx));
474 }
475 }
476
477 removeLockedTask(task);
478 if (mLockTaskModeTasks.isEmpty()) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100479 return;
480 }
Charles Heff9b4dff2017-09-22 10:18:37 +0100481 task.performClearTaskLocked();
Louis Chang149d5c82019-12-30 09:47:39 +0800482 mSupervisor.mRootWindowContainer.resumeFocusedStacksTopActivities();
Benjamin Franza83859f2017-07-03 16:34:14 +0100483 }
484
485 /**
486 * Remove the given task from the locked task list. If this was the last task in the list,
487 * lock task mode is stopped.
488 */
Louis Changcdec0802019-11-11 11:45:07 +0800489 private void removeLockedTask(final Task task) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100490 if (!mLockTaskModeTasks.remove(task)) {
491 return;
492 }
Charles Heff9b4dff2017-09-22 10:18:37 +0100493 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: removed " + task);
Benjamin Franza83859f2017-07-03 16:34:14 +0100494 if (mLockTaskModeTasks.isEmpty()) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100495 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: task=" + task +
496 " last task, reverting locktask mode. Callers=" + Debug.getCallers(3));
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700497 mHandler.post(() -> performStopLockTask(task.mUserId));
Benjamin Franza83859f2017-07-03 16:34:14 +0100498 }
499 }
500
Benjamin Franza83859f2017-07-03 16:34:14 +0100501 // This method should only be called on the handler thread
502 private void performStopLockTask(int userId) {
Hongwei Wangd8163292020-06-20 00:19:34 -0700503 // Update the internal mLockTaskModeState early to avoid the scenario that SysUI queries
504 // mLockTaskModeState (from setStatusBarState) and gets staled state.
505 // TODO: revisit this approach.
506 // The race condition raised above can be addressed by moving this function out of handler
507 // thread, which makes it guarded by ATMS#mGlobalLock as ATMS#getLockTaskModeState.
508 final int oldLockTaskModeState = mLockTaskModeState;
509 mLockTaskModeState = LOCK_TASK_MODE_NONE;
Benjamin Franza83859f2017-07-03 16:34:14 +0100510 // When lock task ends, we enable the status bars.
511 try {
Hongwei Wangd8163292020-06-20 00:19:34 -0700512 setStatusBarState(mLockTaskModeState, userId);
513 setKeyguardState(mLockTaskModeState, userId);
514 if (oldLockTaskModeState == LOCK_TASK_MODE_PINNED) {
Charles Hee078db72017-10-19 18:03:20 +0100515 lockKeyguardIfNeeded();
Benjamin Franza83859f2017-07-03 16:34:14 +0100516 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100517 if (getDevicePolicyManager() != null) {
518 getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId);
519 }
Hongwei Wangd8163292020-06-20 00:19:34 -0700520 if (oldLockTaskModeState == LOCK_TASK_MODE_PINNED) {
Matthew Ng9c3bce52018-02-01 22:00:31 +0000521 getStatusBarService().showPinningEnterExitToast(false /* entering */);
Charles Hebfe82d12017-10-20 11:59:44 +0100522 }
Hongwei Wangd8163292020-06-20 00:19:34 -0700523 mWindowManager.onLockTaskStateChanged(mLockTaskModeState);
Benjamin Franza83859f2017-07-03 16:34:14 +0100524 } catch (RemoteException ex) {
525 throw new RuntimeException(ex);
Benjamin Franza83859f2017-07-03 16:34:14 +0100526 }
527 }
528
529 /**
Charles Hebfe82d12017-10-20 11:59:44 +0100530 * Show the lock task violation toast. Currently we only show toast for screen pinning mode, and
531 * no-op if the device is in locked mode.
Benjamin Franza83859f2017-07-03 16:34:14 +0100532 */
533 void showLockTaskToast() {
Charles Hebfe82d12017-10-20 11:59:44 +0100534 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
Matthew Ng9c3bce52018-02-01 22:00:31 +0000535 try {
536 getStatusBarService().showPinningEscapeToast();
537 } catch (RemoteException e) {
538 Slog.e(TAG, "Failed to send pinning escape toast", e);
539 }
Charles Hebfe82d12017-10-20 11:59:44 +0100540 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100541 }
542
543 // Starting lock task
544
545 /**
546 * Method to start lock task mode on a given task.
547 *
548 * @param task the task that should be locked.
Charles Heff9b4dff2017-09-22 10:18:37 +0100549 * @param isSystemCaller indicates whether this request was initiated by the system via
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700550 * {@link ActivityTaskManagerService#startSystemLockTaskMode(int)}. If
Charles Heff9b4dff2017-09-22 10:18:37 +0100551 * {@code true}, this intends to start pinned mode; otherwise, we look
552 * at the calling task's mLockTaskAuth to decide which mode to start.
Benjamin Franza83859f2017-07-03 16:34:14 +0100553 * @param callingUid the caller that requested the launch of lock task mode.
554 */
Louis Changcdec0802019-11-11 11:45:07 +0800555 void startLockTaskMode(@NonNull Task task, boolean isSystemCaller, int callingUid) {
Charles Heff9b4dff2017-09-22 10:18:37 +0100556 if (!isSystemCaller) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100557 task.mLockTaskUid = callingUid;
558 if (task.mLockTaskAuth == LOCK_TASK_AUTH_PINNABLE) {
559 // startLockTask() called by app, but app is not part of lock task whitelist. Show
Charles Heff9b4dff2017-09-22 10:18:37 +0100560 // app pinning request. We will come back here with isSystemCaller true.
Benjamin Franza83859f2017-07-03 16:34:14 +0100561 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Mode default, asking user");
562 StatusBarManagerInternal statusBarManager = LocalServices.getService(
563 StatusBarManagerInternal.class);
564 if (statusBarManager != null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700565 statusBarManager.showScreenPinningRequest(task.mTaskId);
Benjamin Franza83859f2017-07-03 16:34:14 +0100566 }
567 return;
568 }
569 }
570
571 // System can only initiate screen pinning, not full lock task mode
Charles Heff9b4dff2017-09-22 10:18:37 +0100572 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
573 isSystemCaller ? "Locking pinned" : "Locking fully");
574 setLockTaskMode(task, isSystemCaller ? LOCK_TASK_MODE_PINNED : LOCK_TASK_MODE_LOCKED,
Benjamin Franza83859f2017-07-03 16:34:14 +0100575 "startLockTask", true);
576 }
577
578 /**
579 * Start lock task mode on the given task.
580 * @param lockTaskModeState whether fully locked or pinned mode.
581 * @param andResume whether the task should be brought to foreground as part of the operation.
582 */
Louis Changcdec0802019-11-11 11:45:07 +0800583 private void setLockTaskMode(@NonNull Task task, int lockTaskModeState,
Benjamin Franza83859f2017-07-03 16:34:14 +0100584 String reason, boolean andResume) {
585 // Should have already been checked, but do it again.
586 if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) {
587 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
588 "setLockTaskMode: Can't lock due to auth");
589 return;
590 }
591 if (isLockTaskModeViolation(task)) {
592 Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task.");
593 return;
594 }
595
Bryce Lee1a990e52018-04-23 10:54:11 -0700596 final Intent taskIntent = task.intent;
597 if (mLockTaskModeTasks.isEmpty() && taskIntent != null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700598 mSupervisor.mRecentTasks.onLockTaskModeStateChanged(lockTaskModeState, task.mUserId);
Benjamin Franza83859f2017-07-03 16:34:14 +0100599 // Start lock task on the handler thread
600 mHandler.post(() -> performStartLockTask(
Bryce Lee1a990e52018-04-23 10:54:11 -0700601 taskIntent.getComponent().getPackageName(),
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700602 task.mUserId,
Benjamin Franza83859f2017-07-03 16:34:14 +0100603 lockTaskModeState));
604 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100605 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskMode: Locking to " + task +
606 " Callers=" + Debug.getCallers(4));
Charles Heff9b4dff2017-09-22 10:18:37 +0100607
608 if (!mLockTaskModeTasks.contains(task)) {
609 mLockTaskModeTasks.add(task);
610 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100611
612 if (task.mLockTaskUid == -1) {
613 task.mLockTaskUid = task.effectiveUid;
614 }
615
616 if (andResume) {
Wale Ogunwale66e16852017-10-19 13:35:52 -0700617 mSupervisor.findTaskToMoveToFront(task, 0, null, reason,
Benjamin Franza83859f2017-07-03 16:34:14 +0100618 lockTaskModeState != LOCK_TASK_MODE_NONE);
Louis Chang149d5c82019-12-30 09:47:39 +0800619 mSupervisor.mRootWindowContainer.resumeFocusedStacksTopActivities();
lumark588a3e82018-07-20 18:53:54 +0800620 final ActivityStack stack = task.getStack();
621 if (stack != null) {
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800622 stack.getDisplay().mDisplayContent.executeAppTransition();
lumark588a3e82018-07-20 18:53:54 +0800623 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100624 } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
Wale Ogunwale0568aed2017-09-08 13:29:37 -0700625 mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED,
Andrii Kulian1cb59dd2020-04-10 12:17:17 -0700626 mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea(),
627 task.getStack(), true /* forceNonResizable */);
Benjamin Franza83859f2017-07-03 16:34:14 +0100628 }
629 }
630
631 // This method should only be called on the handler thread
632 private void performStartLockTask(String packageName, int userId, int lockTaskModeState) {
633 // When lock task starts, we disable the status bars.
634 try {
Charles Hebfe82d12017-10-20 11:59:44 +0100635 if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
Matthew Ng9c3bce52018-02-01 22:00:31 +0000636 getStatusBarService().showPinningEnterExitToast(true /* entering */);
Charles Hebfe82d12017-10-20 11:59:44 +0100637 }
Benjamin Franz3662b152018-01-16 17:23:44 +0000638 mWindowManager.onLockTaskStateChanged(lockTaskModeState);
Benjamin Franza83859f2017-07-03 16:34:14 +0100639 mLockTaskModeState = lockTaskModeState;
Charles Hee078db72017-10-19 18:03:20 +0100640 setStatusBarState(lockTaskModeState, userId);
641 setKeyguardState(lockTaskModeState, userId);
Benjamin Franza83859f2017-07-03 16:34:14 +0100642 if (getDevicePolicyManager() != null) {
643 getDevicePolicyManager().notifyLockTaskModeChanged(true, packageName, userId);
644 }
645 } catch (RemoteException ex) {
646 throw new RuntimeException(ex);
647 }
648 }
649
650 /**
Charles He520b2832017-09-02 15:27:16 +0100651 * Update packages that are allowed to be launched in lock task mode.
652 * @param userId Which user this whitelist is associated with
653 * @param packages The whitelist of packages allowed in lock task mode
654 * @see #mLockTaskPackages
Benjamin Franza83859f2017-07-03 16:34:14 +0100655 */
Charles He520b2832017-09-02 15:27:16 +0100656 void updateLockTaskPackages(int userId, String[] packages) {
657 mLockTaskPackages.put(userId, packages);
658
659 boolean taskChanged = false;
Benjamin Franza83859f2017-07-03 16:34:14 +0100660 for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) {
Louis Changcdec0802019-11-11 11:45:07 +0800661 final Task lockedTask = mLockTaskModeTasks.get(taskNdx);
Charles He520b2832017-09-02 15:27:16 +0100662 final boolean wasWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
663 || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
Benjamin Franza83859f2017-07-03 16:34:14 +0100664 lockedTask.setLockTaskAuth();
Charles He520b2832017-09-02 15:27:16 +0100665 final boolean isWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
666 || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
667
668 if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700669 || lockedTask.mUserId != userId
Charles He520b2832017-09-02 15:27:16 +0100670 || !wasWhitelisted || isWhitelisted) {
671 continue;
Benjamin Franza83859f2017-07-03 16:34:14 +0100672 }
Charles He520b2832017-09-02 15:27:16 +0100673
674 // Terminate locked tasks that have recently lost whitelist authorization.
675 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " +
676 lockedTask + " mLockTaskAuth()=" + lockedTask.lockTaskAuthToString());
677 removeLockedTask(lockedTask);
678 lockedTask.performClearTaskLocked();
679 taskChanged = true;
Benjamin Franza83859f2017-07-03 16:34:14 +0100680 }
681
Louis Chang149d5c82019-12-30 09:47:39 +0800682 mSupervisor.mRootWindowContainer.forAllTasks(Task::setLockTaskAuth);
Charles He520b2832017-09-02 15:27:16 +0100683
Louis Chang149d5c82019-12-30 09:47:39 +0800684 final ActivityRecord r = mSupervisor.mRootWindowContainer.topRunningActivity();
Louis Changcdec0802019-11-11 11:45:07 +0800685 final Task task = (r != null) ? r.getTask() : null;
Charles He520b2832017-09-02 15:27:16 +0100686 if (mLockTaskModeTasks.isEmpty() && task!= null
Benjamin Franza83859f2017-07-03 16:34:14 +0100687 && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
688 // This task must have just been authorized.
689 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK,
690 "onLockTaskPackagesUpdated: starting new locktask task=" + task);
Charles He520b2832017-09-02 15:27:16 +0100691 setLockTaskMode(task, LOCK_TASK_MODE_LOCKED, "package updated", false);
692 taskChanged = true;
Benjamin Franza83859f2017-07-03 16:34:14 +0100693 }
Charles He520b2832017-09-02 15:27:16 +0100694
695 if (taskChanged) {
Louis Chang149d5c82019-12-30 09:47:39 +0800696 mSupervisor.mRootWindowContainer.resumeFocusedStacksTopActivities();
Benjamin Franza83859f2017-07-03 16:34:14 +0100697 }
698 }
699
Charles He520b2832017-09-02 15:27:16 +0100700 boolean isPackageWhitelisted(int userId, String pkg) {
701 if (pkg == null) {
702 return false;
703 }
704 String[] whitelist;
705 whitelist = mLockTaskPackages.get(userId);
706 if (whitelist == null) {
707 return false;
708 }
709 for (String whitelistedPkg : whitelist) {
710 if (pkg.equals(whitelistedPkg)) {
711 return true;
712 }
713 }
714 return false;
715 }
716
Benjamin Franza83859f2017-07-03 16:34:14 +0100717 /**
Charles Hee078db72017-10-19 18:03:20 +0100718 * Update the UI features that are enabled for LockTask mode.
719 * @param userId Which user these feature flags are associated with
720 * @param flags Bitfield of feature flags
721 * @see DevicePolicyManager#setLockTaskFeatures(ComponentName, int)
722 */
723 void updateLockTaskFeatures(int userId, int flags) {
724 int oldFlags = getLockTaskFeaturesForUser(userId);
725 if (flags == oldFlags) {
726 return;
727 }
728
729 mLockTaskFeatures.put(userId, flags);
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700730 if (!mLockTaskModeTasks.isEmpty() && userId == mLockTaskModeTasks.get(0).mUserId) {
Charles Hee078db72017-10-19 18:03:20 +0100731 mHandler.post(() -> {
732 if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) {
733 setStatusBarState(mLockTaskModeState, userId);
734 setKeyguardState(mLockTaskModeState, userId);
735 }
736 });
737 }
738 }
739
740 /**
741 * Helper method for configuring the status bar disabled state.
742 * Should only be called on the handler thread to avoid race.
743 */
744 private void setStatusBarState(int lockTaskModeState, int userId) {
745 IStatusBarService statusBar = getStatusBarService();
746 if (statusBar == null) {
747 Slog.e(TAG, "Can't find StatusBarService");
748 return;
749 }
750
751 // Default state, when lockTaskModeState == LOCK_TASK_MODE_NONE
752 int flags1 = StatusBarManager.DISABLE_NONE;
753 int flags2 = StatusBarManager.DISABLE2_NONE;
754
755 if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
756 flags1 = STATUS_BAR_MASK_PINNED;
757
758 } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
759 int lockTaskFeatures = getLockTaskFeaturesForUser(userId);
760 Pair<Integer, Integer> statusBarFlags = getStatusBarDisableFlags(lockTaskFeatures);
761 flags1 = statusBarFlags.first;
762 flags2 = statusBarFlags.second;
763 }
764
765 try {
766 statusBar.disable(flags1, mToken, mContext.getPackageName());
767 statusBar.disable2(flags2, mToken, mContext.getPackageName());
768 } catch (RemoteException e) {
769 Slog.e(TAG, "Failed to set status bar flags", e);
770 }
771 }
772
773 /**
774 * Helper method for configuring the keyguard disabled state.
775 * Should only be called on the handler thread to avoid race.
776 */
777 private void setKeyguardState(int lockTaskModeState, int userId) {
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100778 mPendingDisableFromDismiss = UserHandle.USER_NULL;
Charles Hee078db72017-10-19 18:03:20 +0100779 if (lockTaskModeState == LOCK_TASK_MODE_NONE) {
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100780 mWindowManager.reenableKeyguard(mToken, userId);
Charles Hee078db72017-10-19 18:03:20 +0100781
782 } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
Charles He858f1322017-11-27 17:11:04 -0800783 if (isKeyguardAllowed(userId)) {
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100784 mWindowManager.reenableKeyguard(mToken, userId);
Charles He858f1322017-11-27 17:11:04 -0800785 } else {
Tony Mak2bf36912018-03-21 15:45:52 +0000786 // If keyguard is not secure and it is locked, dismiss the keyguard before
787 // disabling it, which avoids the platform to think the keyguard is still on.
Brad Stenning2bdc21e2019-03-11 14:33:22 -0700788 if (mWindowManager.isKeyguardLocked() && !mWindowManager.isKeyguardSecure(userId)) {
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100789 mPendingDisableFromDismiss = userId;
Tony Mak2bf36912018-03-21 15:45:52 +0000790 mWindowManager.dismissKeyguard(new IKeyguardDismissCallback.Stub() {
791 @Override
792 public void onDismissError() throws RemoteException {
793 Slog.i(TAG, "setKeyguardState: failed to dismiss keyguard");
794 }
795
796 @Override
797 public void onDismissSucceeded() throws RemoteException {
798 mHandler.post(
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100799 () -> {
800 if (mPendingDisableFromDismiss == userId) {
801 mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG,
802 userId);
803 mPendingDisableFromDismiss = UserHandle.USER_NULL;
804 }
805 });
Tony Mak2bf36912018-03-21 15:45:52 +0000806 }
807
808 @Override
809 public void onDismissCancelled() throws RemoteException {
810 Slog.i(TAG, "setKeyguardState: dismiss cancelled");
811 }
812 }, null);
813 } else {
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100814 mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG, userId);
Tony Mak2bf36912018-03-21 15:45:52 +0000815 }
Charles Hee078db72017-10-19 18:03:20 +0100816 }
817
818 } else { // lockTaskModeState == LOCK_TASK_MODE_PINNED
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100819 mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG, userId);
Charles Hee078db72017-10-19 18:03:20 +0100820 }
821 }
822
823 /**
824 * Helper method for locking the device immediately. This may be necessary when the device
825 * leaves the pinned mode.
826 */
827 private void lockKeyguardIfNeeded() {
Jonathan Scott851d4692019-04-29 18:03:58 +0100828 if (shouldLockKeyguard()) {
829 mWindowManager.lockNow(null);
830 mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
831 getLockPatternUtils().requireCredentialEntry(USER_ALL);
832 }
833 }
834
835 private boolean shouldLockKeyguard() {
836 // This functionality should be kept consistent with
837 // com.android.settings.security.ScreenPinningSettings (see b/127605586)
Charles Hee078db72017-10-19 18:03:20 +0100838 try {
Jonathan Scott851d4692019-04-29 18:03:58 +0100839 return Settings.Secure.getIntForUser(
Charles Hee078db72017-10-19 18:03:20 +0100840 mContext.getContentResolver(),
Jonathan Scott851d4692019-04-29 18:03:58 +0100841 Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, USER_CURRENT) != 0;
Charles Hee078db72017-10-19 18:03:20 +0100842 } catch (Settings.SettingNotFoundException e) {
Jonathan Scott851d4692019-04-29 18:03:58 +0100843 // Log to SafetyNet for b/127605586
844 android.util.EventLog.writeEvent(0x534e4554, "127605586", -1, "");
Jonathan Scottaa2d6b82019-05-13 12:21:50 +0100845 return getLockPatternUtils().isSecure(USER_CURRENT);
Charles Hee078db72017-10-19 18:03:20 +0100846 }
847 }
848
849 /**
850 * Translates from LockTask feature flags to StatusBarManager disable and disable2 flags.
851 * @param lockTaskFlags Bitfield of flags as per
852 * {@link DevicePolicyManager#setLockTaskFeatures(ComponentName, int)}
853 * @return A {@link Pair} of {@link StatusBarManager#disable(int)} and
854 * {@link StatusBarManager#disable2(int)} flags
855 */
856 @VisibleForTesting
857 Pair<Integer, Integer> getStatusBarDisableFlags(int lockTaskFlags) {
858 // Everything is disabled by default
859 int flags1 = StatusBarManager.DISABLE_MASK;
860 int flags2 = StatusBarManager.DISABLE2_MASK;
861 for (int i = STATUS_BAR_FLAG_MAP_LOCKED.size() - 1; i >= 0; i--) {
862 Pair<Integer, Integer> statusBarFlags = STATUS_BAR_FLAG_MAP_LOCKED.valueAt(i);
863 if ((STATUS_BAR_FLAG_MAP_LOCKED.keyAt(i) & lockTaskFlags) != 0) {
864 flags1 &= ~statusBarFlags.first;
865 flags2 &= ~statusBarFlags.second;
866 }
867 }
868 // Some flags are not used for LockTask purposes, so we mask them
869 flags1 &= STATUS_BAR_MASK_LOCKED;
870 return new Pair<>(flags1, flags2);
871 }
872
873 /**
874 * Gets the cached value of LockTask feature flags for a specific user.
875 */
876 private int getLockTaskFeaturesForUser(int userId) {
877 return mLockTaskFeatures.get(userId, DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
878 }
879
Benjamin Franza83859f2017-07-03 16:34:14 +0100880 // Should only be called on the handler thread
881 @Nullable
882 private IStatusBarService getStatusBarService() {
883 if (mStatusBarService == null) {
884 mStatusBarService = IStatusBarService.Stub.asInterface(
885 ServiceManager.checkService(STATUS_BAR_SERVICE));
886 if (mStatusBarService == null) {
887 Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE");
888 }
889 }
890 return mStatusBarService;
891 }
892
893 // Should only be called on the handler thread
894 @Nullable
895 private IDevicePolicyManager getDevicePolicyManager() {
896 if (mDevicePolicyManager == null) {
897 mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface(
898 ServiceManager.checkService(DEVICE_POLICY_SERVICE));
899 if (mDevicePolicyManager == null) {
900 Slog.w(TAG, "warning: no DEVICE_POLICY_SERVICE");
901 }
902 }
903 return mDevicePolicyManager;
904 }
905
906 @NonNull
907 private LockPatternUtils getLockPatternUtils() {
908 if (mLockPatternUtils == null) {
909 // We don't preserve the LPU object to save memory
910 return new LockPatternUtils(mContext);
911 }
912 return mLockPatternUtils;
913 }
914
Charles He858f1322017-11-27 17:11:04 -0800915 @Nullable
916 private TelecomManager getTelecomManager() {
917 if (mTelecomManager == null) {
918 // We don't preserve the TelecomManager object to save memory
919 return mContext.getSystemService(TelecomManager.class);
920 }
921 return mTelecomManager;
922 }
923
Benjamin Franza83859f2017-07-03 16:34:14 +0100924 public void dump(PrintWriter pw, String prefix) {
Winson Chung268eccb2020-03-26 13:43:44 -0700925 pw.println(prefix + "LockTaskController:");
Charles He520b2832017-09-02 15:27:16 +0100926 prefix = prefix + " ";
927 pw.println(prefix + "mLockTaskModeState=" + lockTaskModeToString());
928 pw.println(prefix + "mLockTaskModeTasks=");
929 for (int i = 0; i < mLockTaskModeTasks.size(); ++i) {
930 pw.println(prefix + " #" + i + " " + mLockTaskModeTasks.get(i));
931 }
932 pw.println(prefix + "mLockTaskPackages (userId:packages)=");
933 for (int i = 0; i < mLockTaskPackages.size(); ++i) {
934 pw.println(prefix + " u" + mLockTaskPackages.keyAt(i)
935 + ":" + Arrays.toString(mLockTaskPackages.valueAt(i)));
936 }
Winson Chung268eccb2020-03-26 13:43:44 -0700937 pw.println();
Benjamin Franza83859f2017-07-03 16:34:14 +0100938 }
939
940 private String lockTaskModeToString() {
941 switch (mLockTaskModeState) {
942 case LOCK_TASK_MODE_LOCKED:
943 return "LOCKED";
944 case LOCK_TASK_MODE_PINNED:
945 return "PINNED";
946 case LOCK_TASK_MODE_NONE:
947 return "NONE";
948 default: return "unknown=" + mLockTaskModeState;
949 }
950 }
Adrian Roos1c8e3c02018-11-20 20:07:55 +0100951
952 /** Marker class for the token used to disable keyguard. */
953 static class LockTaskToken extends Binder {
954 private LockTaskToken() {
955 }
956 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100957}