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

Commit 18029e2a authored by Mariia Sandrikova's avatar Mariia Sandrikova Committed by Android (Google) Code Review
Browse files

Merge "Refactor task listeners mapping in ShellTaskOrganiser"

parents 3ffe566a fe891989
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
{
  "version": "1.0.0",
  "messages": {
    "-1823823103": {
      "message": "Add listener for types=%s listener=%s",
      "level": "VERBOSE",
      "group": "WM_SHELL_TASK_ORG",
      "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
    },
    "-1534364071": {
      "message": "onTransitionReady %s: %s",
      "level": "VERBOSE",
@@ -37,12 +43,6 @@
      "group": "WM_SHELL_TASK_ORG",
      "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
    },
    "-242812822": {
      "message": "Add listener for modes=%s listener=%s",
      "level": "VERBOSE",
      "group": "WM_SHELL_TASK_ORG",
      "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
    },
    "-191422040": {
      "message": "Transition animations finished, notifying core %s",
      "level": "VERBOSE",
+75 −28
Original line number Diff line number Diff line
@@ -16,9 +16,17 @@

package com.android.wm.shell;

import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;

import android.annotation.IntDef;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.WindowConfiguration.WindowingMode;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
@@ -33,7 +41,6 @@ import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.protolog.ShellProtoLogGroup;

import java.util.ArrayList;
import java.util.Arrays;

/**
@@ -42,6 +49,23 @@ import java.util.Arrays;
 */
public class ShellTaskOrganizer extends TaskOrganizer {

    // Intentionally using negative numbers here so the positive numbers can be used
    // for task id specific listeners that will be added later.
    public static final int TASK_LISTENER_TYPE_UNDEFINED = -1;
    public static final int TASK_LISTENER_TYPE_FULLSCREEN = -2;
    public static final int TASK_LISTENER_TYPE_MULTI_WINDOW = -3;
    public static final int TASK_LISTENER_TYPE_PIP = -4;
    public static final int TASK_LISTENER_TYPE_SPLIT_SCREEN = -5;

    @IntDef(prefix = {"TASK_LISTENER_TYPE_"}, value = {
            TASK_LISTENER_TYPE_UNDEFINED,
            TASK_LISTENER_TYPE_FULLSCREEN,
            TASK_LISTENER_TYPE_MULTI_WINDOW,
            TASK_LISTENER_TYPE_PIP,
            TASK_LISTENER_TYPE_SPLIT_SCREEN,
    })
    public @interface TaskListenerType {}

    private static final String TAG = "ShellTaskOrganizer";

    /**
@@ -54,7 +78,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
        default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {}
    }

    private final SparseArray<TaskListener> mListenerByWindowingMode = new SparseArray<>();
    private final SparseArray<TaskListener> mTaskListenersByType = new SparseArray<>();

    // Keeps track of all the tasks reported to this organizer (changes in windowing mode will
    // require us to report to both old and new listeners)
@@ -73,29 +97,29 @@ public class ShellTaskOrganizer extends TaskOrganizer {
            SyncTransactionQueue syncQueue, TransactionPool transactionPool,
            ShellExecutor mainExecutor, ShellExecutor animExecutor) {
        super(taskOrganizerController);
        addListener(new FullscreenTaskListener(syncQueue), WINDOWING_MODE_FULLSCREEN);
        addListener(new FullscreenTaskListener(syncQueue), TASK_LISTENER_TYPE_FULLSCREEN);
        mTransitions = new Transitions(this, transactionPool, mainExecutor, animExecutor);
        if (Transitions.ENABLE_SHELL_TRANSITIONS) registerTransitionPlayer(mTransitions);
    }

    /**
     * Adds a listener for tasks in a specific windowing mode.
     * Adds a listener for tasks with given types.
     */
    public void addListener(TaskListener listener, int... windowingModes) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Add listener for modes=%s listener=%s",
                Arrays.toString(windowingModes), listener);
        for (int winMode : windowingModes) {
            if (mListenerByWindowingMode.get(winMode) != null) {
                throw new IllegalArgumentException("Listener for winMode=" + winMode
    public void addListener(TaskListener listener, @TaskListenerType int... taskListenerTypes) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Add listener for types=%s listener=%s",
                Arrays.toString(taskListenerTypes), listener);
        for (int listenerType : taskListenerTypes) {
            if (mTaskListenersByType.get(listenerType) != null) {
                throw new IllegalArgumentException("Listener for listenerType=" + listenerType
                        + " already exists");
            }
            mListenerByWindowingMode.put(winMode, listener);
            mTaskListenersByType.put(listenerType, listener);

            // Notify the listener of all existing tasks in that windowing mode
            // Notify the listener of all existing tasks with the given type.
            for (int i = mTasks.size() - 1; i >= 0; i--) {
                Pair<RunningTaskInfo, SurfaceControl> data = mTasks.valueAt(i);
                int taskWinMode = data.first.configuration.windowConfiguration.getWindowingMode();
                if (taskWinMode == winMode) {
                final @TaskListenerType int taskListenerType = getTaskListenerType(data.first);
                if (taskListenerType == listenerType) {
                    listener.onTaskAppeared(data.first, data.second);
                }
            }
@@ -107,12 +131,12 @@ public class ShellTaskOrganizer extends TaskOrganizer {
     */
    public void removeListener(TaskListener listener) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Remove listener=%s", listener);
        final int index = mListenerByWindowingMode.indexOfValue(listener);
        final int index = mTaskListenersByType.indexOfValue(listener);
        if (index == -1) {
            Log.w(TAG, "No registered listener found");
            return;
        }
        mListenerByWindowingMode.removeAt(index);
        mTaskListenersByType.removeAt(index);
    }

    @Override
@@ -120,7 +144,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task appeared taskId=%d",
                taskInfo.taskId);
        mTasks.put(taskInfo.taskId, new Pair<>(taskInfo, leash));
        final TaskListener listener = mListenerByWindowingMode.get(getWindowingMode(taskInfo));
        final TaskListener listener = mTaskListenersByType.get(getTaskListenerType(taskInfo));
        if (listener != null) {
            listener.onTaskAppeared(taskInfo, leash);
        }
@@ -131,23 +155,23 @@ public class ShellTaskOrganizer extends TaskOrganizer {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task info changed taskId=%d",
                taskInfo.taskId);
        final Pair<RunningTaskInfo, SurfaceControl> data = mTasks.get(taskInfo.taskId);
        final int winMode = getWindowingMode(taskInfo);
        final int prevWinMode = getWindowingMode(data.first);
        final @TaskListenerType int listenerType = getTaskListenerType(taskInfo);
        final @TaskListenerType int prevListenerType = getTaskListenerType(data.first);
        mTasks.put(taskInfo.taskId, new Pair<>(taskInfo, data.second));
        if (prevWinMode != -1 && prevWinMode != winMode) {
            // TODO: We currently send vanished/appeared as the task moves between win modes, but
        if (prevListenerType != listenerType) {
            // TODO: We currently send vanished/appeared as the task moves between types, but
            //       we should consider adding a different mode-changed callback
            TaskListener listener = mListenerByWindowingMode.get(prevWinMode);
            TaskListener listener = mTaskListenersByType.get(prevListenerType);
            if (listener != null) {
                listener.onTaskVanished(taskInfo);
            }
            listener = mListenerByWindowingMode.get(winMode);
            listener = mTaskListenersByType.get(listenerType);
            if (listener != null) {
                SurfaceControl leash = data.second;
                listener.onTaskAppeared(taskInfo, leash);
            }
        } else {
            final TaskListener listener = mListenerByWindowingMode.get(winMode);
            final TaskListener listener = mTaskListenersByType.get(listenerType);
            if (listener != null) {
                listener.onTaskInfoChanged(taskInfo);
            }
@@ -158,7 +182,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
    public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task root back pressed taskId=%d",
                taskInfo.taskId);
        final TaskListener listener = mListenerByWindowingMode.get(getWindowingMode(taskInfo));
        final TaskListener listener = mTaskListenersByType.get(getTaskListenerType(taskInfo));
        if (listener != null) {
            listener.onBackPressedOnTaskRoot(taskInfo);
        }
@@ -168,15 +192,38 @@ public class ShellTaskOrganizer extends TaskOrganizer {
    public void onTaskVanished(RunningTaskInfo taskInfo) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Task vanished taskId=%d",
                taskInfo.taskId);
        final int prevWinMode = getWindowingMode(mTasks.get(taskInfo.taskId).first);
        final @TaskListenerType int prevListenerType =
                getTaskListenerType(mTasks.get(taskInfo.taskId).first);
        mTasks.remove(taskInfo.taskId);
        final TaskListener listener = mListenerByWindowingMode.get(prevWinMode);
        final TaskListener listener = mTaskListenersByType.get(prevListenerType);
        if (listener != null) {
            listener.onTaskVanished(taskInfo);
        }
    }

    private int getWindowingMode(RunningTaskInfo taskInfo) {
    @TaskListenerType
    private static int getTaskListenerType(RunningTaskInfo runningTaskInfo) {
        // Right now it's N:1 mapping but in the future different task listerners
        // may be triggered by one windowing mode depending on task parameters.
        switch (getWindowingMode(runningTaskInfo)) {
            case WINDOWING_MODE_FULLSCREEN:
                return TASK_LISTENER_TYPE_FULLSCREEN;
            case WINDOWING_MODE_MULTI_WINDOW:
                return TASK_LISTENER_TYPE_MULTI_WINDOW;
            case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
            case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
                return TASK_LISTENER_TYPE_SPLIT_SCREEN;
            case WINDOWING_MODE_PINNED:
                return TASK_LISTENER_TYPE_PIP;
            case WINDOWING_MODE_FREEFORM:
            case WINDOWING_MODE_UNDEFINED:
            default:
                return TASK_LISTENER_TYPE_UNDEFINED;
        }
    }

    @WindowingMode
    private static int getWindowingMode(RunningTaskInfo taskInfo) {
        return taskInfo.configuration.windowConfiguration.getWindowingMode();
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;

import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP;
@@ -282,7 +283,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        if (!PipUtils.hasSystemFeature(context)) {
            Log.w(TAG, "Device not support PIP feature");
        } else {
            mTaskOrganizer.addListener(this, WINDOWING_MODE_PINNED);
            mTaskOrganizer.addListener(this, TASK_LISTENER_TYPE_PIP);
            displayController.addDisplayWindowListener(this);
        }
    }
+5 −5
Original line number Diff line number Diff line
@@ -23,8 +23,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.view.Display.DEFAULT_DISPLAY;

import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_SPLIT_SCREEN;

import android.app.ActivityManager.RunningTaskInfo;
import android.app.WindowConfiguration;
import android.graphics.Rect;
import android.os.RemoteException;
import android.util.Log;
@@ -56,17 +57,16 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener {
                    ShellTaskOrganizer shellTaskOrganizer) {
        mSplitScreenController = splitScreenController;
        mTaskOrganizer = shellTaskOrganizer;
        mTaskOrganizer.addListener(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
        mTaskOrganizer.addListener(this, TASK_LISTENER_TYPE_SPLIT_SCREEN);
    }

    void init() throws RemoteException {
        synchronized (this) {
            try {
                mPrimary = mTaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
                        WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
                        WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
                mSecondary = mTaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
                        WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
                        WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
            } catch (Exception e) {
                // teardown to prevent callbacks
                mTaskOrganizer.removeListener(this);
+10 −7
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ package com.android.wm.shell;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;

import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_MULTI_WINDOW;
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
@@ -102,10 +105,10 @@ public class ShellTaskOrganizerTests {
    }

    @Test
    public void testOneListenerPerMode() {
        mOrganizer.addListener(new TrackingTaskListener(), WINDOWING_MODE_MULTI_WINDOW);
    public void testOneListenerPerType() {
        mOrganizer.addListener(new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW);
        try {
            mOrganizer.addListener(new TrackingTaskListener(), WINDOWING_MODE_MULTI_WINDOW);
            mOrganizer.addListener(new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW);
            fail("Expected exception due to already registered listener");
        } catch (Exception e) {
            // Expected failure
@@ -116,7 +119,7 @@ public class ShellTaskOrganizerTests {
    public void testAppearedVanished() {
        RunningTaskInfo taskInfo = createTaskInfo(WINDOWING_MODE_MULTI_WINDOW);
        TrackingTaskListener listener = new TrackingTaskListener();
        mOrganizer.addListener(listener, WINDOWING_MODE_MULTI_WINDOW);
        mOrganizer.addListener(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
        mOrganizer.onTaskAppeared(taskInfo, null);
        assertTrue(listener.appeared.contains(taskInfo));

@@ -130,7 +133,7 @@ public class ShellTaskOrganizerTests {
        mOrganizer.onTaskAppeared(taskInfo, null);

        TrackingTaskListener listener = new TrackingTaskListener();
        mOrganizer.addListener(listener, WINDOWING_MODE_MULTI_WINDOW);
        mOrganizer.addListener(listener, TASK_LISTENER_TYPE_MULTI_WINDOW);
        assertTrue(listener.appeared.contains(taskInfo));
    }

@@ -139,8 +142,8 @@ public class ShellTaskOrganizerTests {
        RunningTaskInfo taskInfo = createTaskInfo(WINDOWING_MODE_MULTI_WINDOW);
        TrackingTaskListener mwListener = new TrackingTaskListener();
        TrackingTaskListener pipListener = new TrackingTaskListener();
        mOrganizer.addListener(mwListener, WINDOWING_MODE_MULTI_WINDOW);
        mOrganizer.addListener(pipListener, WINDOWING_MODE_PINNED);
        mOrganizer.addListener(mwListener, TASK_LISTENER_TYPE_MULTI_WINDOW);
        mOrganizer.addListener(pipListener, TASK_LISTENER_TYPE_PIP);
        mOrganizer.onTaskAppeared(taskInfo, null);
        assertTrue(mwListener.appeared.contains(taskInfo));
        assertTrue(pipListener.appeared.isEmpty());