blob: 21f9135bd03dc442ff3d70033eb5cc27c81bb46e [file] [log] [blame]
Benjamin Franza83859f2017-07-03 16:34:14 +01001/*
2 * Copyright 2017, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
19import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
20import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
21import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
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
Benjamin Franza83859f2017-07-03 16:34:14 +010031import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
32import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
33import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
34import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
35import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
36import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
37import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
38import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
39import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
40
41import android.annotation.NonNull;
42import android.annotation.Nullable;
43import android.app.Activity;
44import android.app.ActivityManager;
Charles Hee078db72017-10-19 18:03:20 +010045import android.app.StatusBarManager;
46import android.app.admin.DevicePolicyManager;
Benjamin Franza83859f2017-07-03 16:34:14 +010047import android.app.admin.IDevicePolicyManager;
Charles Hee078db72017-10-19 18:03:20 +010048import android.content.ComponentName;
Benjamin Franza83859f2017-07-03 16:34:14 +010049import android.content.Context;
Charles He858f1322017-11-27 17:11:04 -080050import android.content.Intent;
Benjamin Franza83859f2017-07-03 16:34:14 +010051import android.os.Binder;
52import android.os.Debug;
53import android.os.Handler;
54import android.os.IBinder;
55import android.os.RemoteException;
56import android.os.ServiceManager;
57import android.provider.Settings;
Charles He858f1322017-11-27 17:11:04 -080058import android.telecom.TelecomManager;
Charles Hee078db72017-10-19 18:03:20 +010059import android.util.Pair;
Benjamin Franza83859f2017-07-03 16:34:14 +010060import android.util.Slog;
Charles He520b2832017-09-02 15:27:16 +010061import android.util.SparseArray;
Charles He858f1322017-11-27 17:11:04 -080062import android.util.SparseIntArray;
Benjamin Franza83859f2017-07-03 16:34:14 +010063
64import com.android.internal.annotations.VisibleForTesting;
65import com.android.internal.statusbar.IStatusBarService;
66import com.android.internal.widget.LockPatternUtils;
67import com.android.server.LocalServices;
68import com.android.server.statusbar.StatusBarManagerInternal;
69import com.android.server.wm.WindowManagerService;
70
71import java.io.PrintWriter;
72import java.util.ArrayList;
Charles He520b2832017-09-02 15:27:16 +010073import java.util.Arrays;
Benjamin Franza83859f2017-07-03 16:34:14 +010074
75/**
76 * Helper class that deals with all things related to task locking. This includes the screen pinning
77 * mode that can be launched via System UI as well as the fully locked mode that can be achieved
78 * on fully managed devices.
79 *
80 * Note: All methods in this class should only be called with the ActivityManagerService lock held.
81 *
82 * @see Activity#startLockTask()
83 * @see Activity#stopLockTask()
84 */
85public class LockTaskController {
86 private static final String TAG = TAG_WITH_CLASS_NAME ? "LockTaskController" : TAG_AM;
87 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
88
89 @VisibleForTesting
Charles Hee078db72017-10-19 18:03:20 +010090 static final int STATUS_BAR_MASK_LOCKED = StatusBarManager.DISABLE_MASK
91 & (~StatusBarManager.DISABLE_EXPAND)
92 & (~StatusBarManager.DISABLE_NOTIFICATION_TICKER)
93 & (~StatusBarManager.DISABLE_SYSTEM_INFO)
94 & (~StatusBarManager.DISABLE_BACK);
Benjamin Franza83859f2017-07-03 16:34:14 +010095 @VisibleForTesting
Charles Hee078db72017-10-19 18:03:20 +010096 static final int STATUS_BAR_MASK_PINNED = StatusBarManager.DISABLE_MASK
97 & (~StatusBarManager.DISABLE_BACK)
98 & (~StatusBarManager.DISABLE_HOME)
99 & (~StatusBarManager.DISABLE_RECENT);
100
101 private static final SparseArray<Pair<Integer, Integer>> STATUS_BAR_FLAG_MAP_LOCKED;
102 static {
103 STATUS_BAR_FLAG_MAP_LOCKED = new SparseArray<>();
104
105 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO,
106 new Pair<>(StatusBarManager.DISABLE_CLOCK, StatusBarManager.DISABLE2_SYSTEM_ICONS));
107
108 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS,
109 new Pair<>(StatusBarManager.DISABLE_NOTIFICATION_ICONS
110 | StatusBarManager.DISABLE_NOTIFICATION_ALERTS,
111 StatusBarManager.DISABLE2_NOTIFICATION_SHADE));
112
113 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_HOME,
114 new Pair<>(StatusBarManager.DISABLE_HOME, StatusBarManager.DISABLE2_NONE));
115
116 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_RECENTS,
117 new Pair<>(StatusBarManager.DISABLE_RECENT, StatusBarManager.DISABLE2_NONE));
118
119 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS,
120 new Pair<>(StatusBarManager.DISABLE_NONE,
121 StatusBarManager.DISABLE2_GLOBAL_ACTIONS));
122 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100123
124 /** Tag used for disabling of keyguard */
125 private static final String LOCK_TASK_TAG = "Lock-to-App";
126
127 private final IBinder mToken = new Binder();
128 private final ActivityStackSupervisor mSupervisor;
129 private final Context mContext;
130
131 // The following system services cannot be final, because they do not exist when this class
132 // is instantiated during device boot
133 @VisibleForTesting
134 IStatusBarService mStatusBarService;
135 @VisibleForTesting
136 IDevicePolicyManager mDevicePolicyManager;
137 @VisibleForTesting
138 WindowManagerService mWindowManager;
139 @VisibleForTesting
140 LockPatternUtils mLockPatternUtils;
Charles He858f1322017-11-27 17:11:04 -0800141 @VisibleForTesting
142 TelecomManager mTelecomManager;
Benjamin Franza83859f2017-07-03 16:34:14 +0100143
144 /**
145 * Helper that is responsible for showing the right toast when a disallowed activity operation
146 * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
147 * fully locked mode we only show that unlocking is blocked.
148 */
149 @VisibleForTesting
150 LockTaskNotify mLockTaskNotify;
151
152 /**
Charles Heff9b4dff2017-09-22 10:18:37 +0100153 * The chain of tasks in LockTask mode, in the order of when they first entered LockTask mode.
154 *
155 * The first task in the list, which started the current LockTask session, is called the root
156 * task. It coincides with the Home task in a typical multi-app kiosk deployment. When there are
157 * more than one locked tasks, the root task can't be finished. Nor can it be moved to the back
158 * of the stack by {@link ActivityStack#moveTaskToBackLocked(int)};
159 *
160 * Calling {@link Activity#stopLockTask()} on the root task will finish all tasks but itself in
161 * this list, and the device will exit LockTask mode.
162 *
163 * The list is empty if LockTask is inactive.
Benjamin Franza83859f2017-07-03 16:34:14 +0100164 */
165 private final ArrayList<TaskRecord> mLockTaskModeTasks = new ArrayList<>();
166
167 /**
Charles He520b2832017-09-02 15:27:16 +0100168 * Packages that are allowed to be launched into the lock task mode for each user.
169 */
170 private final SparseArray<String[]> mLockTaskPackages = new SparseArray<>();
171
172 /**
Charles Hee078db72017-10-19 18:03:20 +0100173 * Features that are allowed by DPC to show during LockTask mode.
174 */
Charles He858f1322017-11-27 17:11:04 -0800175 private final SparseIntArray mLockTaskFeatures = new SparseIntArray();
Charles Hee078db72017-10-19 18:03:20 +0100176
177 /**
Benjamin Franza83859f2017-07-03 16:34:14 +0100178 * Store the current lock task mode. Possible values:
179 * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
180 * {@link ActivityManager#LOCK_TASK_MODE_PINNED}
181 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100182 private int mLockTaskModeState = LOCK_TASK_MODE_NONE;
Benjamin Franza83859f2017-07-03 16:34:14 +0100183
184 /**
185 * This is ActivityStackSupervisor's Handler.
186 */
187 private final Handler mHandler;
188
189 LockTaskController(Context context, ActivityStackSupervisor supervisor,
190 Handler handler) {
191 mContext = context;
192 mSupervisor = supervisor;
193 mHandler = handler;
194 }
195
196 /**
197 * Set the window manager instance used in this class. This is necessary, because the window
198 * manager does not exist during instantiation of this class.
199 */
200 void setWindowManager(WindowManagerService windowManager) {
201 mWindowManager = windowManager;
202 }
203
204 /**
205 * @return the current lock task state. This can be any of
206 * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
207 * {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
208 */
209 int getLockTaskModeState() {
210 return mLockTaskModeState;
211 }
212
213 /**
Charles He520b2832017-09-02 15:27:16 +0100214 * @return whether the given task is locked at the moment. Locked tasks cannot be moved to the
215 * back of the stack.
Benjamin Franza83859f2017-07-03 16:34:14 +0100216 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100217 @VisibleForTesting
218 boolean isTaskLocked(TaskRecord task) {
219 return mLockTaskModeTasks.contains(task);
220 }
221
222 /**
223 * @return {@code true} whether this task first started the current LockTask session.
224 */
225 private boolean isRootTask(TaskRecord task) {
226 return mLockTaskModeTasks.indexOf(task) == 0;
227 }
228
229 /**
230 * @return whether the given activity is blocked from finishing, because it is the only activity
231 * of the last locked task and finishing it would mean that lock task mode is ended illegally.
232 */
233 boolean activityBlockedFromFinish(ActivityRecord activity) {
234 final TaskRecord task = activity.getTask();
235 if (activity == task.getRootActivity()
236 && activity == task.getTopActivity()
237 && task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV
238 && isRootTask(task)) {
239 Slog.i(TAG, "Not finishing task in lock task mode");
Benjamin Franza83859f2017-07-03 16:34:14 +0100240 showLockTaskToast();
241 return true;
242 }
243 return false;
244 }
245
246 /**
Charles Heff9b4dff2017-09-22 10:18:37 +0100247 * @return whether the given task can be moved to the back of the stack with
248 * {@link ActivityStack#moveTaskToBackLocked(int)}
249 * @see #mLockTaskModeTasks
Benjamin Franza83859f2017-07-03 16:34:14 +0100250 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100251 boolean canMoveTaskToBack(TaskRecord task) {
252 if (isRootTask(task)) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100253 showLockTaskToast();
Charles Heff9b4dff2017-09-22 10:18:37 +0100254 return false;
Benjamin Franza83859f2017-07-03 16:34:14 +0100255 }
Charles Heff9b4dff2017-09-22 10:18:37 +0100256 return true;
Benjamin Franza83859f2017-07-03 16:34:14 +0100257 }
258
259 /**
Charles Hed62f9652017-11-01 10:05:51 +0000260 * @return whether the requested task is allowed to be locked (either whitelisted, or declares
261 * lockTaskMode="always" in the manifest).
262 */
263 boolean isTaskWhitelisted(TaskRecord task) {
264 switch(task.mLockTaskAuth) {
265 case LOCK_TASK_AUTH_WHITELISTED:
266 case LOCK_TASK_AUTH_LAUNCHABLE:
267 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
268 return true;
269 case LOCK_TASK_AUTH_PINNABLE:
270 case LOCK_TASK_AUTH_DONT_LOCK:
271 default:
272 return false;
273 }
274 }
275
276 /**
277 * @return whether the requested task is disallowed to be launched.
Benjamin Franza83859f2017-07-03 16:34:14 +0100278 */
279 boolean isLockTaskModeViolation(TaskRecord task) {
280 return isLockTaskModeViolation(task, false);
281 }
282
283 /**
284 * @param isNewClearTask whether the task would be cleared as part of the operation.
Charles Hed62f9652017-11-01 10:05:51 +0000285 * @return whether the requested task is disallowed to be launched.
Benjamin Franza83859f2017-07-03 16:34:14 +0100286 */
287 boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) {
288 if (isLockTaskModeViolationInternal(task, isNewClearTask)) {
289 showLockTaskToast();
290 return true;
291 }
292 return false;
293 }
294
295 private boolean isLockTaskModeViolationInternal(TaskRecord task, boolean isNewClearTask) {
296 // TODO: Double check what's going on here. If the task is already in lock task mode, it's
297 // likely whitelisted, so will return false below.
Charles Heff9b4dff2017-09-22 10:18:37 +0100298 if (isTaskLocked(task) && !isNewClearTask) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100299 // If the task is already at the top and won't be cleared, then allow the operation
300 return false;
301 }
Charles Hed62f9652017-11-01 10:05:51 +0000302
303 // Allow recents activity if enabled by policy
304 if (task.isActivityTypeRecents() && isRecentsAllowed(task.userId)) {
305 return false;
Benjamin Franza83859f2017-07-03 16:34:14 +0100306 }
Charles Hed62f9652017-11-01 10:05:51 +0000307
Charles He858f1322017-11-27 17:11:04 -0800308 // Allow emergency calling when the device is protected by a locked keyguard
309 if (isKeyguardAllowed(task.userId) && isEmergencyCallTask(task)) {
310 return false;
311 }
312
Charles Hed62f9652017-11-01 10:05:51 +0000313 return !(isTaskWhitelisted(task) || mLockTaskModeTasks.isEmpty());
314 }
315
316 private boolean isRecentsAllowed(int userId) {
317 return (getLockTaskFeaturesForUser(userId)
318 & DevicePolicyManager.LOCK_TASK_FEATURE_RECENTS) != 0;
Benjamin Franza83859f2017-07-03 16:34:14 +0100319 }
320
Charles He858f1322017-11-27 17:11:04 -0800321 private boolean isKeyguardAllowed(int userId) {
322 return (getLockTaskFeaturesForUser(userId)
323 & DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD) != 0;
324 }
325
326 private boolean isEmergencyCallTask(TaskRecord task) {
327 final Intent intent = task.intent;
328 if (intent == null) {
329 return false;
330 }
331
332 // 1. The emergency keypad activity launched on top of the keyguard
333 if (EMERGENCY_DIALER_COMPONENT.equals(intent.getComponent())) {
334 return true;
335 }
336
337 // 2. The intent sent by the keypad, which is handled by Telephony
338 if (ACTION_CALL_EMERGENCY.equals(intent.getAction())) {
339 return true;
340 }
341
342 // 3. Telephony then starts the default package for making the call
343 final TelecomManager tm = getTelecomManager();
344 final String dialerPackage = tm != null ? tm.getSystemDialerPackage() : null;
345 if (dialerPackage != null && dialerPackage.equals(intent.getComponent().getPackageName())) {
346 return true;
347 }
348
349 return false;
350 }
351
Benjamin Franza83859f2017-07-03 16:34:14 +0100352 /**
353 * Stop the current lock task mode.
354 *
Charles Heff9b4dff2017-09-22 10:18:37 +0100355 * This is called by {@link ActivityManagerService} and performs various checks before actually
356 * finishing the locked task.
357 *
358 * @param task the task that requested the end of lock task mode ({@code null} for quitting app
359 * pinning mode)
360 * @param isSystemCaller indicates whether this request comes from the system via
361 * {@link ActivityManagerService#stopSystemLockTaskMode()}. If
362 * {@code true}, it means the user intends to stop pinned mode through UI;
363 * otherwise, it's called by an app and we need to stop locked or pinned
364 * mode, subject to checks.
Benjamin Franza83859f2017-07-03 16:34:14 +0100365 * @param callingUid the caller that requested the end of lock task mode.
Charles Heff9b4dff2017-09-22 10:18:37 +0100366 * @throws IllegalArgumentException if the calling task is invalid (e.g., {@code null} or not in
367 * foreground)
Benjamin Franza83859f2017-07-03 16:34:14 +0100368 * @throws SecurityException if the caller is not authorized to stop the lock task mode, i.e. if
369 * they differ from the one that launched lock task mode.
370 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100371 void stopLockTaskMode(@Nullable TaskRecord task, boolean isSystemCaller, int callingUid) {
372 if (mLockTaskModeState == LOCK_TASK_MODE_NONE) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100373 return;
374 }
375
Charles Heff9b4dff2017-09-22 10:18:37 +0100376 if (isSystemCaller) {
377 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
378 clearLockedTasks("stopAppPinning");
379 } else {
380 Slog.e(TAG_LOCKTASK, "Attempted to stop LockTask with isSystemCaller=true");
381 showLockTaskToast();
382 }
383
384 } else {
385 // Ensure calling activity is not null
386 if (task == null) {
387 throw new IllegalArgumentException("can't stop LockTask for null task");
388 }
389
390 // Ensure the same caller for startLockTaskMode and stopLockTaskMode.
391 // It is possible lockTaskMode was started by the system process because
392 // android:lockTaskMode is set to a locking value in the application manifest
393 // instead of the app calling startLockTaskMode. In this case
394 // {@link TaskRecord.mLockTaskUid} will be 0, so we compare the callingUid to the
395 // {@link TaskRecord.effectiveUid} instead. Also caller with
396 // {@link MANAGE_ACTIVITY_STACKS} can stop any lock task.
397 if (callingUid != task.mLockTaskUid
398 && (task.mLockTaskUid != 0 || callingUid != task.effectiveUid)) {
399 throw new SecurityException("Invalid uid, expected " + task.mLockTaskUid
400 + " callingUid=" + callingUid + " effectiveUid=" + task.effectiveUid);
401 }
402
403 // We don't care if it's pinned or locked mode; this will stop it anyways.
404 clearLockedTask(task);
405 }
406 }
407
408 /**
409 * Clear all locked tasks and request the end of LockTask mode.
410 *
411 * This method is called by {@link UserController} when starting a new foreground user, and,
412 * unlike {@link #stopLockTaskMode(TaskRecord, boolean, int)}, it doesn't perform the checks.
413 */
414 void clearLockedTasks(String reason) {
415 if (DEBUG_LOCKTASK) Slog.i(TAG_LOCKTASK, "clearLockedTasks: " + reason);
416 if (!mLockTaskModeTasks.isEmpty()) {
417 clearLockedTask(mLockTaskModeTasks.get(0));
418 }
419 }
420
421 /**
422 * Clear one locked task from LockTask mode.
423 *
424 * If the requested task is the root task (see {@link #mLockTaskModeTasks}), then all locked
425 * tasks are cleared. Otherwise, only the requested task is cleared. LockTask mode is stopped
426 * when the last locked task is cleared.
427 *
428 * @param task the task to be cleared from LockTask mode.
429 */
430 void clearLockedTask(final TaskRecord task) {
431 if (task == null || mLockTaskModeTasks.isEmpty()) return;
432
433 if (task == mLockTaskModeTasks.get(0)) {
434 // We're removing the root task while there are other locked tasks. Therefore we should
435 // clear all locked tasks in reverse order.
436 for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx > 0; --taskNdx) {
437 clearLockedTask(mLockTaskModeTasks.get(taskNdx));
438 }
439 }
440
441 removeLockedTask(task);
442 if (mLockTaskModeTasks.isEmpty()) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100443 return;
444 }
Charles Heff9b4dff2017-09-22 10:18:37 +0100445 task.performClearTaskLocked();
446 mSupervisor.resumeFocusedStackTopActivityLocked();
Benjamin Franza83859f2017-07-03 16:34:14 +0100447 }
448
449 /**
450 * Remove the given task from the locked task list. If this was the last task in the list,
451 * lock task mode is stopped.
452 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100453 private void removeLockedTask(final TaskRecord task) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100454 if (!mLockTaskModeTasks.remove(task)) {
455 return;
456 }
Charles Heff9b4dff2017-09-22 10:18:37 +0100457 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: removed " + task);
Benjamin Franza83859f2017-07-03 16:34:14 +0100458 if (mLockTaskModeTasks.isEmpty()) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100459 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: task=" + task +
460 " last task, reverting locktask mode. Callers=" + Debug.getCallers(3));
461 mHandler.post(() -> performStopLockTask(task.userId));
462 }
463 }
464
Benjamin Franza83859f2017-07-03 16:34:14 +0100465 // This method should only be called on the handler thread
466 private void performStopLockTask(int userId) {
467 // When lock task ends, we enable the status bars.
468 try {
Charles Hee078db72017-10-19 18:03:20 +0100469 setStatusBarState(LOCK_TASK_MODE_NONE, userId);
470 setKeyguardState(LOCK_TASK_MODE_NONE, userId);
471 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
472 lockKeyguardIfNeeded();
Benjamin Franza83859f2017-07-03 16:34:14 +0100473 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100474 if (getDevicePolicyManager() != null) {
475 getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId);
476 }
Charles Hebfe82d12017-10-20 11:59:44 +0100477 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
478 getLockTaskNotify().showPinningExitToast();
479 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100480 } catch (RemoteException ex) {
481 throw new RuntimeException(ex);
482 } finally {
483 mLockTaskModeState = LOCK_TASK_MODE_NONE;
484 }
485 }
486
487 /**
Charles Hebfe82d12017-10-20 11:59:44 +0100488 * Show the lock task violation toast. Currently we only show toast for screen pinning mode, and
489 * no-op if the device is in locked mode.
Benjamin Franza83859f2017-07-03 16:34:14 +0100490 */
491 void showLockTaskToast() {
Charles Hebfe82d12017-10-20 11:59:44 +0100492 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
493 mHandler.post(() -> getLockTaskNotify().showEscapeToast());
494 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100495 }
496
497 // Starting lock task
498
499 /**
500 * Method to start lock task mode on a given task.
501 *
502 * @param task the task that should be locked.
Charles Heff9b4dff2017-09-22 10:18:37 +0100503 * @param isSystemCaller indicates whether this request was initiated by the system via
504 * {@link ActivityManagerService#startSystemLockTaskMode(int)}. If
505 * {@code true}, this intends to start pinned mode; otherwise, we look
506 * at the calling task's mLockTaskAuth to decide which mode to start.
Benjamin Franza83859f2017-07-03 16:34:14 +0100507 * @param callingUid the caller that requested the launch of lock task mode.
508 */
Charles Heff9b4dff2017-09-22 10:18:37 +0100509 void startLockTaskMode(@NonNull TaskRecord task, boolean isSystemCaller, int callingUid) {
510 if (!isSystemCaller) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100511 task.mLockTaskUid = callingUid;
512 if (task.mLockTaskAuth == LOCK_TASK_AUTH_PINNABLE) {
513 // startLockTask() called by app, but app is not part of lock task whitelist. Show
Charles Heff9b4dff2017-09-22 10:18:37 +0100514 // app pinning request. We will come back here with isSystemCaller true.
Benjamin Franza83859f2017-07-03 16:34:14 +0100515 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Mode default, asking user");
516 StatusBarManagerInternal statusBarManager = LocalServices.getService(
517 StatusBarManagerInternal.class);
518 if (statusBarManager != null) {
519 statusBarManager.showScreenPinningRequest(task.taskId);
520 }
521 return;
522 }
523 }
524
525 // System can only initiate screen pinning, not full lock task mode
Charles Heff9b4dff2017-09-22 10:18:37 +0100526 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
527 isSystemCaller ? "Locking pinned" : "Locking fully");
528 setLockTaskMode(task, isSystemCaller ? LOCK_TASK_MODE_PINNED : LOCK_TASK_MODE_LOCKED,
Benjamin Franza83859f2017-07-03 16:34:14 +0100529 "startLockTask", true);
530 }
531
532 /**
533 * Start lock task mode on the given task.
534 * @param lockTaskModeState whether fully locked or pinned mode.
535 * @param andResume whether the task should be brought to foreground as part of the operation.
536 */
537 private void setLockTaskMode(@NonNull TaskRecord task, int lockTaskModeState,
538 String reason, boolean andResume) {
539 // Should have already been checked, but do it again.
540 if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) {
541 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
542 "setLockTaskMode: Can't lock due to auth");
543 return;
544 }
545 if (isLockTaskModeViolation(task)) {
546 Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task.");
547 return;
548 }
549
550 if (mLockTaskModeTasks.isEmpty()) {
Charles Hed62f9652017-11-01 10:05:51 +0000551 mSupervisor.mRecentTasks.onLockTaskModeStateChanged(lockTaskModeState, task.userId);
Benjamin Franza83859f2017-07-03 16:34:14 +0100552 // Start lock task on the handler thread
553 mHandler.post(() -> performStartLockTask(
554 task.intent.getComponent().getPackageName(),
555 task.userId,
556 lockTaskModeState));
557 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100558 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskMode: Locking to " + task +
559 " Callers=" + Debug.getCallers(4));
Charles Heff9b4dff2017-09-22 10:18:37 +0100560
561 if (!mLockTaskModeTasks.contains(task)) {
562 mLockTaskModeTasks.add(task);
563 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100564
565 if (task.mLockTaskUid == -1) {
566 task.mLockTaskUid = task.effectiveUid;
567 }
568
569 if (andResume) {
Wale Ogunwale66e16852017-10-19 13:35:52 -0700570 mSupervisor.findTaskToMoveToFront(task, 0, null, reason,
Benjamin Franza83859f2017-07-03 16:34:14 +0100571 lockTaskModeState != LOCK_TASK_MODE_NONE);
572 mSupervisor.resumeFocusedStackTopActivityLocked();
573 mWindowManager.executeAppTransition();
574 } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
Wale Ogunwale0568aed2017-09-08 13:29:37 -0700575 mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED,
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700576 DEFAULT_DISPLAY, task.getStack(), true /* forceNonResizable */);
Benjamin Franza83859f2017-07-03 16:34:14 +0100577 }
578 }
579
580 // This method should only be called on the handler thread
581 private void performStartLockTask(String packageName, int userId, int lockTaskModeState) {
582 // When lock task starts, we disable the status bars.
583 try {
Charles Hebfe82d12017-10-20 11:59:44 +0100584 if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
585 getLockTaskNotify().showPinningStartToast();
586 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100587 mLockTaskModeState = lockTaskModeState;
Charles Hee078db72017-10-19 18:03:20 +0100588 setStatusBarState(lockTaskModeState, userId);
589 setKeyguardState(lockTaskModeState, userId);
Benjamin Franza83859f2017-07-03 16:34:14 +0100590 if (getDevicePolicyManager() != null) {
591 getDevicePolicyManager().notifyLockTaskModeChanged(true, packageName, userId);
592 }
593 } catch (RemoteException ex) {
594 throw new RuntimeException(ex);
595 }
596 }
597
598 /**
Charles He520b2832017-09-02 15:27:16 +0100599 * Update packages that are allowed to be launched in lock task mode.
600 * @param userId Which user this whitelist is associated with
601 * @param packages The whitelist of packages allowed in lock task mode
602 * @see #mLockTaskPackages
Benjamin Franza83859f2017-07-03 16:34:14 +0100603 */
Charles He520b2832017-09-02 15:27:16 +0100604 void updateLockTaskPackages(int userId, String[] packages) {
605 mLockTaskPackages.put(userId, packages);
606
607 boolean taskChanged = false;
Benjamin Franza83859f2017-07-03 16:34:14 +0100608 for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) {
609 final TaskRecord lockedTask = mLockTaskModeTasks.get(taskNdx);
Charles He520b2832017-09-02 15:27:16 +0100610 final boolean wasWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
611 || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
Benjamin Franza83859f2017-07-03 16:34:14 +0100612 lockedTask.setLockTaskAuth();
Charles He520b2832017-09-02 15:27:16 +0100613 final boolean isWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
614 || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
615
616 if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED
617 || lockedTask.userId != userId
618 || !wasWhitelisted || isWhitelisted) {
619 continue;
Benjamin Franza83859f2017-07-03 16:34:14 +0100620 }
Charles He520b2832017-09-02 15:27:16 +0100621
622 // Terminate locked tasks that have recently lost whitelist authorization.
623 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " +
624 lockedTask + " mLockTaskAuth()=" + lockedTask.lockTaskAuthToString());
625 removeLockedTask(lockedTask);
626 lockedTask.performClearTaskLocked();
627 taskChanged = true;
Benjamin Franza83859f2017-07-03 16:34:14 +0100628 }
629
630 for (int displayNdx = mSupervisor.getChildCount() - 1; displayNdx >= 0; --displayNdx) {
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700631 mSupervisor.getChildAt(displayNdx).onLockTaskPackagesUpdated();
Benjamin Franza83859f2017-07-03 16:34:14 +0100632 }
Charles He520b2832017-09-02 15:27:16 +0100633
Benjamin Franza83859f2017-07-03 16:34:14 +0100634 final ActivityRecord r = mSupervisor.topRunningActivityLocked();
Charles He520b2832017-09-02 15:27:16 +0100635 final TaskRecord task = (r != null) ? r.getTask() : null;
636 if (mLockTaskModeTasks.isEmpty() && task!= null
Benjamin Franza83859f2017-07-03 16:34:14 +0100637 && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
638 // This task must have just been authorized.
639 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK,
640 "onLockTaskPackagesUpdated: starting new locktask task=" + task);
Charles He520b2832017-09-02 15:27:16 +0100641 setLockTaskMode(task, LOCK_TASK_MODE_LOCKED, "package updated", false);
642 taskChanged = true;
Benjamin Franza83859f2017-07-03 16:34:14 +0100643 }
Charles He520b2832017-09-02 15:27:16 +0100644
645 if (taskChanged) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100646 mSupervisor.resumeFocusedStackTopActivityLocked();
647 }
648 }
649
Charles He520b2832017-09-02 15:27:16 +0100650 boolean isPackageWhitelisted(int userId, String pkg) {
651 if (pkg == null) {
652 return false;
653 }
654 String[] whitelist;
655 whitelist = mLockTaskPackages.get(userId);
656 if (whitelist == null) {
657 return false;
658 }
659 for (String whitelistedPkg : whitelist) {
660 if (pkg.equals(whitelistedPkg)) {
661 return true;
662 }
663 }
664 return false;
665 }
666
Benjamin Franza83859f2017-07-03 16:34:14 +0100667 /**
Charles Hee078db72017-10-19 18:03:20 +0100668 * Update the UI features that are enabled for LockTask mode.
669 * @param userId Which user these feature flags are associated with
670 * @param flags Bitfield of feature flags
671 * @see DevicePolicyManager#setLockTaskFeatures(ComponentName, int)
672 */
673 void updateLockTaskFeatures(int userId, int flags) {
674 int oldFlags = getLockTaskFeaturesForUser(userId);
675 if (flags == oldFlags) {
676 return;
677 }
678
679 mLockTaskFeatures.put(userId, flags);
Charles Heff9b4dff2017-09-22 10:18:37 +0100680 if (!mLockTaskModeTasks.isEmpty() && userId == mLockTaskModeTasks.get(0).userId) {
Charles Hee078db72017-10-19 18:03:20 +0100681 mHandler.post(() -> {
682 if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) {
683 setStatusBarState(mLockTaskModeState, userId);
684 setKeyguardState(mLockTaskModeState, userId);
685 }
686 });
687 }
688 }
689
690 /**
691 * Helper method for configuring the status bar disabled state.
692 * Should only be called on the handler thread to avoid race.
693 */
694 private void setStatusBarState(int lockTaskModeState, int userId) {
695 IStatusBarService statusBar = getStatusBarService();
696 if (statusBar == null) {
697 Slog.e(TAG, "Can't find StatusBarService");
698 return;
699 }
700
701 // Default state, when lockTaskModeState == LOCK_TASK_MODE_NONE
702 int flags1 = StatusBarManager.DISABLE_NONE;
703 int flags2 = StatusBarManager.DISABLE2_NONE;
704
705 if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
706 flags1 = STATUS_BAR_MASK_PINNED;
707
708 } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
709 int lockTaskFeatures = getLockTaskFeaturesForUser(userId);
710 Pair<Integer, Integer> statusBarFlags = getStatusBarDisableFlags(lockTaskFeatures);
711 flags1 = statusBarFlags.first;
712 flags2 = statusBarFlags.second;
713 }
714
715 try {
716 statusBar.disable(flags1, mToken, mContext.getPackageName());
717 statusBar.disable2(flags2, mToken, mContext.getPackageName());
718 } catch (RemoteException e) {
719 Slog.e(TAG, "Failed to set status bar flags", e);
720 }
721 }
722
723 /**
724 * Helper method for configuring the keyguard disabled state.
725 * Should only be called on the handler thread to avoid race.
726 */
727 private void setKeyguardState(int lockTaskModeState, int userId) {
728 if (lockTaskModeState == LOCK_TASK_MODE_NONE) {
729 mWindowManager.reenableKeyguard(mToken);
730
731 } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
Charles He858f1322017-11-27 17:11:04 -0800732 if (isKeyguardAllowed(userId)) {
Charles Hee078db72017-10-19 18:03:20 +0100733 mWindowManager.reenableKeyguard(mToken);
Charles He858f1322017-11-27 17:11:04 -0800734 } else {
735 mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
Charles Hee078db72017-10-19 18:03:20 +0100736 }
737
738 } else { // lockTaskModeState == LOCK_TASK_MODE_PINNED
739 mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
740 }
741 }
742
743 /**
744 * Helper method for locking the device immediately. This may be necessary when the device
745 * leaves the pinned mode.
746 */
747 private void lockKeyguardIfNeeded() {
748 try {
749 boolean shouldLockKeyguard = Settings.Secure.getIntForUser(
750 mContext.getContentResolver(),
751 Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
752 USER_CURRENT) != 0;
753 if (shouldLockKeyguard) {
754 mWindowManager.lockNow(null);
Lucas Dupinc80c67e2017-12-04 14:29:10 -0800755 mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
Charles Hee078db72017-10-19 18:03:20 +0100756 getLockPatternUtils().requireCredentialEntry(USER_ALL);
757 }
758 } catch (Settings.SettingNotFoundException e) {
759 // No setting, don't lock.
760 }
761 }
762
763 /**
764 * Translates from LockTask feature flags to StatusBarManager disable and disable2 flags.
765 * @param lockTaskFlags Bitfield of flags as per
766 * {@link DevicePolicyManager#setLockTaskFeatures(ComponentName, int)}
767 * @return A {@link Pair} of {@link StatusBarManager#disable(int)} and
768 * {@link StatusBarManager#disable2(int)} flags
769 */
770 @VisibleForTesting
771 Pair<Integer, Integer> getStatusBarDisableFlags(int lockTaskFlags) {
772 // Everything is disabled by default
773 int flags1 = StatusBarManager.DISABLE_MASK;
774 int flags2 = StatusBarManager.DISABLE2_MASK;
775 for (int i = STATUS_BAR_FLAG_MAP_LOCKED.size() - 1; i >= 0; i--) {
776 Pair<Integer, Integer> statusBarFlags = STATUS_BAR_FLAG_MAP_LOCKED.valueAt(i);
777 if ((STATUS_BAR_FLAG_MAP_LOCKED.keyAt(i) & lockTaskFlags) != 0) {
778 flags1 &= ~statusBarFlags.first;
779 flags2 &= ~statusBarFlags.second;
780 }
781 }
782 // Some flags are not used for LockTask purposes, so we mask them
783 flags1 &= STATUS_BAR_MASK_LOCKED;
784 return new Pair<>(flags1, flags2);
785 }
786
787 /**
788 * Gets the cached value of LockTask feature flags for a specific user.
789 */
790 private int getLockTaskFeaturesForUser(int userId) {
791 return mLockTaskFeatures.get(userId, DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
792 }
793
Benjamin Franza83859f2017-07-03 16:34:14 +0100794 // Should only be called on the handler thread
795 @Nullable
796 private IStatusBarService getStatusBarService() {
797 if (mStatusBarService == null) {
798 mStatusBarService = IStatusBarService.Stub.asInterface(
799 ServiceManager.checkService(STATUS_BAR_SERVICE));
800 if (mStatusBarService == null) {
801 Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE");
802 }
803 }
804 return mStatusBarService;
805 }
806
807 // Should only be called on the handler thread
808 @Nullable
809 private IDevicePolicyManager getDevicePolicyManager() {
810 if (mDevicePolicyManager == null) {
811 mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface(
812 ServiceManager.checkService(DEVICE_POLICY_SERVICE));
813 if (mDevicePolicyManager == null) {
814 Slog.w(TAG, "warning: no DEVICE_POLICY_SERVICE");
815 }
816 }
817 return mDevicePolicyManager;
818 }
819
820 @NonNull
821 private LockPatternUtils getLockPatternUtils() {
822 if (mLockPatternUtils == null) {
823 // We don't preserve the LPU object to save memory
824 return new LockPatternUtils(mContext);
825 }
826 return mLockPatternUtils;
827 }
828
Charles He858f1322017-11-27 17:11:04 -0800829 @Nullable
830 private TelecomManager getTelecomManager() {
831 if (mTelecomManager == null) {
832 // We don't preserve the TelecomManager object to save memory
833 return mContext.getSystemService(TelecomManager.class);
834 }
835 return mTelecomManager;
836 }
837
Benjamin Franza83859f2017-07-03 16:34:14 +0100838 // Should only be called on the handler thread
839 @NonNull
840 private LockTaskNotify getLockTaskNotify() {
841 if (mLockTaskNotify == null) {
842 mLockTaskNotify = new LockTaskNotify(mContext);
843 }
844 return mLockTaskNotify;
845 }
846
847 public void dump(PrintWriter pw, String prefix) {
Charles He520b2832017-09-02 15:27:16 +0100848 pw.println(prefix + "LockTaskController");
849 prefix = prefix + " ";
850 pw.println(prefix + "mLockTaskModeState=" + lockTaskModeToString());
851 pw.println(prefix + "mLockTaskModeTasks=");
852 for (int i = 0; i < mLockTaskModeTasks.size(); ++i) {
853 pw.println(prefix + " #" + i + " " + mLockTaskModeTasks.get(i));
854 }
855 pw.println(prefix + "mLockTaskPackages (userId:packages)=");
856 for (int i = 0; i < mLockTaskPackages.size(); ++i) {
857 pw.println(prefix + " u" + mLockTaskPackages.keyAt(i)
858 + ":" + Arrays.toString(mLockTaskPackages.valueAt(i)));
859 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100860 }
861
862 private String lockTaskModeToString() {
863 switch (mLockTaskModeState) {
864 case LOCK_TASK_MODE_LOCKED:
865 return "LOCKED";
866 case LOCK_TASK_MODE_PINNED:
867 return "PINNED";
868 case LOCK_TASK_MODE_NONE:
869 return "NONE";
870 default: return "unknown=" + mLockTaskModeState;
871 }
872 }
873}