Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a0969af authored by Ats Jenk's avatar Ats Jenk Committed by Android (Google) Code Review
Browse files

Merge "Move active task tracking to a repository" into tm-qpr-dev

parents 745d055d 8a3cf44c
Loading
Loading
Loading
Loading
+22 −1
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@ import com.android.wm.shell.common.annotations.ShellBackgroundThread;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.common.annotations.ShellSplashscreenThread;
import com.android.wm.shell.compatui.CompatUIController;
import com.android.wm.shell.desktopmode.DesktopMode;
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
import com.android.wm.shell.displayareahelper.DisplayAreaHelper;
import com.android.wm.shell.displayareahelper.DisplayAreaHelperController;
import com.android.wm.shell.draganddrop.DragAndDropController;
@@ -477,11 +479,12 @@ public abstract class WMShellBaseModule {
            ShellInit shellInit,
            ShellCommandHandler shellCommandHandler,
            TaskStackListenerImpl taskStackListener,
            Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
            @ShellMainThread ShellExecutor mainExecutor
    ) {
        return Optional.ofNullable(
                RecentTasksController.create(context, shellInit, shellCommandHandler,
                        taskStackListener, mainExecutor));
                        taskStackListener, desktopModeTaskRepository, mainExecutor));
    }

    //
@@ -665,6 +668,24 @@ public abstract class WMShellBaseModule {
        return new ShellController(shellInit, shellCommandHandler, mainExecutor);
    }

    //
    // Desktop mode (optional feature)
    //

    @BindsOptionalOf
    @DynamicOverride
    abstract DesktopModeTaskRepository optionalDesktopModeTaskRepository();

    @WMSingleton
    @Provides
    static Optional<DesktopModeTaskRepository> providesDesktopModeTaskRepository(
            @DynamicOverride Optional<DesktopModeTaskRepository> desktopModeTaskRepository) {
        if (DesktopMode.IS_SUPPORTED) {
            return desktopModeTaskRepository;
        }
        return Optional.empty();
    }

    //
    // Misc
    //
+10 −2
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import com.android.wm.shell.common.annotations.ShellBackgroundThread;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.desktopmode.DesktopMode;
import com.android.wm.shell.desktopmode.DesktopModeController;
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.freeform.FreeformComponents;
import com.android.wm.shell.freeform.FreeformTaskListener;
@@ -220,14 +221,14 @@ public abstract class WMShellModule {
            Context context,
            ShellInit shellInit,
            ShellTaskOrganizer shellTaskOrganizer,
            Optional<RecentTasksController> recentTasksController,
            Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
            WindowDecorViewModel<?> windowDecorViewModel) {
        // TODO(b/238217847): Temporarily add this check here until we can remove the dynamic
        //                    override for this controller from the base module
        ShellInit init = FreeformComponents.isFreeformEnabled(context)
                ? shellInit
                : null;
        return new FreeformTaskListener<>(init, shellTaskOrganizer, recentTasksController,
        return new FreeformTaskListener<>(init, shellTaskOrganizer, desktopModeTaskRepository,
                windowDecorViewModel);
    }

@@ -610,6 +611,13 @@ public abstract class WMShellModule {
        }
    }

    @WMSingleton
    @Provides
    @DynamicOverride
    static DesktopModeTaskRepository provideDesktopModeTaskRepository() {
        return new DesktopModeTaskRepository();
    }

    //
    // Misc
    //
+89 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.wm.shell.desktopmode

import android.util.ArraySet

/**
 * Keeps track of task data related to desktop mode.
 */
class DesktopModeTaskRepository {

    /**
     * Set of task ids that are marked as active in desktop mode.
     * Active tasks in desktop mode are freeform tasks that are visible or have been visible after
     * desktop mode was activated.
     * Task gets removed from this list when it vanishes. Or when desktop mode is turned off.
     */
    private val activeTasks = ArraySet<Int>()
    private val listeners = ArraySet<Listener>()

    /**
     * Add a [Listener] to be notified of updates to the repository.
     */
    fun addListener(listener: Listener) {
        listeners.add(listener)
    }

    /**
     * Remove a previously registered [Listener]
     */
    fun removeListener(listener: Listener) {
        listeners.remove(listener)
    }

    /**
     * Mark a task with given [taskId] as active.
     */
    fun addActiveTask(taskId: Int) {
        val added = activeTasks.add(taskId)
        if (added) {
            listeners.onEach { it.onActiveTasksChanged() }
        }
    }

    /**
     * Remove task with given [taskId] from active tasks.
     */
    fun removeActiveTask(taskId: Int) {
        val removed = activeTasks.remove(taskId)
        if (removed) {
            listeners.onEach { it.onActiveTasksChanged() }
        }
    }

    /**
     * Check if a task with the given [taskId] was marked as an active task
     */
    fun isActiveTask(taskId: Int): Boolean {
        return activeTasks.contains(taskId)
    }

    /**
     * Get a set of the active tasks
     */
    fun getActiveTasks(): ArraySet<Int> {
        return ArraySet(activeTasks)
    }

    /**
     * Defines interface for classes that can listen to changes in repository state.
     */
    interface Listener {
        fun onActiveTasksChanged()
    }
}
+7 −7
Original line number Diff line number Diff line
@@ -29,8 +29,8 @@ import androidx.annotation.Nullable;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.desktopmode.DesktopMode;
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
@@ -49,7 +49,7 @@ public class FreeformTaskListener<T extends AutoCloseable>
    private static final String TAG = "FreeformTaskListener";

    private final ShellTaskOrganizer mShellTaskOrganizer;
    private final Optional<RecentTasksController> mRecentTasksOptional;
    private final Optional<DesktopModeTaskRepository> mDesktopModeTaskRepository;
    private final WindowDecorViewModel<T> mWindowDecorationViewModel;

    private final SparseArray<State<T>> mTasks = new SparseArray<>();
@@ -64,11 +64,11 @@ public class FreeformTaskListener<T extends AutoCloseable>
    public FreeformTaskListener(
            ShellInit shellInit,
            ShellTaskOrganizer shellTaskOrganizer,
            Optional<RecentTasksController> recentTasksController,
            Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
            WindowDecorViewModel<T> windowDecorationViewModel) {
        mShellTaskOrganizer = shellTaskOrganizer;
        mWindowDecorationViewModel = windowDecorationViewModel;
        mRecentTasksOptional = recentTasksController;
        mDesktopModeTaskRepository = desktopModeTaskRepository;
        if (shellInit != null) {
            shellInit.addInitCallback(this::onInit, this);
        }
@@ -93,7 +93,7 @@ public class FreeformTaskListener<T extends AutoCloseable>
        if (DesktopMode.IS_SUPPORTED && taskInfo.isVisible) {
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
                    "Adding active freeform task: #%d", taskInfo.taskId);
            mRecentTasksOptional.ifPresent(rt -> rt.addActiveFreeformTask(taskInfo.taskId));
            mDesktopModeTaskRepository.ifPresent(it -> it.addActiveTask(taskInfo.taskId));
        }
    }

@@ -126,7 +126,7 @@ public class FreeformTaskListener<T extends AutoCloseable>
        if (DesktopMode.IS_SUPPORTED) {
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
                    "Removing active freeform task: #%d", taskInfo.taskId);
            mRecentTasksOptional.ifPresent(rt -> rt.removeActiveFreeformTask(taskInfo.taskId));
            mDesktopModeTaskRepository.ifPresent(it -> it.removeActiveTask(taskInfo.taskId));
        }

        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
@@ -154,7 +154,7 @@ public class FreeformTaskListener<T extends AutoCloseable>
            if (taskInfo.isVisible) {
                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
                        "Adding active freeform task: #%d", taskInfo.taskId);
                mRecentTasksOptional.ifPresent(rt -> rt.addActiveFreeformTask(taskInfo.taskId));
                mDesktopModeTaskRepository.ifPresent(it -> it.addActiveTask(taskInfo.taskId));
            }
        }
    }
+13 −26
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.desktopmode.DesktopMode;
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellInit;
@@ -53,19 +54,20 @@ import com.android.wm.shell.util.SplitBounds;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * Manages the recent task list from the system, caching it as necessary.
 */
public class RecentTasksController implements TaskStackListenerCallback,
        RemoteCallable<RecentTasksController> {
        RemoteCallable<RecentTasksController>, DesktopModeTaskRepository.Listener {
    private static final String TAG = RecentTasksController.class.getSimpleName();

    private final Context mContext;
    private final ShellCommandHandler mShellCommandHandler;
    private final Optional<DesktopModeTaskRepository> mDesktopModeTaskRepository;
    private final ShellExecutor mMainExecutor;
    private final TaskStackListenerImpl mTaskStackListener;
    private final RecentTasks mImpl = new RecentTasksImpl();
@@ -83,15 +85,6 @@ public class RecentTasksController implements TaskStackListenerCallback,
     */
    private final Map<Integer, SplitBounds> mTaskSplitBoundsMap = new HashMap<>();

    /**
     * Set of taskId's that have been launched in freeform mode.
     * This includes tasks that are currently running, visible and in freeform mode. And also
     * includes tasks that are running in the background, are no longer visible, but at some point
     * were visible to the user.
     * This is used to decide which freeform apps belong to the user's desktop.
     */
    private final HashSet<Integer> mActiveFreeformTasks = new HashSet<>();

    /**
     * Creates {@link RecentTasksController}, returns {@code null} if the feature is not
     * supported.
@@ -102,24 +95,27 @@ public class RecentTasksController implements TaskStackListenerCallback,
            ShellInit shellInit,
            ShellCommandHandler shellCommandHandler,
            TaskStackListenerImpl taskStackListener,
            Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
            @ShellMainThread ShellExecutor mainExecutor
    ) {
        if (!context.getResources().getBoolean(com.android.internal.R.bool.config_hasRecents)) {
            return null;
        }
        return new RecentTasksController(context, shellInit, shellCommandHandler, taskStackListener,
                mainExecutor);
                desktopModeTaskRepository, mainExecutor);
    }

    RecentTasksController(Context context,
            ShellInit shellInit,
            ShellCommandHandler shellCommandHandler,
            TaskStackListenerImpl taskStackListener,
            Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
            ShellExecutor mainExecutor) {
        mContext = context;
        mShellCommandHandler = shellCommandHandler;
        mIsDesktopMode = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
        mTaskStackListener = taskStackListener;
        mDesktopModeTaskRepository = desktopModeTaskRepository;
        mMainExecutor = mainExecutor;
        shellInit.addInitCallback(this::onInit, this);
    }
@@ -131,6 +127,7 @@ public class RecentTasksController implements TaskStackListenerCallback,
    private void onInit() {
        mShellCommandHandler.addDumpCallback(this::dump, this);
        mTaskStackListener.addListener(this);
        mDesktopModeTaskRepository.ifPresent(it -> it.addListener(this));
    }

    /**
@@ -217,19 +214,8 @@ public class RecentTasksController implements TaskStackListenerCallback,
        notifyRecentTasksChanged();
    }

    /**
     * Mark a task with given {@code taskId} as active in freeform
     */
    public void addActiveFreeformTask(int taskId) {
        mActiveFreeformTasks.add(taskId);
        notifyRecentTasksChanged();
    }

    /**
     * Remove task with given {@code taskId} from active freeform tasks
     */
    public void removeActiveFreeformTask(int taskId) {
        mActiveFreeformTasks.remove(taskId);
    @Override
    public void onActiveTasksChanged() {
        notifyRecentTasksChanged();
    }

@@ -312,7 +298,8 @@ public class RecentTasksController implements TaskStackListenerCallback,
                continue;
            }

            if (desktopModeActive && mActiveFreeformTasks.contains(taskInfo.taskId)) {
            if (desktopModeActive && mDesktopModeTaskRepository.isPresent()
                    && mDesktopModeTaskRepository.get().isActiveTask(taskInfo.taskId)) {
                // Freeform tasks will be added as a separate entry
                freeformTasks.add(taskInfo);
                continue;
Loading