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