/*
 * 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.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.StatusBarManager.DISABLE_BACK;
import static android.app.StatusBarManager.DISABLE_HOME;
import static android.app.StatusBarManager.DISABLE_MASK;
import static android.app.StatusBarManager.DISABLE_NONE;
import static android.app.StatusBarManager.DISABLE_RECENT;
import static android.content.Context.DEVICE_POLICY_SERVICE;
import static android.content.Context.STATUS_BAR_SERVICE;
import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_CURRENT;
import static android.provider.Settings.Secure.LOCK_TO_APP_EXIT_LOCKED;
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.admin.IDevicePolicyManager;
import android.content.Context;
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.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
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;

/**
 * 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 = DISABLE_MASK
            & (~DISABLE_BACK);
    @VisibleForTesting
    static final int STATUS_BAR_MASK_PINNED = DISABLE_MASK
            & (~DISABLE_BACK)
            & (~DISABLE_HOME)
            & (~DISABLE_RECENT);

    /** 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;

    /**
     * Helper that is responsible for showing the right toast when a disallowed activity operation
     * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
     * fully locked mode we only show that unlocking is blocked.
     */
    @VisibleForTesting
    LockTaskNotify mLockTaskNotify;

    /**
     * The chain of tasks in lockTask mode. The current frontmost task is at the top, and tasks
     * may be finished until there is only one entry left. If this is empty the system is not
     * in lockTask mode.
     */
    private final ArrayList<TaskRecord> mLockTaskModeTasks = new ArrayList<>();

    /**
     * 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;

    /**
     * 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 can be moved to the back of the stack. Locked tasks cannot be
     * moved to the back of the stack.
     */
    boolean checkLockedTask(TaskRecord task) {
        if (mLockTaskModeTasks.contains(task)) {
            showLockTaskToast();
            return true;
        }
        return false;
    }

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

    /**
     * @return whether the requested task is allowed 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 allowed to be launched.
     */
    boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) {
        if (isLockTaskModeViolationInternal(task, isNewClearTask)) {
            showLockTaskToast();
            return true;
        }
        return false;
    }

    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 (getLockedTask() == task && !isNewClearTask) {
            // If the task is already at the top and won't be cleared, then allow the operation
            return false;
        }
        final int lockTaskAuth = task.mLockTaskAuth;
        switch (lockTaskAuth) {
            case LOCK_TASK_AUTH_DONT_LOCK:
                return !mLockTaskModeTasks.isEmpty();
            case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
            case LOCK_TASK_AUTH_LAUNCHABLE:
            case LOCK_TASK_AUTH_WHITELISTED:
                return false;
            case LOCK_TASK_AUTH_PINNABLE:
                // Pinnable tasks can't be launched on top of locktask tasks.
                return !mLockTaskModeTasks.isEmpty();
            default:
                Slog.w(TAG, "isLockTaskModeViolation: invalid lockTaskAuth value=" + lockTaskAuth);
                return true;
        }
    }

    /**
     * Stop the current lock task mode.
     *
     * @param isSystemInitiated indicates whether this request was initiated by the system via
     *                          {@link ActivityManagerService#stopSystemLockTaskMode()}.
     * @param callingUid the caller that requested the end of lock task mode.
     * @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(boolean isSystemInitiated, int callingUid) {
        final TaskRecord lockTask = getLockedTask();
        if (lockTask == null || mLockTaskModeState == LOCK_TASK_MODE_NONE) {
            // Our work here is done.
            return;
        }

        if (isSystemInitiated && mLockTaskModeState == LOCK_TASK_MODE_LOCKED) {
            // As system can only start app pinning, we also only let it unlock in this mode.
            showLockTaskToast();
            return;
        }

        // 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 (!isSystemInitiated && callingUid != lockTask.mLockTaskUid
                && (lockTask.mLockTaskUid != 0 || callingUid != lockTask.effectiveUid)) {
            throw new SecurityException("Invalid uid, expected " + lockTask.mLockTaskUid
                    + " callingUid=" + callingUid + " effectiveUid=" + lockTask.effectiveUid);
        }

        clearLockTaskMode("stopLockTask");
    }

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

    /**
     * Remove the topmost task from the locked task list. If this is the last task in the list, it
     * will result in the end of locked task mode.
     */
    void clearLockTaskMode(String reason) {
        // Take out of lock task mode if necessary
        final TaskRecord lockedTask = getLockedTask();
        if (lockedTask != null) {
            removeLockedTask(lockedTask);
            if (!mLockTaskModeTasks.isEmpty()) {
                // There are locked tasks remaining, can only finish this task, not unlock it.
                if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
                        "setLockTaskMode: Tasks remaining, can't unlock");
                lockedTask.performClearTaskLocked();
                mSupervisor.resumeFocusedStackTopActivityLocked();
                return;
            }
        }
        if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
                "setLockTaskMode: No tasks to unlock. Callers=" + Debug.getCallers(4));
    }

    // 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 {
            if (getStatusBarService() != null) {
                getStatusBarService().disable(DISABLE_NONE, mToken,
                        mContext.getPackageName());
            }
            mWindowManager.reenableKeyguard(mToken);
            if (getDevicePolicyManager() != null) {
                getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId);
            }
            getLockTaskNotify().show(false);
            try {
                boolean shouldLockKeyguard = Settings.Secure.getIntForUser(
                        mContext.getContentResolver(),
                        LOCK_TO_APP_EXIT_LOCKED,
                        USER_CURRENT) != 0;
                if (mLockTaskModeState == LOCK_TASK_MODE_PINNED && shouldLockKeyguard) {
                    mWindowManager.lockNow(null);
                    mWindowManager.dismissKeyguard(null /* callback */);
                    getLockPatternUtils().requireCredentialEntry(USER_ALL);
                }
            } catch (Settings.SettingNotFoundException e) {
                // No setting, don't lock.
            }
        } catch (RemoteException ex) {
            throw new RuntimeException(ex);
        } finally {
            mLockTaskModeState = LOCK_TASK_MODE_NONE;
        }
    }

    /**
     * Show the lock task violation toast.
     */
    void showLockTaskToast() {
        mHandler.post(() -> getLockTaskNotify().showToast(mLockTaskModeState));
    }

    // Starting lock task

    /**
     * Method to start lock task mode on a given task.
     *
     * @param task the task that should be locked.
     * @param isSystemInitiated indicates whether this request was initiated by the system via
     *                          {@link ActivityManagerService#startSystemLockTaskMode(int)}.
     * @param callingUid the caller that requested the launch of lock task mode.
     */
    void startLockTaskMode(@NonNull TaskRecord task, boolean isSystemInitiated,
            int callingUid) {
        if (!isSystemInitiated) {
            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 isSystemInitiated 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, isSystemInitiated ? "Locking pinned" : "Locking fully");
        setLockTaskMode(task, isSystemInitiated ? 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()) {
            // Start lock task on the handler thread
            mHandler.post(() -> performStartLockTask(
                    task.intent.getComponent().getPackageName(),
                    task.userId,
                    lockTaskModeState));
        }

        // Add it or move it to the top.
        if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskMode: Locking to " + task +
                " Callers=" + Debug.getCallers(4));
        mLockTaskModeTasks.remove(task);
        mLockTaskModeTasks.add(task);

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

        if (andResume) {
            mSupervisor.findTaskToMoveToFrontLocked(task, 0, null, reason,
                    lockTaskModeState != LOCK_TASK_MODE_NONE);
            mSupervisor.resumeFocusedStackTopActivityLocked();
            mWindowManager.executeAppTransition();
        } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
            mSupervisor.handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, DEFAULT_DISPLAY,
                    task.getStackId(), 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 {
            getLockTaskNotify().show(true);
            mLockTaskModeState = lockTaskModeState;
            if (getStatusBarService() != null) {
                int flags = 0;
                if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) {
                    flags = STATUS_BAR_MASK_LOCKED;
                } else if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
                    flags = STATUS_BAR_MASK_PINNED;
                }
                getStatusBarService().disable(flags, mToken, mContext.getPackageName());
            }
            mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
            if (getDevicePolicyManager() != null) {
                getDevicePolicyManager().notifyLockTaskModeChanged(true, packageName, userId);
            }
        } catch (RemoteException ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * Called when the list of packages whitelisted for lock task mode is changed. Any currently
     * locked tasks that got removed from the whitelist will be finished.
     */
    // TODO: Missing unit tests
    void onLockTaskPackagesUpdated() {
        boolean didSomething = 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 (wasWhitelisted && !isWhitelisted) {
                // Lost whitelisting authorization. End it now.
                if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " +
                        lockedTask + " mLockTaskAuth()=" + lockedTask.lockTaskAuthToString());
                removeLockedTask(lockedTask);
                lockedTask.performClearTaskLocked();
                didSomething = true;
            }
        }

        for (int displayNdx = mSupervisor.getChildCount() - 1; displayNdx >= 0; --displayNdx) {
            ArrayList<ActivityStack> stacks = mSupervisor.getChildAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                stack.onLockTaskPackagesUpdatedLocked();
            }
        }
        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);
            didSomething = true;
        }
        if (didSomething) {
            mSupervisor.resumeFocusedStackTopActivityLocked();
        }
    }

    /**
     * @return the topmost locked task
     */
    private TaskRecord getLockedTask() {
        final int top = mLockTaskModeTasks.size() - 1;
        if (top >= 0) {
            return mLockTaskModeTasks.get(top);
        }
        return null;
    }

    // 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;
    }

    // Should only be called on the handler thread
    @NonNull
    private LockTaskNotify getLockTaskNotify() {
        if (mLockTaskNotify == null) {
            mLockTaskNotify = new LockTaskNotify(mContext);
        }
        return mLockTaskNotify;
    }

    public void dump(PrintWriter pw, String prefix) {
        pw.print(prefix); pw.print("mLockTaskModeState=" + lockTaskModeToString());
        pw.println(" mLockTaskModeTasks" + mLockTaskModeTasks);
    }

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