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