• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.wm;
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_PINNED;
23 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
24 import static android.content.Context.DEVICE_POLICY_SERVICE;
25 import static android.content.Context.STATUS_BAR_SERVICE;
26 import static android.content.Intent.ACTION_CALL_EMERGENCY;
27 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
28 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
29 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED;
30 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
31 import static android.os.UserHandle.USER_ALL;
32 import static android.os.UserHandle.USER_CURRENT;
33 import static android.telecom.TelecomManager.EMERGENCY_DIALER_COMPONENT;
34 
35 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_LOCKTASK;
36 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
37 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
38 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
39 
40 import android.annotation.NonNull;
41 import android.annotation.Nullable;
42 import android.app.Activity;
43 import android.app.ActivityManager;
44 import android.app.StatusBarManager;
45 import android.app.admin.DevicePolicyManager;
46 import android.app.admin.IDevicePolicyManager;
47 import android.content.ComponentName;
48 import android.content.Context;
49 import android.content.Intent;
50 import android.os.Binder;
51 import android.os.Debug;
52 import android.os.Handler;
53 import android.os.IBinder;
54 import android.os.RemoteException;
55 import android.os.ServiceManager;
56 import android.os.UserHandle;
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.protolog.ProtoLog;
67 import com.android.internal.statusbar.IStatusBarService;
68 import com.android.internal.telephony.CellBroadcastUtils;
69 import com.android.internal.widget.LockPatternUtils;
70 import com.android.server.LocalServices;
71 import com.android.server.am.ActivityManagerService;
72 import com.android.server.statusbar.StatusBarManagerInternal;
73 
74 import java.io.PrintWriter;
75 import java.util.ArrayList;
76 import java.util.Arrays;
77 
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  *
83  * Note: All methods in this class should only be called with the ActivityTaskManagerService lock
84  * held.
85  *
86  * @see Activity#startLockTask()
87  * @see Activity#stopLockTask()
88  */
89 public class LockTaskController {
90     private static final String TAG = TAG_WITH_CLASS_NAME ? "LockTaskController" : TAG_ATM;
91     private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
92 
93     @VisibleForTesting
94     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);
99     @VisibleForTesting
100     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 
STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO, new Pair<>(StatusBarManager.DISABLE_CLOCK, StatusBarManager.DISABLE2_SYSTEM_ICONS))109         STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO,
110                 new Pair<>(StatusBarManager.DISABLE_CLOCK, StatusBarManager.DISABLE2_SYSTEM_ICONS));
111 
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))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 
STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_HOME, new Pair<>(StatusBarManager.DISABLE_HOME, StatusBarManager.DISABLE2_NONE))117         STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_HOME,
118                 new Pair<>(StatusBarManager.DISABLE_HOME, StatusBarManager.DISABLE2_NONE));
119 
STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW, new Pair<>(StatusBarManager.DISABLE_RECENT, StatusBarManager.DISABLE2_NONE))120         STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW,
121                 new Pair<>(StatusBarManager.DISABLE_RECENT, StatusBarManager.DISABLE2_NONE));
122 
STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS, new Pair<>(StatusBarManager.DISABLE_NONE, StatusBarManager.DISABLE2_GLOBAL_ACTIONS))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     }
127 
128     /** Tag used for disabling of keyguard */
129     private static final String LOCK_TASK_TAG = "Lock-to-App";
130 
131     /** Can't be put in lockTask mode. */
132     static final int LOCK_TASK_AUTH_DONT_LOCK = 0;
133     /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
134     static final int LOCK_TASK_AUTH_PINNABLE = 1;
135     /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
136     static final int LOCK_TASK_AUTH_LAUNCHABLE = 2;
137     /** Can enter lockTask without user approval. Can start over existing lockTask task. */
138     static final int LOCK_TASK_AUTH_ALLOWLISTED = 3;
139     /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
140      * lockTask task. */
141     static final int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
142 
143     private final IBinder mToken = new LockTaskToken();
144     private final ActivityTaskSupervisor mSupervisor;
145     private final Context mContext;
146     private final TaskChangeNotificationController mTaskChangeNotificationController;
147 
148     // The following system services cannot be final, because they do not exist when this class
149     // is instantiated during device boot
150     @VisibleForTesting
151     IStatusBarService mStatusBarService;
152     @VisibleForTesting
153     IDevicePolicyManager mDevicePolicyManager;
154     @VisibleForTesting
155     WindowManagerService mWindowManager;
156     @VisibleForTesting
157     LockPatternUtils mLockPatternUtils;
158     @VisibleForTesting
159     TelecomManager mTelecomManager;
160 
161     /**
162      * The chain of tasks in LockTask mode, in the order of when they first entered LockTask mode.
163      *
164      * The first task in the list, which started the current LockTask session, is called the root
165      * task. It coincides with the Home task in a typical multi-app kiosk deployment. When there are
166      * more than one locked tasks, the root task can't be finished. Nor can it be moved to the back
167      * of the stack by {@link Task#moveTaskToBack(Task)};
168      *
169      * Calling {@link Activity#stopLockTask()} on the root task will finish all tasks but itself in
170      * this list, and the device will exit LockTask mode.
171      *
172      * The list is empty if LockTask is inactive.
173      */
174     private final ArrayList<Task> mLockTaskModeTasks = new ArrayList<>();
175 
176     /**
177      * Packages that are allowed to be launched into the lock task mode for each user.
178      */
179     private final SparseArray<String[]> mLockTaskPackages = new SparseArray<>();
180 
181     /**
182      * Features that are allowed by DPC to show during LockTask mode.
183      */
184     private final SparseIntArray mLockTaskFeatures = new SparseIntArray();
185 
186     /**
187      * Store the current lock task mode. Possible values:
188      * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
189      * {@link ActivityManager#LOCK_TASK_MODE_PINNED}
190      */
191     private volatile int mLockTaskModeState = LOCK_TASK_MODE_NONE;
192 
193     /**
194      * This is ActivityTaskSupervisor's Handler.
195      */
196     private final Handler mHandler;
197 
198     /**
199      * Stores the user for which we're trying to dismiss the keyguard and then subsequently
200      * disable it.
201      *
202      * Tracking this ensures we don't mistakenly disable the keyguard if we've stopped trying to
203      * between the dismiss request and when it succeeds.
204      *
205      * Must only be accessed from the Handler thread.
206      */
207     private int mPendingDisableFromDismiss = UserHandle.USER_NULL;
208 
LockTaskController(Context context, ActivityTaskSupervisor supervisor, Handler handler, TaskChangeNotificationController taskChangeNotificationController)209     LockTaskController(Context context, ActivityTaskSupervisor supervisor,
210             Handler handler, TaskChangeNotificationController taskChangeNotificationController) {
211         mContext = context;
212         mSupervisor = supervisor;
213         mHandler = handler;
214         mTaskChangeNotificationController = taskChangeNotificationController;
215     }
216 
217     /**
218      * Set the window manager instance used in this class. This is necessary, because the window
219      * manager does not exist during instantiation of this class.
220      */
setWindowManager(WindowManagerService windowManager)221     void setWindowManager(WindowManagerService windowManager) {
222         mWindowManager = windowManager;
223     }
224 
225     /**
226      * @return the current lock task state. This can be any of
227      * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
228      * {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
229      */
getLockTaskModeState()230     int getLockTaskModeState() {
231         return mLockTaskModeState;
232     }
233 
234     /**
235      * @return whether the given task is locked at the moment. Locked tasks cannot be moved to the
236      * back of the stack.
237      */
238     @VisibleForTesting
isTaskLocked(Task task)239     boolean isTaskLocked(Task task) {
240         return mLockTaskModeTasks.contains(task);
241     }
242 
243     /**
244      * @return {@code true} whether this task first started the current LockTask session.
245      */
isRootTask(Task task)246     private boolean isRootTask(Task task) {
247         return mLockTaskModeTasks.indexOf(task) == 0;
248     }
249 
250     /**
251      * @return whether the given activity is blocked from finishing, because it is the only activity
252      * of the last locked task and finishing it would mean that lock task mode is ended illegally.
253      */
activityBlockedFromFinish(ActivityRecord activity)254     boolean activityBlockedFromFinish(ActivityRecord activity) {
255         final Task task = activity.getTask();
256         if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV || !isRootTask(task)) {
257             return false;
258         }
259 
260         final ActivityRecord taskTop = task.getTopNonFinishingActivity();
261         final ActivityRecord taskRoot = task.getRootActivity();
262         // If task has more than one Activity, verify if there's only adjacent TaskFragments that
263         // should be finish together in the Task.
264         if (activity != taskRoot || activity != taskTop) {
265             final TaskFragment taskFragment = activity.getTaskFragment();
266             if (taskFragment.asTask() != null
267                     || !taskFragment.isDelayLastActivityRemoval()
268                     || !taskFragment.hasAdjacentTaskFragment()) {
269                 // Don't block activity from finishing if the TaskFragment don't have any adjacent
270                 // TaskFragment, or it won't finish together with its adjacent TaskFragment.
271                 return false;
272             }
273 
274             final boolean hasOtherActivityInTaskFragment =
275                     taskFragment.getActivity(a -> !a.finishing && a != activity) != null;
276             if (hasOtherActivityInTaskFragment) {
277                 // Don't block activity from finishing if there's other Activity in the same
278                 // TaskFragment.
279                 return false;
280             }
281 
282             final boolean hasOtherActivityInTask = task.getActivity(a -> !a.finishing
283                     && a != activity && !taskFragment.isAdjacentTo(a.getTaskFragment())) != null;
284             if (hasOtherActivityInTask) {
285                 // Do not block activity from finishing if there are another running activities
286                 // after the current and adjacent TaskFragments are removed. Note that we don't
287                 // check activities in adjacent TaskFragment because it will be finished together
288                 // with TaskFragment regardless of numbers of activities.
289                 return false;
290             }
291         }
292 
293         Slog.i(TAG, "Not finishing task in lock task mode");
294         showLockTaskToast();
295         return true;
296     }
297 
298     /**
299      * @return whether the given task can be moved to the back of the stack with
300      * {@link Task#moveTaskToBack(Task)}
301      * @see #mLockTaskModeTasks
302      */
canMoveTaskToBack(Task task)303     boolean canMoveTaskToBack(Task task) {
304         if (isRootTask(task)) {
305             showLockTaskToast();
306             return false;
307         }
308         return true;
309     }
310 
311     /**
312      * @return whether the requested task auth is allowed to be locked.
313      */
isTaskAuthAllowlisted(int lockTaskAuth)314     static boolean isTaskAuthAllowlisted(int lockTaskAuth) {
315         switch(lockTaskAuth) {
316             case LOCK_TASK_AUTH_ALLOWLISTED:
317             case LOCK_TASK_AUTH_LAUNCHABLE:
318             case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
319                 return true;
320             case LOCK_TASK_AUTH_PINNABLE:
321             case LOCK_TASK_AUTH_DONT_LOCK:
322             default:
323                 return false;
324         }
325     }
326 
327     /**
328      * @return whether the requested task is disallowed to be launched.
329      */
isLockTaskModeViolation(Task task)330     boolean isLockTaskModeViolation(Task task) {
331         return isLockTaskModeViolation(task, false);
332     }
333 
334     /**
335      * @param isNewClearTask whether the task would be cleared as part of the operation.
336      * @return whether the requested task is disallowed to be launched.
337      */
isLockTaskModeViolation(Task task, boolean isNewClearTask)338     boolean isLockTaskModeViolation(Task task, boolean isNewClearTask) {
339         // TODO: Double check what's going on here. If the task is already in lock task mode, it's
340         // likely allowlisted, so will return false below.
341         if (isTaskLocked(task) && !isNewClearTask) {
342             // If the task is already at the top and won't be cleared, then allow the operation
343         } else if (isLockTaskModeViolationInternal(task, task.mUserId, task.intent,
344                 task.mLockTaskAuth)) {
345             showLockTaskToast();
346             return true;
347         }
348         return false;
349     }
350 
351     /**
352      * @param activity an activity that is going to be started in a new task as the root activity.
353      * @return whether the given activity is allowed to be launched.
354      */
isNewTaskLockTaskModeViolation(ActivityRecord activity)355     boolean isNewTaskLockTaskModeViolation(ActivityRecord activity) {
356         // Use the belong task (if any) to perform the lock task checks
357         if (activity.getTask() != null) {
358             return isLockTaskModeViolation(activity.getTask());
359         }
360 
361         int auth = getLockTaskAuth(activity, null /* task */);
362         if (isLockTaskModeViolationInternal(activity, activity.mUserId, activity.intent, auth)) {
363             showLockTaskToast();
364             return true;
365         }
366         return false;
367     }
368 
369     /**
370      * @return the root task of the lock task.
371      */
getRootTask()372     Task getRootTask() {
373         if (mLockTaskModeTasks.isEmpty()) {
374             return null;
375         }
376         return mLockTaskModeTasks.get(0);
377     }
378 
isLockTaskModeViolationInternal(WindowContainer wc, int userId, Intent intent, int taskAuth)379     private boolean isLockTaskModeViolationInternal(WindowContainer wc, int userId,
380             Intent intent, int taskAuth) {
381         // Allow recents activity if enabled by policy
382         if (wc.isActivityTypeRecents() && isRecentsAllowed(userId)) {
383             return false;
384         }
385 
386         // Allow emergency calling when the device is protected by a locked keyguard
387         if (isKeyguardAllowed(userId) && isEmergencyCallIntent(intent)) {
388             return false;
389         }
390 
391         // Allow the dream to start during lock task mode
392         if (wc.isActivityTypeDream()) {
393             return false;
394         }
395 
396         if (isWirelessEmergencyAlert(intent)) {
397             return false;
398         }
399 
400         return !(isTaskAuthAllowlisted(taskAuth) || mLockTaskModeTasks.isEmpty());
401     }
402 
isRecentsAllowed(int userId)403     private boolean isRecentsAllowed(int userId) {
404         return (getLockTaskFeaturesForUser(userId)
405                 & DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW) != 0;
406     }
407 
isKeyguardAllowed(int userId)408     private boolean isKeyguardAllowed(int userId) {
409         return (getLockTaskFeaturesForUser(userId)
410                 & DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD) != 0;
411     }
412 
isBlockingInTaskEnabled(int userId)413     private boolean isBlockingInTaskEnabled(int userId) {
414         return (getLockTaskFeaturesForUser(userId)
415                 & DevicePolicyManager.LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK) != 0;
416     }
417 
isActivityAllowed(int userId, String packageName, int lockTaskLaunchMode)418     boolean isActivityAllowed(int userId, String packageName, int lockTaskLaunchMode) {
419         if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED || !isBlockingInTaskEnabled(userId)) {
420             return true;
421         }
422         switch (lockTaskLaunchMode) {
423             case LOCK_TASK_LAUNCH_MODE_ALWAYS:
424                 return true;
425             case LOCK_TASK_LAUNCH_MODE_NEVER:
426                 return false;
427             default:
428         }
429         return isPackageAllowlisted(userId, packageName);
430     }
431 
isWirelessEmergencyAlert(Intent intent)432     private boolean isWirelessEmergencyAlert(Intent intent) {
433         if (intent == null) {
434             return false;
435         }
436 
437         final ComponentName cellBroadcastAlertDialogComponentName =
438                 CellBroadcastUtils.getDefaultCellBroadcastAlertDialogComponent(mContext);
439 
440         if (cellBroadcastAlertDialogComponentName == null) {
441             return false;
442         }
443 
444         if (cellBroadcastAlertDialogComponentName.equals(intent.getComponent())) {
445             return true;
446         }
447 
448         return false;
449     }
450 
isEmergencyCallIntent(Intent intent)451     private boolean isEmergencyCallIntent(Intent intent) {
452         if (intent == null) {
453             return false;
454         }
455 
456         // 1. The emergency keypad activity launched on top of the keyguard
457         if (EMERGENCY_DIALER_COMPONENT.equals(intent.getComponent())) {
458             return true;
459         }
460 
461         // 2. The intent sent by the keypad, which is handled by Telephony
462         if (ACTION_CALL_EMERGENCY.equals(intent.getAction())) {
463             return true;
464         }
465 
466         // 3. Telephony then starts the default package for making the call
467         final TelecomManager tm = getTelecomManager();
468         final String dialerPackage = tm != null ? tm.getSystemDialerPackage() : null;
469         if (dialerPackage != null && dialerPackage.equals(intent.getComponent().getPackageName())) {
470             return true;
471         }
472 
473         return false;
474     }
475 
476     /**
477      * Stop the current lock task mode.
478      *
479      * This is called by {@link ActivityManagerService} and performs various checks before actually
480      * finishing the locked task.
481      *
482      * @param task the task that requested the end of lock task mode ({@code null} for quitting app
483      *             pinning mode)
484      * @param stopAppPinning indicates whether to stop app pinning mode or to stop a task from
485      *                       being locked.
486      * @param callingUid the caller that requested the end of lock task mode.
487      * @throws IllegalArgumentException if the calling task is invalid (e.g., {@code null} or not in
488      *                                  foreground)
489      * @throws SecurityException if the caller is not authorized to stop the lock task mode, i.e. if
490      *                           they differ from the one that launched lock task mode.
491      */
stopLockTaskMode(@ullable Task task, boolean stopAppPinning, int callingUid)492     void stopLockTaskMode(@Nullable Task task, boolean stopAppPinning, int callingUid) {
493         if (mLockTaskModeState == LOCK_TASK_MODE_NONE) {
494             return;
495         }
496 
497         if (stopAppPinning) {
498             if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
499                 clearLockedTasks("stopAppPinning");
500             } else {
501                 Slog.e(TAG_LOCKTASK, "Attempted to stop app pinning while fully locked");
502                 showLockTaskToast();
503             }
504 
505         } else {
506             // Ensure calling activity is not null
507             if (task == null) {
508                 throw new IllegalArgumentException("can't stop LockTask for null task");
509             }
510 
511             // Ensure the same caller for startLockTaskMode and stopLockTaskMode.
512             // It is possible lockTaskMode was started by the system process because
513             // android:lockTaskMode is set to a locking value in the application manifest
514             // instead of the app calling startLockTaskMode. In this case
515             // {@link Task.mLockTaskUid} will be 0, so we compare the callingUid to the
516             // {@link Task.effectiveUid} instead. Also caller with
517             // {@link MANAGE_ACTIVITY_TASKS} can stop any lock task.
518             if (callingUid != task.mLockTaskUid
519                     && (task.mLockTaskUid != 0 || callingUid != task.effectiveUid)) {
520                 throw new SecurityException("Invalid uid, expected " + task.mLockTaskUid
521                         + " callingUid=" + callingUid + " effectiveUid=" + task.effectiveUid);
522             }
523 
524             // We don't care if it's pinned or locked mode; this will stop it anyways.
525             clearLockedTask(task);
526         }
527     }
528 
529     /**
530      * Clear all locked tasks and request the end of LockTask mode.
531      *
532      * This method is called by UserController when starting a new foreground user, and,
533      * unlike {@link #stopLockTaskMode(Task, boolean, int)}, it doesn't perform the checks.
534      */
clearLockedTasks(String reason)535     void clearLockedTasks(String reason) {
536         ProtoLog.i(WM_DEBUG_LOCKTASK, "clearLockedTasks: %s", reason);
537         if (!mLockTaskModeTasks.isEmpty()) {
538             clearLockedTask(mLockTaskModeTasks.get(0));
539         }
540     }
541 
542     /**
543      * Clear one locked task from LockTask mode.
544      *
545      * If the requested task is the root task (see {@link #mLockTaskModeTasks}), then all locked
546      * tasks are cleared. Otherwise, only the requested task is cleared. LockTask mode is stopped
547      * when the last locked task is cleared.
548      *
549      * @param task the task to be cleared from LockTask mode.
550      */
clearLockedTask(final Task task)551     void clearLockedTask(final Task task) {
552         if (task == null || mLockTaskModeTasks.isEmpty()) return;
553 
554         if (task == mLockTaskModeTasks.get(0)) {
555             // We're removing the root task while there are other locked tasks. Therefore we should
556             // clear all locked tasks in reverse order.
557             for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx > 0; --taskNdx) {
558                 clearLockedTask(mLockTaskModeTasks.get(taskNdx));
559             }
560         }
561 
562         removeLockedTask(task);
563         if (mLockTaskModeTasks.isEmpty()) {
564             return;
565         }
566         task.performClearTaskForReuse(false /* excludingTaskOverlay*/);
567         mSupervisor.mRootWindowContainer.resumeFocusedTasksTopActivities();
568     }
569 
570     /**
571      * Remove the given task from the locked task list. If this was the last task in the list,
572      * lock task mode is stopped.
573      */
removeLockedTask(final Task task)574     private void removeLockedTask(final Task task) {
575         if (!mLockTaskModeTasks.remove(task)) {
576             return;
577         }
578         ProtoLog.d(WM_DEBUG_LOCKTASK, "removeLockedTask: removed %s", task);
579         if (mLockTaskModeTasks.isEmpty()) {
580             ProtoLog.d(WM_DEBUG_LOCKTASK, "removeLockedTask: task=%s last task, "
581                     + "reverting locktask mode. Callers=%s", task, Debug.getCallers(3));
582             mHandler.post(() -> performStopLockTask(task.mUserId));
583         }
584     }
585 
586     // This method should only be called on the handler thread
performStopLockTask(int userId)587     private void performStopLockTask(int userId) {
588         // Update the internal mLockTaskModeState early to avoid the scenario that SysUI queries
589         // mLockTaskModeState (from setStatusBarState) and gets staled state.
590         // TODO: revisit this approach.
591         // The race condition raised above can be addressed by moving this function out of handler
592         // thread, which makes it guarded by ATMS#mGlobalLock as ATMS#getLockTaskModeState.
593         final int oldLockTaskModeState = mLockTaskModeState;
594         mLockTaskModeState = LOCK_TASK_MODE_NONE;
595         mTaskChangeNotificationController.notifyLockTaskModeChanged(mLockTaskModeState);
596         // When lock task ends, we enable the status bars.
597         try {
598             setStatusBarState(mLockTaskModeState, userId);
599             setKeyguardState(mLockTaskModeState, userId);
600             if (oldLockTaskModeState == LOCK_TASK_MODE_PINNED) {
601                 lockKeyguardIfNeeded(userId);
602             }
603             if (getDevicePolicyManager() != null) {
604                 getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId);
605             }
606             if (oldLockTaskModeState == LOCK_TASK_MODE_PINNED) {
607                 final IStatusBarService statusBarService = getStatusBarService();
608                 if (statusBarService != null) {
609                     statusBarService.showPinningEnterExitToast(false /* entering */);
610                 }
611             }
612         } catch (RemoteException ex) {
613             throw new RuntimeException(ex);
614         }
615     }
616 
617     /**
618      * Show the lock task violation toast. Currently we only show toast for screen pinning mode, and
619      * no-op if the device is in locked mode.
620      */
showLockTaskToast()621     void showLockTaskToast() {
622         if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
623             try {
624                 final IStatusBarService statusBarService = getStatusBarService();
625                 if (statusBarService != null) {
626                     statusBarService.showPinningEscapeToast();
627                 }
628             } catch (RemoteException e) {
629                 Slog.e(TAG, "Failed to send pinning escape toast", e);
630             }
631         }
632     }
633 
634     // Starting lock task
635 
636     /**
637      * Method to start lock task mode on a given task.
638      *
639      * @param task the task that should be locked.
640      * @param isSystemCaller indicates whether this request was initiated by the system via
641      *                       {@link ActivityTaskManagerService#startSystemLockTaskMode(int)}. If
642      *                       {@code true}, this intends to start pinned mode; otherwise, we look
643      *                       at the calling task's mLockTaskAuth to decide which mode to start.
644      * @param callingUid the caller that requested the launch of lock task mode.
645      */
startLockTaskMode(@onNull Task task, boolean isSystemCaller, int callingUid)646     void startLockTaskMode(@NonNull Task task, boolean isSystemCaller, int callingUid) {
647         if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) {
648             ProtoLog.w(WM_DEBUG_LOCKTASK, "startLockTaskMode: Can't lock due to auth");
649             return;
650         }
651         if (!isSystemCaller) {
652             task.mLockTaskUid = callingUid;
653             if (task.mLockTaskAuth == LOCK_TASK_AUTH_PINNABLE) {
654                 if (mLockTaskModeTasks.contains(task)) {
655                     ProtoLog.w(WM_DEBUG_LOCKTASK, "Already locked.");
656                     return;
657                 }
658                 // startLockTask() called by app, but app is not part of lock task allowlist. Show
659                 // app pinning request. We will come back here with isSystemCaller true.
660                 ProtoLog.w(WM_DEBUG_LOCKTASK, "Mode default, asking user");
661                 StatusBarManagerInternal statusBarManager = LocalServices.getService(
662                         StatusBarManagerInternal.class);
663                 if (statusBarManager != null) {
664                     statusBarManager.showScreenPinningRequest(task.mTaskId, task.mUserId);
665                 }
666                 return;
667             } else if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
668                 // startLockTask() called by app, and app is part of lock task allowlist.
669                 // Deactivate the currently pinned task before doing so.
670                 Slog.i(TAG, "Stop app pinning before entering full lock task mode");
671                 stopLockTaskMode(/* task= */ null, /* stopAppPinning= */ true, callingUid);
672             }
673         }
674 
675         // When a task is locked, dismiss the root pinned task if it exists
676         mSupervisor.mRootWindowContainer.removeRootTasksInWindowingModes(WINDOWING_MODE_PINNED);
677 
678         // System can only initiate screen pinning, not full lock task mode
679         ProtoLog.w(WM_DEBUG_LOCKTASK, "%s", isSystemCaller ? "Locking pinned" : "Locking fully");
680         setLockTaskMode(task, isSystemCaller ? LOCK_TASK_MODE_PINNED : LOCK_TASK_MODE_LOCKED,
681                 "startLockTask", true);
682     }
683 
684     /**
685      * Start lock task mode on the given task.
686      * @param lockTaskModeState whether fully locked or pinned mode.
687      * @param andResume whether the task should be brought to foreground as part of the operation.
688      */
setLockTaskMode(@onNull Task task, int lockTaskModeState, String reason, boolean andResume)689     private void setLockTaskMode(@NonNull Task task, int lockTaskModeState,
690                                  String reason, boolean andResume) {
691         // Should have already been checked, but do it again.
692         if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) {
693             ProtoLog.w(WM_DEBUG_LOCKTASK,
694                     "setLockTaskMode: Can't lock due to auth");
695             return;
696         }
697         if (isLockTaskModeViolation(task)) {
698             Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task.");
699             return;
700         }
701 
702         final Intent taskIntent = task.intent;
703         if (mLockTaskModeTasks.isEmpty() && taskIntent != null) {
704             mSupervisor.mRecentTasks.onLockTaskModeStateChanged(lockTaskModeState, task.mUserId);
705             // Start lock task on the handler thread
706             mHandler.post(() -> performStartLockTask(
707                     taskIntent.getComponent().getPackageName(),
708                     task.mUserId,
709                     lockTaskModeState));
710         }
711         ProtoLog.w(WM_DEBUG_LOCKTASK, "setLockTaskMode: Locking to %s Callers=%s",
712                 task, Debug.getCallers(4));
713 
714         if (!mLockTaskModeTasks.contains(task)) {
715             mLockTaskModeTasks.add(task);
716         }
717 
718         if (task.mLockTaskUid == -1) {
719             task.mLockTaskUid = task.effectiveUid;
720         }
721 
722         if (andResume) {
723             mSupervisor.findTaskToMoveToFront(task, 0, null, reason,
724                     lockTaskModeState != LOCK_TASK_MODE_NONE);
725             mSupervisor.mRootWindowContainer.resumeFocusedTasksTopActivities();
726             final Task rootTask = task.getRootTask();
727             if (rootTask != null) {
728                 rootTask.mDisplayContent.executeAppTransition();
729             }
730         } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
731             mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED,
732                     mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea(),
733                     task.getRootTask(), true /* forceNonResizable */);
734         }
735     }
736 
737     // This method should only be called on the handler thread
performStartLockTask(String packageName, int userId, int lockTaskModeState)738     private void performStartLockTask(String packageName, int userId, int lockTaskModeState) {
739         // When lock task starts, we disable the status bars.
740         try {
741             if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
742                 final IStatusBarService statusBarService = getStatusBarService();
743                 if (statusBarService != null) {
744                     statusBarService.showPinningEnterExitToast(true /* entering */);
745                 }
746             }
747             mLockTaskModeState = lockTaskModeState;
748             mTaskChangeNotificationController.notifyLockTaskModeChanged(mLockTaskModeState);
749             setStatusBarState(lockTaskModeState, userId);
750             setKeyguardState(lockTaskModeState, userId);
751             if (getDevicePolicyManager() != null) {
752                 getDevicePolicyManager().notifyLockTaskModeChanged(true, packageName, userId);
753             }
754         } catch (RemoteException ex) {
755             throw new RuntimeException(ex);
756         }
757     }
758 
759     /**
760      * Update packages that are allowed to be launched in lock task mode.
761      * @param userId Which user this allowlist is associated with
762      * @param packages The allowlist of packages allowed in lock task mode
763      * @see #mLockTaskPackages
764      */
updateLockTaskPackages(int userId, String[] packages)765     void updateLockTaskPackages(int userId, String[] packages) {
766         mLockTaskPackages.put(userId, packages);
767 
768         boolean taskChanged = false;
769         for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) {
770             final Task lockedTask = mLockTaskModeTasks.get(taskNdx);
771             final boolean wasAllowlisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
772                     || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_ALLOWLISTED;
773             lockedTask.setLockTaskAuth();
774             final boolean isAllowlisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
775                     || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_ALLOWLISTED;
776 
777             if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED
778                     || lockedTask.mUserId != userId
779                     || !wasAllowlisted || isAllowlisted) {
780                 continue;
781             }
782 
783             // Terminate locked tasks that have recently lost allowlist authorization.
784             ProtoLog.d(WM_DEBUG_LOCKTASK, "onLockTaskPackagesUpdated: removing %s"
785                     + " mLockTaskAuth()=%s", lockedTask, lockedTask.lockTaskAuthToString());
786             removeLockedTask(lockedTask);
787             lockedTask.performClearTaskForReuse(false /* excludingTaskOverlay*/);
788             taskChanged = true;
789         }
790 
791         mSupervisor.mRootWindowContainer.forAllTasks(Task::setLockTaskAuth);
792 
793         final ActivityRecord r = mSupervisor.mRootWindowContainer.topRunningActivity();
794         final Task task = (r != null) ? r.getTask() : null;
795         if (mLockTaskModeTasks.isEmpty() && task!= null
796                 && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
797             // This task must have just been authorized.
798             ProtoLog.d(WM_DEBUG_LOCKTASK, "onLockTaskPackagesUpdated: starting new "
799                     + "locktask task=%s", task);
800             setLockTaskMode(task, LOCK_TASK_MODE_LOCKED, "package updated", false);
801             taskChanged = true;
802         }
803 
804         if (taskChanged) {
805             mSupervisor.mRootWindowContainer.resumeFocusedTasksTopActivities();
806         }
807     }
808 
getLockTaskAuth(@ullable ActivityRecord rootActivity, @Nullable Task task)809     int getLockTaskAuth(@Nullable ActivityRecord rootActivity, @Nullable Task task) {
810         if (rootActivity == null && task == null) {
811             return LOCK_TASK_AUTH_DONT_LOCK;
812         }
813         if (rootActivity == null) {
814             return LOCK_TASK_AUTH_PINNABLE;
815         }
816 
817         final String pkg = (task == null || task.realActivity == null) ? rootActivity.packageName
818                 : task.realActivity.getPackageName();
819         final int userId = task != null ? task.mUserId : rootActivity.mUserId;
820         int lockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
821         switch (rootActivity.lockTaskLaunchMode) {
822             case LOCK_TASK_LAUNCH_MODE_DEFAULT:
823                 lockTaskAuth = isPackageAllowlisted(userId, pkg)
824                         ? LOCK_TASK_AUTH_ALLOWLISTED : LOCK_TASK_AUTH_PINNABLE;
825                 break;
826 
827             case LOCK_TASK_LAUNCH_MODE_NEVER:
828                 lockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
829                 break;
830 
831             case LOCK_TASK_LAUNCH_MODE_ALWAYS:
832                 lockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
833                 break;
834 
835             case LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED:
836                 lockTaskAuth = isPackageAllowlisted(userId, pkg)
837                         ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
838                 break;
839         }
840         return lockTaskAuth;
841     }
842 
isPackageAllowlisted(int userId, String pkg)843     boolean isPackageAllowlisted(int userId, String pkg) {
844         if (pkg == null) {
845             return false;
846         }
847         String[] allowlist;
848         allowlist = mLockTaskPackages.get(userId);
849         if (allowlist == null) {
850             return false;
851         }
852         for (String allowlistedPkg : allowlist) {
853             if (pkg.equals(allowlistedPkg)) {
854                 return true;
855             }
856         }
857         return false;
858     }
859 
860     /**
861      * Update the UI features that are enabled for LockTask mode.
862      * @param userId Which user these feature flags are associated with
863      * @param flags Bitfield of feature flags
864      * @see DevicePolicyManager#setLockTaskFeatures(ComponentName, int)
865      */
updateLockTaskFeatures(int userId, int flags)866     void updateLockTaskFeatures(int userId, int flags) {
867         int oldFlags = getLockTaskFeaturesForUser(userId);
868         if (flags == oldFlags) {
869             return;
870         }
871 
872         mLockTaskFeatures.put(userId, flags);
873         if (!mLockTaskModeTasks.isEmpty() && userId == mLockTaskModeTasks.get(0).mUserId) {
874             mHandler.post(() -> {
875                 if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) {
876                     setStatusBarState(mLockTaskModeState, userId);
877                     setKeyguardState(mLockTaskModeState, userId);
878                 }
879             });
880         }
881     }
882 
883     /**
884      * Helper method for configuring the status bar disabled state.
885      * Should only be called on the handler thread to avoid race.
886      */
setStatusBarState(int lockTaskModeState, int userId)887     private void setStatusBarState(int lockTaskModeState, int userId) {
888         IStatusBarService statusBar = getStatusBarService();
889         if (statusBar == null) {
890             Slog.e(TAG, "Can't find StatusBarService");
891             return;
892         }
893 
894         // Default state, when lockTaskModeState == LOCK_TASK_MODE_NONE
895         int flags1 = StatusBarManager.DISABLE_NONE;
896         int flags2 = StatusBarManager.DISABLE2_NONE;
897 
898         if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
899             flags1 = STATUS_BAR_MASK_PINNED;
900 
901         } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
902             int lockTaskFeatures = getLockTaskFeaturesForUser(userId);
903             Pair<Integer, Integer> statusBarFlags = getStatusBarDisableFlags(lockTaskFeatures);
904             flags1 = statusBarFlags.first;
905             flags2 = statusBarFlags.second;
906         }
907 
908         try {
909             statusBar.disable(flags1, mToken, mContext.getPackageName());
910             statusBar.disable2(flags2, mToken, mContext.getPackageName());
911         } catch (RemoteException e) {
912             Slog.e(TAG, "Failed to set status bar flags", e);
913         }
914     }
915 
916     /**
917      * Helper method for configuring the keyguard disabled state.
918      * Should only be called on the handler thread to avoid race.
919      */
setKeyguardState(int lockTaskModeState, int userId)920     private void setKeyguardState(int lockTaskModeState, int userId) {
921         mPendingDisableFromDismiss = UserHandle.USER_NULL;
922         if (lockTaskModeState == LOCK_TASK_MODE_NONE) {
923             mWindowManager.reenableKeyguard(mToken, userId);
924 
925         } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
926             if (isKeyguardAllowed(userId)) {
927                 mWindowManager.reenableKeyguard(mToken, userId);
928             } else {
929                 // If keyguard is not secure and it is locked, dismiss the keyguard before
930                 // disabling it, which avoids the platform to think the keyguard is still on.
931                 if (mWindowManager.isKeyguardLocked() && !mWindowManager.isKeyguardSecure(userId)) {
932                     mPendingDisableFromDismiss = userId;
933                     mWindowManager.dismissKeyguard(new IKeyguardDismissCallback.Stub() {
934                         @Override
935                         public void onDismissError() throws RemoteException {
936                             Slog.i(TAG, "setKeyguardState: failed to dismiss keyguard");
937                         }
938 
939                         @Override
940                         public void onDismissSucceeded() throws RemoteException {
941                             mHandler.post(
942                                     () -> {
943                                         if (mPendingDisableFromDismiss == userId) {
944                                             mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG,
945                                                     userId);
946                                             mPendingDisableFromDismiss = UserHandle.USER_NULL;
947                                         }
948                                     });
949                         }
950 
951                         @Override
952                         public void onDismissCancelled() throws RemoteException {
953                             Slog.i(TAG, "setKeyguardState: dismiss cancelled");
954                         }
955                     }, null);
956                 } else {
957                     mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG, userId);
958                 }
959             }
960 
961         } else { // lockTaskModeState == LOCK_TASK_MODE_PINNED
962             mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG, userId);
963         }
964     }
965 
966     /**
967      * Helper method for locking the device immediately. This may be necessary when the device
968      * leaves the pinned mode.
969      */
lockKeyguardIfNeeded(int userId)970     private void lockKeyguardIfNeeded(int userId) {
971         if (shouldLockKeyguard(userId)) {
972             mWindowManager.lockNow(null);
973             mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
974             getLockPatternUtils().requireCredentialEntry(USER_ALL);
975         }
976     }
977 
shouldLockKeyguard(int userId)978     private boolean shouldLockKeyguard(int userId) {
979         // This functionality should be kept consistent with
980         // com.android.settings.security.ScreenPinningSettings (see b/127605586)
981         try {
982             return Settings.Secure.getIntForUser(
983                     mContext.getContentResolver(),
984                     Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, USER_CURRENT) != 0;
985         } catch (Settings.SettingNotFoundException e) {
986             // Log to SafetyNet for b/127605586
987             android.util.EventLog.writeEvent(0x534e4554, "127605586", -1, "");
988             return getLockPatternUtils().isSecure(userId);
989         }
990     }
991 
992     /**
993      * Translates from LockTask feature flags to StatusBarManager disable and disable2 flags.
994      * @param lockTaskFlags Bitfield of flags as per
995      *                      {@link DevicePolicyManager#setLockTaskFeatures(ComponentName, int)}
996      * @return A {@link Pair} of {@link StatusBarManager#disable(int)} and
997      *         {@link StatusBarManager#disable2(int)} flags
998      */
999     @VisibleForTesting
getStatusBarDisableFlags(int lockTaskFlags)1000     Pair<Integer, Integer> getStatusBarDisableFlags(int lockTaskFlags) {
1001         // Everything is disabled by default
1002         int flags1 = StatusBarManager.DISABLE_MASK;
1003         int flags2 = StatusBarManager.DISABLE2_MASK;
1004         for (int i = STATUS_BAR_FLAG_MAP_LOCKED.size() - 1; i >= 0; i--) {
1005             Pair<Integer, Integer> statusBarFlags = STATUS_BAR_FLAG_MAP_LOCKED.valueAt(i);
1006             if ((STATUS_BAR_FLAG_MAP_LOCKED.keyAt(i) & lockTaskFlags) != 0) {
1007                 flags1 &= ~statusBarFlags.first;
1008                 flags2 &= ~statusBarFlags.second;
1009             }
1010         }
1011         // Some flags are not used for LockTask purposes, so we mask them
1012         flags1 &= STATUS_BAR_MASK_LOCKED;
1013         return new Pair<>(flags1, flags2);
1014     }
1015 
1016     /**
1017      * @param packageName The package to check
1018      * @return Whether the package is the base of any locked task
1019      */
isBaseOfLockedTask(String packageName)1020     boolean isBaseOfLockedTask(String packageName) {
1021         for (int i = 0; i < mLockTaskModeTasks.size(); i++) {
1022             if (packageName.equals(mLockTaskModeTasks.get(i).getBasePackageName())) {
1023                 return true;
1024             }
1025         }
1026         return false;
1027     }
1028 
1029     /**
1030      * Gets the cached value of LockTask feature flags for a specific user.
1031      */
getLockTaskFeaturesForUser(int userId)1032     private int getLockTaskFeaturesForUser(int userId) {
1033         return mLockTaskFeatures.get(userId, DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
1034     }
1035 
1036     // Should only be called on the handler thread
1037     @Nullable
getStatusBarService()1038     private IStatusBarService getStatusBarService() {
1039         if (mStatusBarService == null) {
1040             mStatusBarService = IStatusBarService.Stub.asInterface(
1041                     ServiceManager.checkService(STATUS_BAR_SERVICE));
1042             if (mStatusBarService == null) {
1043                 Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE");
1044             }
1045         }
1046         return mStatusBarService;
1047     }
1048 
1049     // Should only be called on the handler thread
1050     @Nullable
getDevicePolicyManager()1051     private IDevicePolicyManager getDevicePolicyManager() {
1052         if (mDevicePolicyManager == null) {
1053             mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface(
1054                     ServiceManager.checkService(DEVICE_POLICY_SERVICE));
1055             if (mDevicePolicyManager == null) {
1056                 Slog.w(TAG, "warning: no DEVICE_POLICY_SERVICE");
1057             }
1058         }
1059         return mDevicePolicyManager;
1060     }
1061 
1062     @NonNull
getLockPatternUtils()1063     private LockPatternUtils getLockPatternUtils() {
1064         if (mLockPatternUtils == null) {
1065             // We don't preserve the LPU object to save memory
1066             return new LockPatternUtils(mContext);
1067         }
1068         return mLockPatternUtils;
1069     }
1070 
1071     @Nullable
getTelecomManager()1072     private TelecomManager getTelecomManager() {
1073         if (mTelecomManager == null) {
1074             // We don't preserve the TelecomManager object to save memory
1075             return mContext.getSystemService(TelecomManager.class);
1076         }
1077         return mTelecomManager;
1078     }
1079 
dump(PrintWriter pw, String prefix)1080     public void dump(PrintWriter pw, String prefix) {
1081         pw.println(prefix + "LockTaskController:");
1082         prefix = prefix + "  ";
1083         pw.println(prefix + "mLockTaskModeState=" + lockTaskModeToString());
1084         pw.println(prefix + "mLockTaskModeTasks=");
1085         for (int i = 0; i < mLockTaskModeTasks.size(); ++i) {
1086             pw.println(prefix + "  #" + i + " " + mLockTaskModeTasks.get(i));
1087         }
1088         pw.println(prefix + "mLockTaskPackages (userId:packages)=");
1089         for (int i = 0; i < mLockTaskPackages.size(); ++i) {
1090             pw.println(prefix + "  u" + mLockTaskPackages.keyAt(i)
1091                     + ":" + Arrays.toString(mLockTaskPackages.valueAt(i)));
1092         }
1093         pw.println();
1094     }
1095 
lockTaskModeToString()1096     private String lockTaskModeToString() {
1097         switch (mLockTaskModeState) {
1098             case LOCK_TASK_MODE_LOCKED:
1099                 return "LOCKED";
1100             case LOCK_TASK_MODE_PINNED:
1101                 return "PINNED";
1102             case LOCK_TASK_MODE_NONE:
1103                 return "NONE";
1104             default: return "unknown=" + mLockTaskModeState;
1105         }
1106     }
1107 
1108     /** Marker class for the token used to disable keyguard. */
1109     static class LockTaskToken extends Binder {
LockTaskToken()1110         private LockTaskToken() {
1111         }
1112     }
1113 }
1114