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