/*
 * Copyright (C) 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.wm;

import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;

import android.app.ActivityManager.RunningTaskInfo;
import android.app.WindowConfiguration.ActivityType;
import android.app.WindowConfiguration.WindowingMode;
import android.os.UserHandle;
import android.util.ArraySet;

import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledLambda;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;

/**
 * Class for resolving the set of running tasks in the system.
 */
class RunningTasks {

    // Comparator to sort by last active time (descending)
    private static final Comparator<Task> LAST_ACTIVE_TIME_COMPARATOR =
            (o1, o2) -> Long.signum(o2.lastActiveTime - o1.lastActiveTime);

    private final TreeSet<Task> mTmpSortedSet = new TreeSet<>(LAST_ACTIVE_TIME_COMPARATOR);
    private final ArrayList<Task> mTmpStackTasks = new ArrayList<>();

    private int mCallingUid;
    private int mUserId;
    private boolean mCrossUser;
    private ArraySet<Integer> mProfileIds;
    private boolean mAllowed;
    private int mIgnoreActivityType;
    private int mIgnoreWindowingMode;
    private ActivityStack mTopDisplayFocusStack;

    void getTasks(int maxNum, List<RunningTaskInfo> list, @ActivityType int ignoreActivityType,
            @WindowingMode int ignoreWindowingMode, RootActivityContainer root,
            int callingUid, boolean allowed, boolean crossUser, ArraySet<Integer> profileIds) {
        // Return early if there are no tasks to fetch
        if (maxNum <= 0) {
            return;
        }

        // Gather all of the tasks across all of the tasks, and add them to the sorted set
        mTmpSortedSet.clear();
        mCallingUid = callingUid;
        mUserId = UserHandle.getUserId(callingUid);
        mCrossUser = crossUser;
        mProfileIds = profileIds;
        mAllowed = allowed;
        mIgnoreActivityType = ignoreActivityType;
        mIgnoreWindowingMode = ignoreWindowingMode;
        mTopDisplayFocusStack = root.getTopDisplayFocusedStack();

        final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this,
                PooledLambda.__(Task.class));
        root.mRootWindowContainer.forAllTasks(c, false);
        c.recycle();

        // Take the first {@param maxNum} tasks and create running task infos for them
        final Iterator<Task> iter = mTmpSortedSet.iterator();
        while (iter.hasNext()) {
            if (maxNum == 0) {
                break;
            }

            final Task task = iter.next();
            list.add(createRunningTaskInfo(task));
            maxNum--;
        }
    }

    private void processTask(Task task) {
        if (task.getTopNonFinishingActivity() == null) {
            // Skip if there are no activities in the task
            return;
        }
        if (task.effectiveUid != mCallingUid) {
            if (task.mUserId != mUserId && !mCrossUser && !mProfileIds.contains(task.mUserId)) {
                // Skip if the caller does not have cross user permission or cannot access
                // the task's profile
                return;
            }
            if (!mAllowed && !task.isActivityTypeHome()) {
                // Skip if the caller isn't allowed to fetch this task, except for the home
                // task which we always return.
                return;
            }
        }
        if (mIgnoreActivityType != ACTIVITY_TYPE_UNDEFINED
                && task.getActivityType() == mIgnoreActivityType) {
            // Skip ignored activity type
            return;
        }
        if (mIgnoreWindowingMode != WINDOWING_MODE_UNDEFINED
                && task.getWindowingMode() == mIgnoreWindowingMode) {
            // Skip ignored windowing mode
            return;
        }

        final ActivityStack stack = task.getStack();
        if (stack == mTopDisplayFocusStack && stack.getTopMostTask() == task) {
            // For the focused stack top task, update the last stack active time so that it can be
            // used to determine the order of the tasks (it may not be set for newly created tasks)
            task.touchActiveTime();
        }

        mTmpSortedSet.add(task);
    }

    /** Constructs a {@link RunningTaskInfo} from a given {@param task}. */
    private RunningTaskInfo createRunningTaskInfo(Task task) {
        final RunningTaskInfo rti = new RunningTaskInfo();
        task.fillTaskInfo(rti);
        // Fill in some deprecated values
        rti.id = rti.taskId;
        return rti;
    }
}
