1 /*
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 
17 package com.android.server.am;
18 
19 import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
20 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
21 import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
22 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
23 import static android.content.Context.DEVICE_POLICY_SERVICE;
24 import static android.content.Context.STATUS_BAR_SERVICE;
25 import static android.content.Intent.ACTION_CALL_EMERGENCY;
26 import static android.os.UserHandle.USER_ALL;
27 import static android.os.UserHandle.USER_CURRENT;
28 import static android.telecom.TelecomManager.EMERGENCY_DIALER_COMPONENT;
29 import static android.view.Display.DEFAULT_DISPLAY;
30 
31 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
32 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
33 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
34 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
35 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
36 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
37 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
38 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
39 import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
40 
41 import android.annotation.NonNull;
42 import android.annotation.Nullable;
43 import android.app.Activity;
44 import android.app.ActivityManager;
45 import android.app.StatusBarManager;
46 import android.app.admin.DevicePolicyManager;
47 import android.app.admin.IDevicePolicyManager;
48 import android.content.ComponentName;
49 import android.content.Context;
50 import android.content.Intent;
51 import android.os.Binder;
52 import android.os.Debug;
53 import android.os.Handler;
54 import android.os.IBinder;
55 import android.os.RemoteException;
56 import android.os.ServiceManager;
57 import android.provider.Settings;
58 import android.telecom.TelecomManager;
59 import android.util.Pair;
60 import android.util.Slog;
61 import android.util.SparseArray;
62 import android.util.SparseIntArray;
63 
64 import com.android.internal.annotations.VisibleForTesting;
65 import com.android.internal.policy.IKeyguardDismissCallback;
66 import com.android.internal.statusbar.IStatusBarService;
67 import com.android.internal.widget.LockPatternUtils;
68 import com.android.server.LocalServices;
69 import com.android.server.statusbar.StatusBarManagerInternal;
70 import com.android.server.wm.WindowManagerService;
71 
72 import java.io.PrintWriter;
73 import java.util.ArrayList;
74 import java.util.Arrays;
75 
76 /**
77  * Helper class that deals with all things related to task locking. This includes the screen pinning
78  * mode that can be launched via System UI as well as the fully locked mode that can be achieved
79  * on fully managed devices.
80  *
81  * Note: All methods in this class should only be called with the ActivityManagerService lock held.
82  *
83  * @see Activity#startLockTask()
84  * @see Activity#stopLockTask()
85  */
86 public class LockTaskController {
87     private static final String TAG = TAG_WITH_CLASS_NAME ? "LockTaskController" : TAG_AM;
88     private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
89 
90     @VisibleForTesting
91     static final int STATUS_BAR_MASK_LOCKED = StatusBarManager.DISABLE_MASK
92             & (~StatusBarManager.DISABLE_EXPAND)
93             & (~StatusBarManager.DISABLE_NOTIFICATION_TICKER)
94             & (~StatusBarManager.DISABLE_SYSTEM_INFO)
95             & (~StatusBarManager.DISABLE_BACK);
96     @VisibleForTesting
97     static final int STATUS_BAR_MASK_PINNED = StatusBarManager.DISABLE_MASK
98             & (~StatusBarManager.DISABLE_BACK)
99             & (~StatusBarManager.DISABLE_HOME)
100             & (~StatusBarManager.DISABLE_RECENT);
101 
102     private static final SparseArray<Pair<Integer, Integer>> STATUS_BAR_FLAG_MAP_LOCKED;
103     static {
104         STATUS_BAR_FLAG_MAP_LOCKED = new SparseArray<>();
105 
STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO, new Pair<>(StatusBarManager.DISABLE_CLOCK, StatusBarManager.DISABLE2_SYSTEM_ICONS))106         STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO,
107                 new Pair<>(StatusBarManager.DISABLE_CLOCK, StatusBarManager.DISABLE2_SYSTEM_ICONS));
108 
STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS, new Pair<>(StatusBarManager.DISABLE_NOTIFICATION_ICONS | StatusBarManager.DISABLE_NOTIFICATION_ALERTS, StatusBarManager.DISABLE2_NOTIFICATION_SHADE))109         STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS,
110                 new Pair<>(StatusBarManager.DISABLE_NOTIFICATION_ICONS
111                         | StatusBarManager.DISABLE_NOTIFICATION_ALERTS,
112                         StatusBarManager.DISABLE2_NOTIFICATION_SHADE));
113 
STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_HOME, new Pair<>(StatusBarManager.DISABLE_HOME, StatusBarManager.DISABLE2_NONE))114         STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_HOME,
115                 new Pair<>(StatusBarManager.DISABLE_HOME, StatusBarManager.DISABLE2_NONE));
116 
STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW, new Pair<>(StatusBarManager.DISABLE_RECENT, StatusBarManager.DISABLE2_NONE))117         STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW,
118                 new Pair<>(StatusBarManager.DISABLE_RECENT, StatusBarManager.DISABLE2_NONE));
119 
STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS, new Pair<>(StatusBarManager.DISABLE_NONE, StatusBarManager.DISABLE2_GLOBAL_ACTIONS))120         STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS,
121                 new Pair<>(StatusBarManager.DISABLE_NONE,
122                         StatusBarManager.DISABLE2_GLOBAL_ACTIONS));
123     }
124 
125     /** Tag used for disabling of keyguard */
126     private static final String LOCK_TASK_TAG = "Lock-to-App";
127 
128     private final IBinder mToken = new Binder();
129     private final ActivityStackSupervisor mSupervisor;
130     private final Context mContext;
131 
132     // The following system services cannot be final, because they do not exist when this class
133     // is instantiated during device boot
134     @VisibleForTesting
135     IStatusBarService mStatusBarService;
136     @VisibleForTesting
137     IDevicePolicyManager mDevicePolicyManager;
138     @VisibleForTesting
139     WindowManagerService mWindowManager;
140     @VisibleForTesting
141     LockPatternUtils mLockPatternUtils;
142     @VisibleForTesting
143     TelecomManager mTelecomManager;
144 
145     /**
146      * The chain of tasks in LockTask mode, in the order of when they first entered LockTask mode.
147      *
148      * The first task in the list, which started the current LockTask session, is called the root
149      * task. It coincides with the Home task in a typical multi-app kiosk deployment. When there are
150      * more than one locked tasks, the root task can't be finished. Nor can it be moved to the back
151      * of the stack by {@link ActivityStack#moveTaskToBackLocked(int)};
152      *
153      * Calling {@link Activity#stopLockTask()} on the root task will finish all tasks but itself in
154      * this list, and the device will exit LockTask mode.
155      *
156      * The list is empty if LockTask is inactive.
157      */
158     private final ArrayList<TaskRecord> mLockTaskModeTasks = new ArrayList<>();
159 
160     /**
161      * Packages that are allowed to be launched into the lock task mode for each user.
162      */
163     private final SparseArray<String[]> mLockTaskPackages = new SparseArray<>();
164 
165     /**
166      * Features that are allowed by DPC to show during LockTask mode.
167      */
168     private final SparseIntArray mLockTaskFeatures = new SparseIntArray();
169 
170     /**
171      * Store the current lock task mode. Possible values:
172      * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
173      * {@link ActivityManager#LOCK_TASK_MODE_PINNED}
174      */
175     private int mLockTaskModeState = LOCK_TASK_MODE_NONE;
176 
177     /**
178      * This is ActivityStackSupervisor's Handler.
179      */
180     private final Handler mHandler;
181 
LockTaskController(Context context, ActivityStackSupervisor supervisor, Handler handler)182     LockTaskController(Context context, ActivityStackSupervisor supervisor,
183             Handler handler) {
184         mContext = context;
185         mSupervisor = supervisor;
186         mHandler = handler;
187     }
188 
189     /**
190      * Set the window manager instance used in this class. This is necessary, because the window
191      * manager does not exist during instantiation of this class.
192      */
setWindowManager(WindowManagerService windowManager)193     void setWindowManager(WindowManagerService windowManager) {
194         mWindowManager = windowManager;
195     }
196 
197     /**
198      * @return the current lock task state. This can be any of
199      * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
200      * {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
201      */
getLockTaskModeState()202     int getLockTaskModeState() {
203         return mLockTaskModeState;
204     }
205 
206     /**
207      * @return whether the given task is locked at the moment. Locked tasks cannot be moved to the
208      * back of the stack.
209      */
210     @VisibleForTesting
isTaskLocked(TaskRecord task)211     boolean isTaskLocked(TaskRecord task) {
212         return mLockTaskModeTasks.contains(task);
213     }
214 
215     /**
216      * @return {@code true} whether this task first started the current LockTask session.
217      */
isRootTask(TaskRecord task)218     private boolean isRootTask(TaskRecord task) {
219         return mLockTaskModeTasks.indexOf(task) == 0;
220     }
221 
222     /**
223      * @return whether the given activity is blocked from finishing, because it is the only activity
224      * of the last locked task and finishing it would mean that lock task mode is ended illegally.
225      */
activityBlockedFromFinish(ActivityRecord activity)226     boolean activityBlockedFromFinish(ActivityRecord activity) {
227         final TaskRecord task = activity.getTask();
228         if (activity == task.getRootActivity()
229                 && activity == task.getTopActivity()
230                 && task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV
231                 && isRootTask(task)) {
232             Slog.i(TAG, "Not finishing task in lock task mode");
233             showLockTaskToast();
234             return true;
235         }
236         return false;
237     }
238 
239     /**
240      * @return whether the given task can be moved to the back of the stack with
241      * {@link ActivityStack#moveTaskToBackLocked(int)}
242      * @see #mLockTaskModeTasks
243      */
canMoveTaskToBack(TaskRecord task)244     boolean canMoveTaskToBack(TaskRecord task) {
245         if (isRootTask(task)) {
246             showLockTaskToast();
247             return false;
248         }
249         return true;
250     }
251 
252     /**
253      * @return whether the requested task is allowed to be locked (either whitelisted, or declares
254      * lockTaskMode="always" in the manifest).
255      */
isTaskWhitelisted(TaskRecord task)256     boolean isTaskWhitelisted(TaskRecord task) {
257         switch(task.mLockTaskAuth) {
258             case LOCK_TASK_AUTH_WHITELISTED:
259             case LOCK_TASK_AUTH_LAUNCHABLE:
260             case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
261                 return true;
262             case LOCK_TASK_AUTH_PINNABLE:
263             case LOCK_TASK_AUTH_DONT_LOCK:
264             default:
265                 return false;
266         }
267     }
268 
269     /**
270      * @return whether the requested task is disallowed to be launched.
271      */
isLockTaskModeViolation(TaskRecord task)272     boolean isLockTaskModeViolation(TaskRecord task) {
273         return isLockTaskModeViolation(task, false);
274     }
275 
276     /**
277      * @param isNewClearTask whether the task would be cleared as part of the operation.
278      * @return whether the requested task is disallowed to be launched.
279      */
isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask)280     boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) {
281         if (isLockTaskModeViolationInternal(task, isNewClearTask)) {
282             showLockTaskToast();
283             return true;
284         }
285         return false;
286     }
287 
288     /**
289      * @return the root task of the lock task.
290      */
getRootTask()291     TaskRecord getRootTask() {
292         if (mLockTaskModeTasks.isEmpty()) {
293             return null;
294         }
295         return mLockTaskModeTasks.get(0);
296     }
297 
isLockTaskModeViolationInternal(TaskRecord task, boolean isNewClearTask)298     private boolean isLockTaskModeViolationInternal(TaskRecord task, boolean isNewClearTask) {
299         // TODO: Double check what's going on here. If the task is already in lock task mode, it's
300         // likely whitelisted, so will return false below.
301         if (isTaskLocked(task) && !isNewClearTask) {
302             // If the task is already at the top and won't be cleared, then allow the operation
303             return false;
304         }
305 
306         // Allow recents activity if enabled by policy
307         if (task.isActivityTypeRecents() && isRecentsAllowed(task.userId)) {
308             return false;
309         }
310 
311         // Allow emergency calling when the device is protected by a locked keyguard
312         if (isKeyguardAllowed(task.userId) && isEmergencyCallTask(task)) {
313             return false;
314         }
315 
316         return !(isTaskWhitelisted(task) || mLockTaskModeTasks.isEmpty());
317     }
318 
isRecentsAllowed(int userId)319     private boolean isRecentsAllowed(int userId) {
320         return (getLockTaskFeaturesForUser(userId)
321                 & DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW) != 0;
322     }
323 
isKeyguardAllowed(int userId)324     private boolean isKeyguardAllowed(int userId) {
325         return (getLockTaskFeaturesForUser(userId)
326                 & DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD) != 0;
327     }
328 
isEmergencyCallTask(TaskRecord task)329     private boolean isEmergencyCallTask(TaskRecord task) {
330         final Intent intent = task.intent;
331         if (intent == null) {
332             return false;
333         }
334 
335         // 1. The emergency keypad activity launched on top of the keyguard
336         if (EMERGENCY_DIALER_COMPONENT.equals(intent.getComponent())) {
337             return true;
338         }
339 
340         // 2. The intent sent by the keypad, which is handled by Telephony
341         if (ACTION_CALL_EMERGENCY.equals(intent.getAction())) {
342             return true;
343         }
344 
345         // 3. Telephony then starts the default package for making the call
346         final TelecomManager tm = getTelecomManager();
347         final String dialerPackage = tm != null ? tm.getSystemDialerPackage() : null;
348         if (dialerPackage != null && dialerPackage.equals(intent.getComponent().getPackageName())) {
349             return true;
350         }
351 
352         return false;
353     }
354 
355     /**
356      * Stop the current lock task mode.
357      *
358      * This is called by {@link ActivityManagerService} and performs various checks before actually
359      * finishing the locked task.
360      *
361      * @param task the task that requested the end of lock task mode ({@code null} for quitting app
362      *             pinning mode)
363      * @param isSystemCaller indicates whether this request comes from the system via
364      *                       {@link ActivityManagerService#stopSystemLockTaskMode()}. If
365      *                       {@code true}, it means the user intends to stop pinned mode through UI;
366      *                       otherwise, it's called by an app and we need to stop locked or pinned
367      *                       mode, subject to checks.
368      * @param callingUid the caller that requested the end of lock task mode.
369      * @throws IllegalArgumentException if the calling task is invalid (e.g., {@code null} or not in
370      *                                  foreground)
371      * @throws SecurityException if the caller is not authorized to stop the lock task mode, i.e. if
372      *                           they differ from the one that launched lock task mode.
373      */
stopLockTaskMode(@ullable TaskRecord task, boolean isSystemCaller, int callingUid)374     void stopLockTaskMode(@Nullable TaskRecord task, boolean isSystemCaller, int callingUid) {
375         if (mLockTaskModeState == LOCK_TASK_MODE_NONE) {
376             return;
377         }
378 
379         if (isSystemCaller) {
380             if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
381                 clearLockedTasks("stopAppPinning");
382             } else {
383                 Slog.e(TAG_LOCKTASK, "Attempted to stop LockTask with isSystemCaller=true");
384                 showLockTaskToast();
385             }
386 
387         } else {
388             // Ensure calling activity is not null
389             if (task == null) {
390                 throw new IllegalArgumentException("can't stop LockTask for null task");
391             }
392 
393             // Ensure the same caller for startLockTaskMode and stopLockTaskMode.
394             // It is possible lockTaskMode was started by the system process because
395             // android:lockTaskMode is set to a locking value in the application manifest
396             // instead of the app calling startLockTaskMode. In this case
397             // {@link TaskRecord.mLockTaskUid} will be 0, so we compare the callingUid to the
398             // {@link TaskRecord.effectiveUid} instead. Also caller with
399             // {@link MANAGE_ACTIVITY_STACKS} can stop any lock task.
400             if (callingUid != task.mLockTaskUid
401                     && (task.mLockTaskUid != 0 || callingUid != task.effectiveUid)) {
402                 throw new SecurityException("Invalid uid, expected " + task.mLockTaskUid
403                         + " callingUid=" + callingUid + " effectiveUid=" + task.effectiveUid);
404             }
405 
406             // We don't care if it's pinned or locked mode; this will stop it anyways.
407             clearLockedTask(task);
408         }
409     }
410 
411     /**
412      * Clear all locked tasks and request the end of LockTask mode.
413      *
414      * This method is called by {@link UserController} when starting a new foreground user, and,
415      * unlike {@link #stopLockTaskMode(TaskRecord, boolean, int)}, it doesn't perform the checks.
416      */
clearLockedTasks(String reason)417     void clearLockedTasks(String reason) {
418         if (DEBUG_LOCKTASK) Slog.i(TAG_LOCKTASK, "clearLockedTasks: " + reason);
419         if (!mLockTaskModeTasks.isEmpty()) {
420             clearLockedTask(mLockTaskModeTasks.get(0));
421         }
422     }
423 
424     /**
425      * Clear one locked task from LockTask mode.
426      *
427      * If the requested task is the root task (see {@link #mLockTaskModeTasks}), then all locked
428      * tasks are cleared. Otherwise, only the requested task is cleared. LockTask mode is stopped
429      * when the last locked task is cleared.
430      *
431      * @param task the task to be cleared from LockTask mode.
432      */
clearLockedTask(final TaskRecord task)433     void clearLockedTask(final TaskRecord task) {
434         if (task == null || mLockTaskModeTasks.isEmpty()) return;
435 
436         if (task == mLockTaskModeTasks.get(0)) {
437             // We're removing the root task while there are other locked tasks. Therefore we should
438             // clear all locked tasks in reverse order.
439             for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx > 0; --taskNdx) {
440                 clearLockedTask(mLockTaskModeTasks.get(taskNdx));
441             }
442         }
443 
444         removeLockedTask(task);
445         if (mLockTaskModeTasks.isEmpty()) {
446             return;
447         }
448         task.performClearTaskLocked();
449         mSupervisor.resumeFocusedStackTopActivityLocked();
450     }
451 
452     /**
453      * Remove the given task from the locked task list. If this was the last task in the list,
454      * lock task mode is stopped.
455      */
removeLockedTask(final TaskRecord task)456     private void removeLockedTask(final TaskRecord task) {
457         if (!mLockTaskModeTasks.remove(task)) {
458             return;
459         }
460         if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: removed " + task);
461         if (mLockTaskModeTasks.isEmpty()) {
462             if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: task=" + task +
463                     " last task, reverting locktask mode. Callers=" + Debug.getCallers(3));
464             mHandler.post(() -> performStopLockTask(task.userId));
465         }
466     }
467 
468     // This method should only be called on the handler thread
performStopLockTask(int userId)469     private void performStopLockTask(int userId) {
470         // When lock task ends, we enable the status bars.
471         try {
472             setStatusBarState(LOCK_TASK_MODE_NONE, userId);
473             setKeyguardState(LOCK_TASK_MODE_NONE, userId);
474             if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
475                 lockKeyguardIfNeeded();
476             }
477             if (getDevicePolicyManager() != null) {
478                 getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId);
479             }
480             if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
481                 getStatusBarService().showPinningEnterExitToast(false /* entering */);
482             }
483             mWindowManager.onLockTaskStateChanged(LOCK_TASK_MODE_NONE);
484         } catch (RemoteException ex) {
485             throw new RuntimeException(ex);
486         } finally {
487             mLockTaskModeState = LOCK_TASK_MODE_NONE;
488         }
489     }
490 
491     /**
492      * Show the lock task violation toast. Currently we only show toast for screen pinning mode, and
493      * no-op if the device is in locked mode.
494      */
showLockTaskToast()495     void showLockTaskToast() {
496         if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
497             try {
498                 getStatusBarService().showPinningEscapeToast();
499             } catch (RemoteException e) {
500                 Slog.e(TAG, "Failed to send pinning escape toast", e);
501             }
502         }
503     }
504 
505     // Starting lock task
506 
507     /**
508      * Method to start lock task mode on a given task.
509      *
510      * @param task the task that should be locked.
511      * @param isSystemCaller indicates whether this request was initiated by the system via
512      *                       {@link ActivityManagerService#startSystemLockTaskMode(int)}. If
513      *                       {@code true}, this intends to start pinned mode; otherwise, we look
514      *                       at the calling task's mLockTaskAuth to decide which mode to start.
515      * @param callingUid the caller that requested the launch of lock task mode.
516      */
startLockTaskMode(@onNull TaskRecord task, boolean isSystemCaller, int callingUid)517     void startLockTaskMode(@NonNull TaskRecord task, boolean isSystemCaller, int callingUid) {
518         if (!isSystemCaller) {
519             task.mLockTaskUid = callingUid;
520             if (task.mLockTaskAuth == LOCK_TASK_AUTH_PINNABLE) {
521                 // startLockTask() called by app, but app is not part of lock task whitelist. Show
522                 // app pinning request. We will come back here with isSystemCaller true.
523                 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Mode default, asking user");
524                 StatusBarManagerInternal statusBarManager = LocalServices.getService(
525                         StatusBarManagerInternal.class);
526                 if (statusBarManager != null) {
527                     statusBarManager.showScreenPinningRequest(task.taskId);
528                 }
529                 return;
530             }
531         }
532 
533         // System can only initiate screen pinning, not full lock task mode
534         if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
535                 isSystemCaller ? "Locking pinned" : "Locking fully");
536         setLockTaskMode(task, isSystemCaller ? LOCK_TASK_MODE_PINNED : LOCK_TASK_MODE_LOCKED,
537                 "startLockTask", true);
538     }
539 
540     /**
541      * Start lock task mode on the given task.
542      * @param lockTaskModeState whether fully locked or pinned mode.
543      * @param andResume whether the task should be brought to foreground as part of the operation.
544      */
setLockTaskMode(@onNull TaskRecord task, int lockTaskModeState, String reason, boolean andResume)545     private void setLockTaskMode(@NonNull TaskRecord task, int lockTaskModeState,
546                                  String reason, boolean andResume) {
547         // Should have already been checked, but do it again.
548         if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) {
549             if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
550                     "setLockTaskMode: Can't lock due to auth");
551             return;
552         }
553         if (isLockTaskModeViolation(task)) {
554             Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task.");
555             return;
556         }
557 
558         final Intent taskIntent = task.intent;
559         if (mLockTaskModeTasks.isEmpty() && taskIntent != null) {
560             mSupervisor.mRecentTasks.onLockTaskModeStateChanged(lockTaskModeState, task.userId);
561             // Start lock task on the handler thread
562             mHandler.post(() -> performStartLockTask(
563                     taskIntent.getComponent().getPackageName(),
564                     task.userId,
565                     lockTaskModeState));
566         }
567         if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskMode: Locking to " + task +
568                 " Callers=" + Debug.getCallers(4));
569 
570         if (!mLockTaskModeTasks.contains(task)) {
571             mLockTaskModeTasks.add(task);
572         }
573 
574         if (task.mLockTaskUid == -1) {
575             task.mLockTaskUid = task.effectiveUid;
576         }
577 
578         if (andResume) {
579             mSupervisor.findTaskToMoveToFront(task, 0, null, reason,
580                     lockTaskModeState != LOCK_TASK_MODE_NONE);
581             mSupervisor.resumeFocusedStackTopActivityLocked();
582             mWindowManager.executeAppTransition();
583         } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
584             mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED,
585                     DEFAULT_DISPLAY, task.getStack(), true /* forceNonResizable */);
586         }
587     }
588 
589     // This method should only be called on the handler thread
performStartLockTask(String packageName, int userId, int lockTaskModeState)590     private void performStartLockTask(String packageName, int userId, int lockTaskModeState) {
591         // When lock task starts, we disable the status bars.
592         try {
593             if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
594                 getStatusBarService().showPinningEnterExitToast(true /* entering */);
595             }
596             mWindowManager.onLockTaskStateChanged(lockTaskModeState);
597             mLockTaskModeState = lockTaskModeState;
598             setStatusBarState(lockTaskModeState, userId);
599             setKeyguardState(lockTaskModeState, userId);
600             if (getDevicePolicyManager() != null) {
601                 getDevicePolicyManager().notifyLockTaskModeChanged(true, packageName, userId);
602             }
603         } catch (RemoteException ex) {
604             throw new RuntimeException(ex);
605         }
606     }
607 
608     /**
609      * Update packages that are allowed to be launched in lock task mode.
610      * @param userId Which user this whitelist is associated with
611      * @param packages The whitelist of packages allowed in lock task mode
612      * @see #mLockTaskPackages
613      */
updateLockTaskPackages(int userId, String[] packages)614     void updateLockTaskPackages(int userId, String[] packages) {
615         mLockTaskPackages.put(userId, packages);
616 
617         boolean taskChanged = false;
618         for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) {
619             final TaskRecord lockedTask = mLockTaskModeTasks.get(taskNdx);
620             final boolean wasWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
621                     || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
622             lockedTask.setLockTaskAuth();
623             final boolean isWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
624                     || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
625 
626             if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED
627                     || lockedTask.userId != userId
628                     || !wasWhitelisted || isWhitelisted) {
629                 continue;
630             }
631 
632             // Terminate locked tasks that have recently lost whitelist authorization.
633             if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " +
634                     lockedTask + " mLockTaskAuth()=" + lockedTask.lockTaskAuthToString());
635             removeLockedTask(lockedTask);
636             lockedTask.performClearTaskLocked();
637             taskChanged = true;
638         }
639 
640         for (int displayNdx = mSupervisor.getChildCount() - 1; displayNdx >= 0; --displayNdx) {
641             mSupervisor.getChildAt(displayNdx).onLockTaskPackagesUpdated();
642         }
643 
644         final ActivityRecord r = mSupervisor.topRunningActivityLocked();
645         final TaskRecord task = (r != null) ? r.getTask() : null;
646         if (mLockTaskModeTasks.isEmpty() && task!= null
647                 && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
648             // This task must have just been authorized.
649             if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK,
650                     "onLockTaskPackagesUpdated: starting new locktask task=" + task);
651             setLockTaskMode(task, LOCK_TASK_MODE_LOCKED, "package updated", false);
652             taskChanged = true;
653         }
654 
655         if (taskChanged) {
656             mSupervisor.resumeFocusedStackTopActivityLocked();
657         }
658     }
659 
isPackageWhitelisted(int userId, String pkg)660     boolean isPackageWhitelisted(int userId, String pkg) {
661         if (pkg == null) {
662             return false;
663         }
664         String[] whitelist;
665         whitelist = mLockTaskPackages.get(userId);
666         if (whitelist == null) {
667             return false;
668         }
669         for (String whitelistedPkg : whitelist) {
670             if (pkg.equals(whitelistedPkg)) {
671                 return true;
672             }
673         }
674         return false;
675     }
676 
677     /**
678      * Update the UI features that are enabled for LockTask mode.
679      * @param userId Which user these feature flags are associated with
680      * @param flags Bitfield of feature flags
681      * @see DevicePolicyManager#setLockTaskFeatures(ComponentName, int)
682      */
updateLockTaskFeatures(int userId, int flags)683     void updateLockTaskFeatures(int userId, int flags) {
684         int oldFlags = getLockTaskFeaturesForUser(userId);
685         if (flags == oldFlags) {
686             return;
687         }
688 
689         mLockTaskFeatures.put(userId, flags);
690         if (!mLockTaskModeTasks.isEmpty() && userId == mLockTaskModeTasks.get(0).userId) {
691             mHandler.post(() -> {
692                 if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) {
693                     setStatusBarState(mLockTaskModeState, userId);
694                     setKeyguardState(mLockTaskModeState, userId);
695                 }
696             });
697         }
698     }
699 
700     /**
701      * Helper method for configuring the status bar disabled state.
702      * Should only be called on the handler thread to avoid race.
703      */
setStatusBarState(int lockTaskModeState, int userId)704     private void setStatusBarState(int lockTaskModeState, int userId) {
705         IStatusBarService statusBar = getStatusBarService();
706         if (statusBar == null) {
707             Slog.e(TAG, "Can't find StatusBarService");
708             return;
709         }
710 
711         // Default state, when lockTaskModeState == LOCK_TASK_MODE_NONE
712         int flags1 = StatusBarManager.DISABLE_NONE;
713         int flags2 = StatusBarManager.DISABLE2_NONE;
714 
715         if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
716             flags1 = STATUS_BAR_MASK_PINNED;
717 
718         } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
719             int lockTaskFeatures = getLockTaskFeaturesForUser(userId);
720             Pair<Integer, Integer> statusBarFlags = getStatusBarDisableFlags(lockTaskFeatures);
721             flags1 = statusBarFlags.first;
722             flags2 = statusBarFlags.second;
723         }
724 
725         try {
726             statusBar.disable(flags1, mToken, mContext.getPackageName());
727             statusBar.disable2(flags2, mToken, mContext.getPackageName());
728         } catch (RemoteException e) {
729             Slog.e(TAG, "Failed to set status bar flags", e);
730         }
731     }
732 
733     /**
734      * Helper method for configuring the keyguard disabled state.
735      * Should only be called on the handler thread to avoid race.
736      */
setKeyguardState(int lockTaskModeState, int userId)737     private void setKeyguardState(int lockTaskModeState, int userId) {
738         if (lockTaskModeState == LOCK_TASK_MODE_NONE) {
739             mWindowManager.reenableKeyguard(mToken);
740 
741         } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
742             if (isKeyguardAllowed(userId)) {
743                 mWindowManager.reenableKeyguard(mToken);
744             } else {
745                 // If keyguard is not secure and it is locked, dismiss the keyguard before
746                 // disabling it, which avoids the platform to think the keyguard is still on.
747                 if (mWindowManager.isKeyguardLocked() && !mWindowManager.isKeyguardSecure()) {
748                     mWindowManager.dismissKeyguard(new IKeyguardDismissCallback.Stub() {
749                         @Override
750                         public void onDismissError() throws RemoteException {
751                             Slog.i(TAG, "setKeyguardState: failed to dismiss keyguard");
752                         }
753 
754                         @Override
755                         public void onDismissSucceeded() throws RemoteException {
756                             mHandler.post(
757                                     () -> mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG));
758                         }
759 
760                         @Override
761                         public void onDismissCancelled() throws RemoteException {
762                             Slog.i(TAG, "setKeyguardState: dismiss cancelled");
763                         }
764                     }, null);
765                 } else {
766                     mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
767                 }
768             }
769 
770         } else { // lockTaskModeState == LOCK_TASK_MODE_PINNED
771             mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
772         }
773     }
774 
775     /**
776      * Helper method for locking the device immediately. This may be necessary when the device
777      * leaves the pinned mode.
778      */
lockKeyguardIfNeeded()779     private void lockKeyguardIfNeeded() {
780         try {
781             boolean shouldLockKeyguard = Settings.Secure.getIntForUser(
782                     mContext.getContentResolver(),
783                     Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
784                     USER_CURRENT) != 0;
785             if (shouldLockKeyguard) {
786                 mWindowManager.lockNow(null);
787                 mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
788                 getLockPatternUtils().requireCredentialEntry(USER_ALL);
789             }
790         } catch (Settings.SettingNotFoundException e) {
791             // No setting, don't lock.
792         }
793     }
794 
795     /**
796      * Translates from LockTask feature flags to StatusBarManager disable and disable2 flags.
797      * @param lockTaskFlags Bitfield of flags as per
798      *                      {@link DevicePolicyManager#setLockTaskFeatures(ComponentName, int)}
799      * @return A {@link Pair} of {@link StatusBarManager#disable(int)} and
800      *         {@link StatusBarManager#disable2(int)} flags
801      */
802     @VisibleForTesting
getStatusBarDisableFlags(int lockTaskFlags)803     Pair<Integer, Integer> getStatusBarDisableFlags(int lockTaskFlags) {
804         // Everything is disabled by default
805         int flags1 = StatusBarManager.DISABLE_MASK;
806         int flags2 = StatusBarManager.DISABLE2_MASK;
807         for (int i = STATUS_BAR_FLAG_MAP_LOCKED.size() - 1; i >= 0; i--) {
808             Pair<Integer, Integer> statusBarFlags = STATUS_BAR_FLAG_MAP_LOCKED.valueAt(i);
809             if ((STATUS_BAR_FLAG_MAP_LOCKED.keyAt(i) & lockTaskFlags) != 0) {
810                 flags1 &= ~statusBarFlags.first;
811                 flags2 &= ~statusBarFlags.second;
812             }
813         }
814         // Some flags are not used for LockTask purposes, so we mask them
815         flags1 &= STATUS_BAR_MASK_LOCKED;
816         return new Pair<>(flags1, flags2);
817     }
818 
819     /**
820      * Gets the cached value of LockTask feature flags for a specific user.
821      */
getLockTaskFeaturesForUser(int userId)822     private int getLockTaskFeaturesForUser(int userId) {
823         return mLockTaskFeatures.get(userId, DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
824     }
825 
826     // Should only be called on the handler thread
827     @Nullable
getStatusBarService()828     private IStatusBarService getStatusBarService() {
829         if (mStatusBarService == null) {
830             mStatusBarService = IStatusBarService.Stub.asInterface(
831                     ServiceManager.checkService(STATUS_BAR_SERVICE));
832             if (mStatusBarService == null) {
833                 Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE");
834             }
835         }
836         return mStatusBarService;
837     }
838 
839     // Should only be called on the handler thread
840     @Nullable
getDevicePolicyManager()841     private IDevicePolicyManager getDevicePolicyManager() {
842         if (mDevicePolicyManager == null) {
843             mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface(
844                     ServiceManager.checkService(DEVICE_POLICY_SERVICE));
845             if (mDevicePolicyManager == null) {
846                 Slog.w(TAG, "warning: no DEVICE_POLICY_SERVICE");
847             }
848         }
849         return mDevicePolicyManager;
850     }
851 
852     @NonNull
getLockPatternUtils()853     private LockPatternUtils getLockPatternUtils() {
854         if (mLockPatternUtils == null) {
855             // We don't preserve the LPU object to save memory
856             return new LockPatternUtils(mContext);
857         }
858         return mLockPatternUtils;
859     }
860 
861     @Nullable
getTelecomManager()862     private TelecomManager getTelecomManager() {
863         if (mTelecomManager == null) {
864             // We don't preserve the TelecomManager object to save memory
865             return mContext.getSystemService(TelecomManager.class);
866         }
867         return mTelecomManager;
868     }
869 
dump(PrintWriter pw, String prefix)870     public void dump(PrintWriter pw, String prefix) {
871         pw.println(prefix + "LockTaskController");
872         prefix = prefix + "  ";
873         pw.println(prefix + "mLockTaskModeState=" + lockTaskModeToString());
874         pw.println(prefix + "mLockTaskModeTasks=");
875         for (int i = 0; i < mLockTaskModeTasks.size(); ++i) {
876             pw.println(prefix + "  #" + i + " " + mLockTaskModeTasks.get(i));
877         }
878         pw.println(prefix + "mLockTaskPackages (userId:packages)=");
879         for (int i = 0; i < mLockTaskPackages.size(); ++i) {
880             pw.println(prefix + "  u" + mLockTaskPackages.keyAt(i)
881                     + ":" + Arrays.toString(mLockTaskPackages.valueAt(i)));
882         }
883     }
884 
lockTaskModeToString()885     private String lockTaskModeToString() {
886         switch (mLockTaskModeState) {
887             case LOCK_TASK_MODE_LOCKED:
888                 return "LOCKED";
889             case LOCK_TASK_MODE_PINNED:
890                 return "PINNED";
891             case LOCK_TASK_MODE_NONE:
892                 return "NONE";
893             default: return "unknown=" + mLockTaskModeState;
894         }
895     }
896 }
897