/*
 * Copyright 2017, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.am;

import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Context.DEVICE_POLICY_SERVICE;
import static android.content.Context.STATUS_BAR_SERVICE;
import static android.content.Intent.ACTION_CALL_EMERGENCY;
import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_CURRENT;
import static android.telecom.TelecomManager.EMERGENCY_DIALER_COMPONENT;
import static android.view.Display.DEFAULT_DISPLAY;

import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.StatusBarManager;
import android.app.admin.DevicePolicyManager;
import android.app.admin.IDevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
import android.telecom.TelecomManager;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.WindowManagerService;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * Helper class that deals with all things related to task locking. This includes the screen pinning
 * mode that can be launched via System UI as well as the fully locked mode that can be achieved
 * on fully managed devices.
 *
 * Note: All methods in this class should only be called with the ActivityManagerService lock held.
 *
 * @see Activity#startLockTask()
 * @see Activity#stopLockTask()
 */
public class LockTaskController {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "LockTaskController" : TAG_AM;
    private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;

    @VisibleForTesting
    static final int STATUS_BAR_MASK_LOCKED = StatusBarManager.DISABLE_MASK
            & (~StatusBarManager.DISABLE_EXPAND)
            & (~StatusBarManager.DISABLE_NOTIFICATION_TICKER)
            & (~StatusBarManager.DISABLE_SYSTEM_INFO)
            & (~StatusBarManager.DISABLE_BACK);
    @VisibleForTesting
    static final int STATUS_BAR_MASK_PINNED = StatusBarManager.DISABLE_MASK
            & (~StatusBarManager.DISABLE_BACK)
            & (~StatusBarManager.DISABLE_HOME)
            & (~StatusBarManager.DISABLE_RECENT);

    private static final SparseArray<Pair<Integer, Integer>> STATUS_BAR_FLAG_MAP_LOCKED;
    static {
        STATUS_BAR_FLAG_MAP_LOCKED = new SparseArray<>();

        STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO,
                new Pair<>(StatusBarManager.DISABLE_CLOCK, StatusBarManager.DISABLE2_SYSTEM_ICONS));

        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));

        STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_HOME,
                new Pair<>(StatusBarManager.DISABLE_HOME, StatusBarManager.DISABLE2_NONE));

        STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW,
                new Pair<>(StatusBarManager.DISABLE_RECENT, StatusBarManager.DISABLE2_NONE));

        STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS,
                new Pair<>(StatusBarManager.DISABLE_NONE,
                        StatusBarManager.DISABLE2_GLOBAL_ACTIONS));
    }

    /** Tag used for disabling of keyguard */
    private static final String LOCK_TASK_TAG = "Lock-to-App";

    private final IBinder mToken = new Binder();
    private final ActivityStackSupervisor mSupervisor;
    private final Context mContext;

    // The following system services cannot be final, because they do not exist when this class
    // is instantiated during device boot
    @VisibleForTesting
    IStatusBarService mStatusBarService;
    @VisibleForTesting
    IDevicePolicyManager mDevicePolicyManager;
    @VisibleForTesting
    WindowManagerService mWindowManager;
    @VisibleForTesting
    LockPatternUtils mLockPatternUtils;
    @VisibleForTesting
    TelecomManager mTelecomManager;

    /**
     * The chain of tasks in LockTask mode, in the order of when they first entered LockTask mode.
     *
     * The first task in the list, which started the current LockTask session, is called the root
     * task. It coincides with the Home task in a typical multi-app kiosk deployment. When there are
     * more than one locked tasks, the root task can't be finished. Nor can it be moved to the back
     * of the stack by {@link ActivityStack#moveTaskToBackLocked(int)};
     *
     * Calling {@link Activity#stopLockTask()} on the root task will finish all tasks but itself in
     * this list, and the device will exit LockTask mode.
     *
     * The list is empty if LockTask is inactive.
     */
    private final ArrayList<TaskRecord> mLockTaskModeTasks = new ArrayList<>();

    /**
     * Packages that are allowed to be launched into the lock task mode for each user.
     */
    private final SparseArray<String[]> mLockTaskPackages = new SparseArray<>();

    /**
     * Features that are allowed by DPC to show during LockTask mode.
     */
    private final SparseIntArray mLockTaskFeatures = new SparseIntArray();

    /**
     * Store the current lock task mode. Possible values:
     * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
     * {@link ActivityManager#LOCK_TASK_MODE_PINNED}
     */
    private int mLockTaskModeState = LOCK_TASK_MODE_NONE;

    /**
     * This is ActivityStackSupervisor's Handler.
     */
    private final Handler mHandler;

    LockTaskController(Context context, ActivityStackSupervisor supervisor,
            Handler handler) {
        mContext = context;
        mSupervisor = supervisor;
        mHandler = handler;
    }

    /**
     * Set the window manager instance used in this class. This is necessary, because the window
     * manager does not exist during instantiation of this class.
     */
    void setWindowManager(WindowManagerService windowManager) {
        mWindowManager = windowManager;
    }

    /**
     * @return the current lock task state. This can be any of
     * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
     * {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
     */
    int getLockTaskModeState() {
        return mLockTaskModeState;
    }

    /**
     * @return whether the given task is locked at the moment. Locked tasks cannot be moved to the
     * back of the stack.
     */
    @VisibleForTesting
    boolean isTaskLocked(TaskRecord task) {
        return mLockTaskModeTasks.contains(task);
    }

    /**
     * @return {@code true} whether this task first started the current LockTask session.
     */
    private boolean isRootTask(TaskRecord task) {
        return mLockTaskModeTasks.indexOf(task) == 0;
    }

    /**
     * @return whether the given activity is blocked from finishing, because it is the only activity
     * of the last locked task and finishing it would mean that lock task mode is ended illegally.
     */
    boolean activityBlockedFromFinish(ActivityRecord activity) {
        final TaskRecord task = activity.getTask();
        if (activity == task.getRootActivity()
                && activity == task.getTopActivity()
                && task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV
                && isRootTask(task)) {
            Slog.i(TAG, "Not finishing task in lock task mode");
            showLockTaskToast();
            return true;
        }
        return false;
    }

    /**
     * @return whether the given task can be moved to the back of the stack with
     * {@link ActivityStack#moveTaskToBackLocked(int)}
     * @see #mLockTaskModeTasks
     */
    boolean canMoveTaskToBack(TaskRecord task) {
        if (isRootTask(task)) {
            showLockTaskToast();
            return false;
        }
        return true;
    }

    /**
     * @return whether the requested task is allowed to be locked (either whitelisted, or declares
     * lockTaskMode="always" in the manifest).
     */
    boolean isTaskWhitelisted(TaskRecord task) {
        switch(task.mLockTaskAuth) {
            case LOCK_TASK_AUTH_WHITELISTED:
            case LOCK_TASK_AUTH_LAUNCHABLE:
            case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
                return true;
            case LOCK_TASK_AUTH_PINNABLE:
            case LOCK_TASK_AUTH_DONT_LOCK:
            default:
                return false;
        }
    }

    /**
     * @return whether the requested task is disallowed to be launched.
     */
    boolean isLockTaskModeViolation(TaskRecord task) {
        return isLockTaskModeViolation(task, false);
    }

    /**
     * @param isNewClearTask whether the task would be cleared as part of the operation.
     * @return whether the requested task is disallowed to be launched.
     */
    boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) {
        if (isLockTaskModeViolationInternal(task, isNewClearTask)) {
            showLockTaskToast();
            return true;
        }
        return false;
    }

    /**
     * @return the root task of the lock task.
     */
    TaskRecord getRootTask() {
        if (mLockTaskModeTasks.isEmpty()) {
            return null;
        }
        return mLockTaskModeTasks.get(0);
    }

    private boolean isLockTaskModeViolationInternal(TaskRecord task, boolean isNewClearTask) {
        // TODO: Double check what's going on here. If the task is already in lock task mode, it's
        // likely whitelisted, so will return false below.
        if (isTaskLocked(task) && !isNewClearTask) {
            // If the task is already at the top and won't be cleared, then allow the operation
            return false;
        }

        // Allow recents activity if enabled by policy
        if (task.isActivityTypeRecents() && isRecentsAllowed(task.userId)) {
            return false;
        }

        // Allow emergency calling when the device is protected by a locked keyguard
        if (isKeyguardAllowed(task.userId) && isEmergencyCallTask(task)) {
            return false;
        }

        return !(isTaskWhitelisted(task) || mLockTaskModeTasks.isEmpty());
    }

    private boolean isRecentsAllowed(int userId) {
        return (getLockTaskFeaturesForUser(userId)
                & DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW) != 0;
    }

    private boolean isKeyguardAllowed(int userId) {
        return (getLockTaskFeaturesForUser(userId)
                & DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD) != 0;
    }

    private boolean isEmergencyCallTask(TaskRecord task) {
        final Intent intent = task.intent;
        if (intent == null) {
            return false;
        }

        // 1. The emergency keypad activity launched on top of the keyguard
        if (EMERGENCY_DIALER_COMPONENT.equals(intent.getComponent())) {
            return true;
        }

        // 2. The intent sent by the keypad, which is handled by Telephony
        if (ACTION_CALL_EMERGENCY.equals(intent.getAction())) {
            return true;
        }

        // 3. Telephony then starts the default package for making the call
        final TelecomManager tm = getTelecomManager();
        final String dialerPackage = tm != null ? tm.getSystemDialerPackage() : null;
        if (dialerPackage != null && dialerPackage.equals(intent.getComponent().getPackageName())) {
            return true;
        }

        return false;
    }

    /**
     * Stop the current lock task mode.
     *
     * This is called by {@link ActivityManagerService} and performs various checks before actually
     * finishing the locked task.
     *
     * @param task the task that requested the end of lock task mode ({@code null} for quitting app
     *             pinning mode)
     * @param isSystemCaller indicates whether this request comes from the system via
     *                       {@link ActivityManagerService#stopSystemLockTaskMode()}. If
     *                       {@code true}, it means the user intends to stop pinned mode through UI;
     *                       otherwise, it's called by an app and we need to stop locked or pinned
     *                       mode, subject to checks.
     * @param callingUid the caller that requested the end of lock task mode.
     * @throws IllegalArgumentException if the calling task is invalid (e.g., {@code null} or not in
     *                                  foreground)
     * @throws SecurityException if the caller is not authorized to stop the lock task mode, i.e. if
     *                           they differ from the one that launched lock task mode.
     */
    void stopLockTaskMode(@Nullable TaskRecord task, boolean isSystemCaller, int callingUid) {
        if (mLockTaskModeState == LOCK_TASK_MODE_NONE) {
            return;
        }

        if (isSystemCaller) {
            if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
                clearLockedTasks("stopAppPinning");
            } else {
                Slog.e(TAG_LOCKTASK, "Attempted to stop LockTask with isSystemCaller=true");
                showLockTaskToast();
            }

        } else {
            // Ensure calling activity is not null
            if (task == null) {
                throw new IllegalArgumentException("can't stop LockTask for null task");
            }

            // Ensure the same caller for startLockTaskMode and stopLockTaskMode.
            // It is possible lockTaskMode was started by the system process because
            // android:lockTaskMode is set to a locking value in the application manifest
            // instead of the app calling startLockTaskMode. In this case
            // {@link TaskRecord.mLockTaskUid} will be 0, so we compare the callingUid to the
            // {@link TaskRecord.effectiveUid} instead. Also caller with
            // {@link MANAGE_ACTIVITY_STACKS} can stop any lock task.
            if (callingUid != task.mLockTaskUid
                    && (task.mLockTaskUid != 0 || callingUid != task.effectiveUid)) {
                throw new SecurityException("Invalid uid, expected " + task.mLockTaskUid
                        + " callingUid=" + callingUid + " effectiveUid=" + task.effectiveUid);
            }

            // We don't care if it's pinned or locked mode; this will stop it anyways.
            clearLockedTask(task);
        }
    }

    /**
     * Clear all locked tasks and request the end of LockTask mode.
     *
     * This method is called by {@link UserController} when starting a new foreground user, and,
     * unlike {@link #stopLockTaskMode(TaskRecord, boolean, int)}, it doesn't perform the checks.
     */
    void clearLockedTasks(String reason) {
        if (DEBUG_LOCKTASK) Slog.i(TAG_LOCKTASK, "clearLockedTasks: " + reason);
        if (!mLockTaskModeTasks.isEmpty()) {
            clearLockedTask(mLockTaskModeTasks.get(0));
        }
    }

    /**
     * Clear one locked task from LockTask mode.
     *
     * If the requested task is the root task (see {@link #mLockTaskModeTasks}), then all locked
     * tasks are cleared. Otherwise, only the requested task is cleared. LockTask mode is stopped
     * when the last locked task is cleared.
     *
     * @param task the task to be cleared from LockTask mode.
     */
    void clearLockedTask(final TaskRecord task) {
        if (task == null || mLockTaskModeTasks.isEmpty()) return;

        if (task == mLockTaskModeTasks.get(0)) {
            // We're removing the root task while there are other locked tasks. Therefore we should
            // clear all locked tasks in reverse order.
            for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx > 0; --taskNdx) {
                clearLockedTask(mLockTaskModeTasks.get(taskNdx));
            }
        }

        removeLockedTask(task);
        if (mLockTaskModeTasks.isEmpty()) {
            return;
        }
        task.performClearTaskLocked();
        mSupervisor.resumeFocusedStackTopActivityLocked();
    }

    /**
     * Remove the given task from the locked task list. If this was the last task in the list,
     * lock task mode is stopped.
     */
    private void removeLockedTask(final TaskRecord task) {
        if (!mLockTaskModeTasks.remove(task)) {
            return;
        }
        if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: removed " + task);
        if (mLockTaskModeTasks.isEmpty()) {
            if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: task=" + task +
                    " last task, reverting locktask mode. Callers=" + Debug.getCallers(3));
            mHandler.post(() -> performStopLockTask(task.userId));
        }
    }

    // This method should only be called on the handler thread
    private void performStopLockTask(int userId) {
        // When lock task ends, we enable the status bars.
        try {
            setStatusBarState(LOCK_TASK_MODE_NONE, userId);
            setKeyguardState(LOCK_TASK_MODE_NONE, userId);
            if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
                lockKeyguardIfNeeded();
            }
            if (getDevicePolicyManager() != null) {
                getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId);
            }
            if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
                getStatusBarService().showPinningEnterExitToast(false /* entering */);
            }
            mWindowManager.onLockTaskStateChanged(LOCK_TASK_MODE_NONE);
        } catch (RemoteException ex) {
            throw new RuntimeException(ex);
        } finally {
            mLockTaskModeState = LOCK_TASK_MODE_NONE;
        }
    }

    /**
     * Show the lock task violation toast. Currently we only show toast for screen pinning mode, and
     * no-op if the device is in locked mode.
     */
    void showLockTaskToast() {
        if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
            try {
                getStatusBarService().showPinningEscapeToast();
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to send pinning escape toast", e);
            }
        }
    }

    // Starting lock task

    /**
     * Method to start lock task mode on a given task.
     *
     * @param task the task that should be locked.
     * @param isSystemCaller indicates whether this request was initiated by the system via
     *                       {@link ActivityManagerService#startSystemLockTaskMode(int)}. If
     *                       {@code true}, this intends to start pinned mode; otherwise, we look
     *                       at the calling task's mLockTaskAuth to decide which mode to start.
     * @param callingUid the caller that requested the launch of lock task mode.
     */
    void startLockTaskMode(@NonNull TaskRecord task, boolean isSystemCaller, int callingUid) {
        if (!isSystemCaller) {
            task.mLockTaskUid = callingUid;
            if (task.mLockTaskAuth == LOCK_TASK_AUTH_PINNABLE) {
                // startLockTask() called by app, but app is not part of lock task whitelist. Show
                // app pinning request. We will come back here with isSystemCaller true.
                if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Mode default, asking user");
                StatusBarManagerInternal statusBarManager = LocalServices.getService(
                        StatusBarManagerInternal.class);
                if (statusBarManager != null) {
                    statusBarManager.showScreenPinningRequest(task.taskId);
                }
                return;
            }
        }

        // System can only initiate screen pinning, not full lock task mode
        if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
                isSystemCaller ? "Locking pinned" : "Locking fully");
        setLockTaskMode(task, isSystemCaller ? LOCK_TASK_MODE_PINNED : LOCK_TASK_MODE_LOCKED,
                "startLockTask", true);
    }

    /**
     * Start lock task mode on the given task.
     * @param lockTaskModeState whether fully locked or pinned mode.
     * @param andResume whether the task should be brought to foreground as part of the operation.
     */
    private void setLockTaskMode(@NonNull TaskRecord task, int lockTaskModeState,
                                 String reason, boolean andResume) {
        // Should have already been checked, but do it again.
        if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) {
            if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
                    "setLockTaskMode: Can't lock due to auth");
            return;
        }
        if (isLockTaskModeViolation(task)) {
            Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task.");
            return;
        }

        if (mLockTaskModeTasks.isEmpty()) {
            mSupervisor.mRecentTasks.onLockTaskModeStateChanged(lockTaskModeState, task.userId);
            // Start lock task on the handler thread
            mHandler.post(() -> performStartLockTask(
                    task.intent.getComponent().getPackageName(),
                    task.userId,
                    lockTaskModeState));
        }
        if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskMode: Locking to " + task +
                " Callers=" + Debug.getCallers(4));

        if (!mLockTaskModeTasks.contains(task)) {
            mLockTaskModeTasks.add(task);
        }

        if (task.mLockTaskUid == -1) {
            task.mLockTaskUid = task.effectiveUid;
        }

        if (andResume) {
            mSupervisor.findTaskToMoveToFront(task, 0, null, reason,
                    lockTaskModeState != LOCK_TASK_MODE_NONE);
            mSupervisor.resumeFocusedStackTopActivityLocked();
            mWindowManager.executeAppTransition();
        } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
            mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED,
                    DEFAULT_DISPLAY, task.getStack(), true /* forceNonResizable */);
        }
    }

    // This method should only be called on the handler thread
    private void performStartLockTask(String packageName, int userId, int lockTaskModeState) {
        // When lock task starts, we disable the status bars.
        try {
            if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
                getStatusBarService().showPinningEnterExitToast(true /* entering */);
            }
            mWindowManager.onLockTaskStateChanged(lockTaskModeState);
            mLockTaskModeState = lockTaskModeState;
            setStatusBarState(lockTaskModeState, userId);
            setKeyguardState(lockTaskModeState, userId);
            if (getDevicePolicyManager() != null) {
                getDevicePolicyManager().notifyLockTaskModeChanged(true, packageName, userId);
            }
        } catch (RemoteException ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * Update packages that are allowed to be launched in lock task mode.
     * @param userId Which user this whitelist is associated with
     * @param packages The whitelist of packages allowed in lock task mode
     * @see #mLockTaskPackages
     */
    void updateLockTaskPackages(int userId, String[] packages) {
        mLockTaskPackages.put(userId, packages);

        boolean taskChanged = false;
        for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) {
            final TaskRecord lockedTask = mLockTaskModeTasks.get(taskNdx);
            final boolean wasWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
                    || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
            lockedTask.setLockTaskAuth();
            final boolean isWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
                    || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;

            if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED
                    || lockedTask.userId != userId
                    || !wasWhitelisted || isWhitelisted) {
                continue;
            }

            // Terminate locked tasks that have recently lost whitelist authorization.
            if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " +
                    lockedTask + " mLockTaskAuth()=" + lockedTask.lockTaskAuthToString());
            removeLockedTask(lockedTask);
            lockedTask.performClearTaskLocked();
            taskChanged = true;
        }

        for (int displayNdx = mSupervisor.getChildCount() - 1; displayNdx >= 0; --displayNdx) {
            mSupervisor.getChildAt(displayNdx).onLockTaskPackagesUpdated();
        }

        final ActivityRecord r = mSupervisor.topRunningActivityLocked();
        final TaskRecord task = (r != null) ? r.getTask() : null;
        if (mLockTaskModeTasks.isEmpty() && task!= null
                && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
            // This task must have just been authorized.
            if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK,
                    "onLockTaskPackagesUpdated: starting new locktask task=" + task);
            setLockTaskMode(task, LOCK_TASK_MODE_LOCKED, "package updated", false);
            taskChanged = true;
        }

        if (taskChanged) {
            mSupervisor.resumeFocusedStackTopActivityLocked();
        }
    }

    boolean isPackageWhitelisted(int userId, String pkg) {
        if (pkg == null) {
            return false;
        }
        String[] whitelist;
        whitelist = mLockTaskPackages.get(userId);
        if (whitelist == null) {
            return false;
        }
        for (String whitelistedPkg : whitelist) {
            if (pkg.equals(whitelistedPkg)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Update the UI features that are enabled for LockTask mode.
     * @param userId Which user these feature flags are associated with
     * @param flags Bitfield of feature flags
     * @see DevicePolicyManager#setLockTaskFeatures(ComponentName, int)
     */
    void updateLockTaskFeatures(int userId, int flags) {
        int oldFlags = getLockTaskFeaturesForUser(userId);
        if (flags == oldFlags) {
            return;
        }

        mLockTaskFeatures.put(userId, flags);
        if (!mLockTaskModeTasks.isEmpty() && userId == mLockTaskModeTasks.get(0).userId) {
            mHandler.post(() -> {
                if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) {
                    setStatusBarState(mLockTaskModeState, userId);
                    setKeyguardState(mLockTaskModeState, userId);
                }
            });
        }
    }

    /**
     * Helper method for configuring the status bar disabled state.
     * Should only be called on the handler thread to avoid race.
     */
    private void setStatusBarState(int lockTaskModeState, int userId) {
        IStatusBarService statusBar = getStatusBarService();
        if (statusBar == null) {
            Slog.e(TAG, "Can't find StatusBarService");
            return;
        }

        // Default state, when lockTaskModeState == LOCK_TASK_MODE_NONE
        int flags1 = StatusBarManager.DISABLE_NONE;
        int flags2 = StatusBarManager.DISABLE2_NONE;

        if (lockTaskModeState == LOCK_TASK_MODE_PINNED) {
            flags1 = STATUS_BAR_MASK_PINNED;

        } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
            int lockTaskFeatures = getLockTaskFeaturesForUser(userId);
            Pair<Integer, Integer> statusBarFlags = getStatusBarDisableFlags(lockTaskFeatures);
            flags1 = statusBarFlags.first;
            flags2 = statusBarFlags.second;
        }

        try {
            statusBar.disable(flags1, mToken, mContext.getPackageName());
            statusBar.disable2(flags2, mToken, mContext.getPackageName());
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to set status bar flags", e);
        }
    }

    /**
     * Helper method for configuring the keyguard disabled state.
     * Should only be called on the handler thread to avoid race.
     */
    private void setKeyguardState(int lockTaskModeState, int userId) {
        if (lockTaskModeState == LOCK_TASK_MODE_NONE) {
            mWindowManager.reenableKeyguard(mToken);

        } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) {
            if (isKeyguardAllowed(userId)) {
                mWindowManager.reenableKeyguard(mToken);
            } else {
                // If keyguard is not secure and it is locked, dismiss the keyguard before
                // disabling it, which avoids the platform to think the keyguard is still on.
                if (mWindowManager.isKeyguardLocked() && !mWindowManager.isKeyguardSecure()) {
                    mWindowManager.dismissKeyguard(new IKeyguardDismissCallback.Stub() {
                        @Override
                        public void onDismissError() throws RemoteException {
                            Slog.i(TAG, "setKeyguardState: failed to dismiss keyguard");
                        }

                        @Override
                        public void onDismissSucceeded() throws RemoteException {
                            mHandler.post(
                                    () -> mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG));
                        }

                        @Override
                        public void onDismissCancelled() throws RemoteException {
                            Slog.i(TAG, "setKeyguardState: dismiss cancelled");
                        }
                    }, null);
                } else {
                    mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
                }
            }

        } else { // lockTaskModeState == LOCK_TASK_MODE_PINNED
            mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
        }
    }

    /**
     * Helper method for locking the device immediately. This may be necessary when the device
     * leaves the pinned mode.
     */
    private void lockKeyguardIfNeeded() {
        try {
            boolean shouldLockKeyguard = Settings.Secure.getIntForUser(
                    mContext.getContentResolver(),
                    Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
                    USER_CURRENT) != 0;
            if (shouldLockKeyguard) {
                mWindowManager.lockNow(null);
                mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
                getLockPatternUtils().requireCredentialEntry(USER_ALL);
            }
        } catch (Settings.SettingNotFoundException e) {
            // No setting, don't lock.
        }
    }

    /**
     * Translates from LockTask feature flags to StatusBarManager disable and disable2 flags.
     * @param lockTaskFlags Bitfield of flags as per
     *                      {@link DevicePolicyManager#setLockTaskFeatures(ComponentName, int)}
     * @return A {@link Pair} of {@link StatusBarManager#disable(int)} and
     *         {@link StatusBarManager#disable2(int)} flags
     */
    @VisibleForTesting
    Pair<Integer, Integer> getStatusBarDisableFlags(int lockTaskFlags) {
        // Everything is disabled by default
        int flags1 = StatusBarManager.DISABLE_MASK;
        int flags2 = StatusBarManager.DISABLE2_MASK;
        for (int i = STATUS_BAR_FLAG_MAP_LOCKED.size() - 1; i >= 0; i--) {
            Pair<Integer, Integer> statusBarFlags = STATUS_BAR_FLAG_MAP_LOCKED.valueAt(i);
            if ((STATUS_BAR_FLAG_MAP_LOCKED.keyAt(i) & lockTaskFlags) != 0) {
                flags1 &= ~statusBarFlags.first;
                flags2 &= ~statusBarFlags.second;
            }
        }
        // Some flags are not used for LockTask purposes, so we mask them
        flags1 &= STATUS_BAR_MASK_LOCKED;
        return new Pair<>(flags1, flags2);
    }

    /**
     * Gets the cached value of LockTask feature flags for a specific user.
     */
    private int getLockTaskFeaturesForUser(int userId) {
        return mLockTaskFeatures.get(userId, DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
    }

    // Should only be called on the handler thread
    @Nullable
    private IStatusBarService getStatusBarService() {
        if (mStatusBarService == null) {
            mStatusBarService = IStatusBarService.Stub.asInterface(
                    ServiceManager.checkService(STATUS_BAR_SERVICE));
            if (mStatusBarService == null) {
                Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE");
            }
        }
        return mStatusBarService;
    }

    // Should only be called on the handler thread
    @Nullable
    private IDevicePolicyManager getDevicePolicyManager() {
        if (mDevicePolicyManager == null) {
            mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface(
                    ServiceManager.checkService(DEVICE_POLICY_SERVICE));
            if (mDevicePolicyManager == null) {
                Slog.w(TAG, "warning: no DEVICE_POLICY_SERVICE");
            }
        }
        return mDevicePolicyManager;
    }

    @NonNull
    private LockPatternUtils getLockPatternUtils() {
        if (mLockPatternUtils == null) {
            // We don't preserve the LPU object to save memory
            return new LockPatternUtils(mContext);
        }
        return mLockPatternUtils;
    }

    @Nullable
    private TelecomManager getTelecomManager() {
        if (mTelecomManager == null) {
            // We don't preserve the TelecomManager object to save memory
            return mContext.getSystemService(TelecomManager.class);
        }
        return mTelecomManager;
    }

    public void dump(PrintWriter pw, String prefix) {
        pw.println(prefix + "LockTaskController");
        prefix = prefix + "  ";
        pw.println(prefix + "mLockTaskModeState=" + lockTaskModeToString());
        pw.println(prefix + "mLockTaskModeTasks=");
        for (int i = 0; i < mLockTaskModeTasks.size(); ++i) {
            pw.println(prefix + "  #" + i + " " + mLockTaskModeTasks.get(i));
        }
        pw.println(prefix + "mLockTaskPackages (userId:packages)=");
        for (int i = 0; i < mLockTaskPackages.size(); ++i) {
            pw.println(prefix + "  u" + mLockTaskPackages.keyAt(i)
                    + ":" + Arrays.toString(mLockTaskPackages.valueAt(i)));
        }
    }

    private String lockTaskModeToString() {
        switch (mLockTaskModeState) {
            case LOCK_TASK_MODE_LOCKED:
                return "LOCKED";
            case LOCK_TASK_MODE_PINNED:
                return "PINNED";
            case LOCK_TASK_MODE_NONE:
                return "NONE";
            default: return "unknown=" + mLockTaskModeState;
        }
    }
}
