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

Commit 03189654 authored by Jordan Silva's avatar Jordan Silva Committed by Android (Google) Code Review
Browse files

Merge "Adds a new listener to propagate taskInfo changes when when change.mode...

Merge "Adds a new listener to propagate taskInfo changes when when change.mode is TRANSIT_CHANGE" into main
parents 55a93561 f00a12f8
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -45,4 +45,7 @@ oneway interface IRecentTasksListener {

    /** A task has moved to front. */
    oneway void onTaskMovedToFront(in RunningTaskInfo taskInfo);

    /** A task info has changed. */
    oneway void onTaskInfoChanged(in RunningTaskInfo taskInfo);
}
 No newline at end of file
+23 −0
Original line number Diff line number Diff line
@@ -288,6 +288,11 @@ public class RecentTasksController implements TaskStackListenerCallback,
        notifyRecentTasksChanged();
    }

    @Override
    public void onTaskChangedThroughTransition(@NonNull ActivityManager.RunningTaskInfo taskInfo) {
        notifyTaskInfoChanged(taskInfo);
    }

    @Override
    public void onTaskMovedToFrontThroughTransition(
            ActivityManager.RunningTaskInfo runningTaskInfo) {
@@ -355,6 +360,19 @@ public class RecentTasksController implements TaskStackListenerCallback,
        }
    }

    private void notifyTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
        if (mListener == null
                || !DesktopModeFlags.ENABLE_TASK_STACK_OBSERVER_IN_SHELL.isTrue()
                || taskInfo.realActivity == null) {
            return;
        }
        try {
            mListener.onTaskInfoChanged(taskInfo);
        } catch (RemoteException e) {
            Slog.w(TAG, "Failed call onTaskInfoChanged", e);
        }
    }

    private void notifyTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
        if (mListener == null
                || !DesktopModeFlags.ENABLE_TASK_STACK_OBSERVER_IN_SHELL.isTrue()
@@ -636,6 +654,11 @@ public class RecentTasksController implements TaskStackListenerCallback,
            public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
                mListener.call(l -> l.onTaskMovedToFront(taskInfo));
            }

            @Override
            public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
                mListener.call(l -> l.onTaskInfoChanged(taskInfo));
            }
        };

        public IRecentTasksImpl(RecentTasksController controller) {
+14 −3
Original line number Diff line number Diff line
@@ -20,8 +20,9 @@ import android.app.ActivityManager.RunningTaskInfo
import android.os.IBinder
import android.util.ArrayMap
import android.view.SurfaceControl
import android.window.TransitionInfo
import android.view.WindowManager.TRANSIT_CHANGE
import android.window.DesktopModeFlags
import android.window.TransitionInfo
import com.android.wm.shell.shared.TransitionUtil
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.transition.Transitions
@@ -69,8 +70,10 @@ class TaskStackTransitionObserver(
                // Find the first task that is opening, this should be the one at the front after
                // the transition
                if (TransitionUtil.isOpeningType(change.mode)) {
                    notifyTaskStackTransitionObserverListeners(taskInfo)
                    notifyOnTaskMovedToFront(taskInfo)
                    break
                } else if (change.mode == TRANSIT_CHANGE) {
                    notifyOnTaskChanged(taskInfo)
                }
            }
        }
@@ -95,15 +98,23 @@ class TaskStackTransitionObserver(
        taskStackTransitionObserverListeners.remove(taskStackTransitionObserverListener)
    }

    private fun notifyTaskStackTransitionObserverListeners(taskInfo: RunningTaskInfo) {
    private fun notifyOnTaskMovedToFront(taskInfo: RunningTaskInfo) {
        taskStackTransitionObserverListeners.forEach { (listener, executor) ->
            executor.execute { listener.onTaskMovedToFrontThroughTransition(taskInfo) }
        }
    }

    private fun notifyOnTaskChanged(taskInfo: RunningTaskInfo) {
        taskStackTransitionObserverListeners.forEach { (listener, executor) ->
            executor.execute { listener.onTaskChangedThroughTransition(taskInfo) }
        }
    }

    /** Listener to use to get updates regarding task stack from this observer */
    interface TaskStackTransitionObserverListener {
        /** Called when a task is moved to front. */
        fun onTaskMovedToFrontThroughTransition(taskInfo: RunningTaskInfo) {}
        /** Called when a task info has changed. */
        fun onTaskChangedThroughTransition(taskInfo: RunningTaskInfo) {}
    }
}
+153 −13
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.transition.TransitionInfoBuilder
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.windowdecor.extension.isFullscreen
import com.google.common.truth.Truth.assertThat
import dagger.Lazy
import org.junit.Before
@@ -107,8 +108,8 @@ class TaskStackTransitionObserverTest {
        callOnTransitionFinished()
        executor.flushAll()

        assertThat(listener.taskInfoToBeNotified.taskId).isEqualTo(change.taskInfo?.taskId)
        assertThat(listener.taskInfoToBeNotified.windowingMode)
        assertThat(listener.taskInfoOnTaskMovedToFront.taskId).isEqualTo(change.taskInfo?.taskId)
        assertThat(listener.taskInfoOnTaskMovedToFront.windowingMode)
            .isEqualTo(change.taskInfo?.windowingMode)
    }

@@ -130,8 +131,8 @@ class TaskStackTransitionObserverTest {
        callOnTransitionFinished()
        executor.flushAll()

        assertThat(listener.taskInfoToBeNotified.taskId).isEqualTo(1)
        assertThat(listener.taskInfoToBeNotified.windowingMode)
        assertThat(listener.taskInfoOnTaskMovedToFront.taskId).isEqualTo(1)
        assertThat(listener.taskInfoOnTaskMovedToFront.windowingMode)
            .isEqualTo(WindowConfiguration.WINDOWING_MODE_FULLSCREEN)
    }

@@ -161,9 +162,9 @@ class TaskStackTransitionObserverTest {
        callOnTransitionFinished()
        executor.flushAll()

        assertThat(listener.taskInfoToBeNotified.taskId)
        assertThat(listener.taskInfoOnTaskMovedToFront.taskId)
            .isEqualTo(freeformOpenChange.taskInfo?.taskId)
        assertThat(listener.taskInfoToBeNotified.windowingMode)
        assertThat(listener.taskInfoOnTaskMovedToFront.windowingMode)
            .isEqualTo(freeformOpenChange.taskInfo?.windowingMode)
    }

@@ -199,9 +200,15 @@ class TaskStackTransitionObserverTest {
        callOnTransitionFinished()
        executor.flushAll()

        assertThat(listener.taskInfoToBeNotified.taskId).isEqualTo(change.taskInfo?.taskId)
        assertThat(listener.taskInfoToBeNotified.windowingMode)
        assertThat(listener.taskInfoOnTaskMovedToFront.taskId).isEqualTo(change.taskInfo?.taskId)
        assertThat(listener.taskInfoOnTaskMovedToFront.windowingMode)
            .isEqualTo(change.taskInfo?.windowingMode)

        assertThat(listener.taskInfoOnTaskChanged.size).isEqualTo(1)
        with(listener.taskInfoOnTaskChanged.last()) {
            assertThat(taskId).isEqualTo(mergedChange.taskInfo?.taskId)
            assertThat(windowingMode).isEqualTo(mergedChange.taskInfo?.windowingMode)
        }
    }

    @Test
@@ -236,18 +243,151 @@ class TaskStackTransitionObserverTest {
        callOnTransitionFinished()
        executor.flushAll()

        assertThat(listener.taskInfoToBeNotified.taskId).isEqualTo(mergedChange.taskInfo?.taskId)
        assertThat(listener.taskInfoToBeNotified.windowingMode)
        assertThat(listener.taskInfoOnTaskMovedToFront.taskId)
            .isEqualTo(mergedChange.taskInfo?.taskId)
        assertThat(listener.taskInfoOnTaskMovedToFront.windowingMode)
            .isEqualTo(mergedChange.taskInfo?.windowingMode)
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_TASK_STACK_OBSERVER_IN_SHELL)
    fun taskChange_freeformWindowToFullscreenWindow_listenerNotified() {
        val listener = TestListener()
        val executor = TestShellExecutor()
        transitionObserver.addTaskStackTransitionObserverListener(listener, executor)
        val freeformState =
            createChange(
                WindowManager.TRANSIT_OPEN,
                createTaskInfo(1, WindowConfiguration.WINDOWING_MODE_FREEFORM)
            )
        val transitionInfoOpen =
            TransitionInfoBuilder(WindowManager.TRANSIT_OPEN, 0).addChange(freeformState).build()
        callOnTransitionReady(transitionInfoOpen)
        callOnTransitionFinished()
        executor.flushAll()

        assertThat(listener.taskInfoOnTaskMovedToFront.taskId)
            .isEqualTo(freeformState.taskInfo?.taskId)
        assertThat(listener.taskInfoOnTaskMovedToFront.windowingMode)
            .isEqualTo(freeformState.taskInfo?.windowingMode)
        assertThat(listener.taskInfoOnTaskMovedToFront.isFullscreen).isEqualTo(false)

        // create change transition to update the windowing mode to full screen.
        val fullscreenState =
            createChange(
                WindowManager.TRANSIT_CHANGE,
                createTaskInfo(1, WindowConfiguration.WINDOWING_MODE_FULLSCREEN)
            )
        val transitionInfoChange =
            TransitionInfoBuilder(WindowManager.TRANSIT_CHANGE, 0)
                .addChange(fullscreenState)
                .build()

        callOnTransitionReady(transitionInfoChange)
        callOnTransitionFinished()
        executor.flushAll()

        // Asserting whether freeformState remains the same as before the change
        assertThat(listener.taskInfoOnTaskMovedToFront.taskId)
            .isEqualTo(freeformState.taskInfo?.taskId)
        assertThat(listener.taskInfoOnTaskMovedToFront.isFullscreen).isEqualTo(false)

        // Asserting changes
        assertThat(listener.taskInfoOnTaskChanged.size).isEqualTo(1)
        with(listener.taskInfoOnTaskChanged.last()) {
            assertThat(taskId).isEqualTo(fullscreenState.taskInfo?.taskId)
            assertThat(isFullscreen).isEqualTo(true)
        }
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_TASK_STACK_OBSERVER_IN_SHELL)
    fun singleTransition_withOpenAndChange_onlyOpenIsNotified() {
        val listener = TestListener()
        val executor = TestShellExecutor()
        transitionObserver.addTaskStackTransitionObserverListener(listener, executor)

        // Creating multiple changes to be fired in a single transition
        val freeformState =
            createChange(
                mode = WindowManager.TRANSIT_OPEN,
                taskInfo = createTaskInfo(1, WindowConfiguration.WINDOWING_MODE_FREEFORM)
            )
        val fullscreenState =
            createChange(
                mode = WindowManager.TRANSIT_CHANGE,
                taskInfo = createTaskInfo(1, WindowConfiguration.WINDOWING_MODE_FULLSCREEN)
            )

        val transitionInfoWithChanges =
            TransitionInfoBuilder(WindowManager.TRANSIT_CHANGE, 0)
                .addChange(freeformState)
                .addChange(fullscreenState)
                .build()

        callOnTransitionReady(transitionInfoWithChanges)
        callOnTransitionFinished()
        executor.flushAll()

        assertThat(listener.taskInfoOnTaskMovedToFront.taskId)
            .isEqualTo(freeformState.taskInfo?.taskId)
        assertThat(listener.taskInfoOnTaskMovedToFront.isFullscreen).isEqualTo(false)
        assertThat(listener.taskInfoOnTaskChanged.size).isEqualTo(0)
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_TASK_STACK_OBSERVER_IN_SHELL)
    fun singleTransition_withMultipleChanges_listenerNotified_forEachChange() {
        val listener = TestListener()
        val executor = TestShellExecutor()
        transitionObserver.addTaskStackTransitionObserverListener(listener, executor)

        val taskId = 1

        // Creating multiple changes to be fired in a single transition
        val changes =
            listOf(
                    WindowConfiguration.WINDOWING_MODE_FREEFORM,
                    WindowConfiguration.WINDOW_CONFIG_DISPLAY_ROTATION,
                    WindowConfiguration.WINDOWING_MODE_FULLSCREEN
                )
                .map { change ->
                    createChange(
                        mode = WindowManager.TRANSIT_CHANGE,
                        taskInfo = createTaskInfo(taskId, change)
                    )
                }

        val transitionInfoWithChanges =
            TransitionInfoBuilder(WindowManager.TRANSIT_CHANGE, 0)
                .apply { changes.forEach { c -> this@apply.addChange(c) } }
                .build()

        callOnTransitionReady(transitionInfoWithChanges)
        callOnTransitionFinished()
        executor.flushAll()

        assertThat(listener.taskInfoOnTaskChanged.size).isEqualTo(changes.size)
        changes.forEachIndexed { index, change ->
            assertThat(listener.taskInfoOnTaskChanged[index].taskId)
                .isEqualTo(change.taskInfo?.taskId)
            assertThat(listener.taskInfoOnTaskChanged[index].windowingMode)
                .isEqualTo(change.taskInfo?.windowingMode)
        }
    }

    class TestListener : TaskStackTransitionObserver.TaskStackTransitionObserverListener {
        var taskInfoToBeNotified = ActivityManager.RunningTaskInfo()
        var taskInfoOnTaskMovedToFront = ActivityManager.RunningTaskInfo()
        var taskInfoOnTaskChanged = mutableListOf<ActivityManager.RunningTaskInfo>()

        override fun onTaskMovedToFrontThroughTransition(
            taskInfo: ActivityManager.RunningTaskInfo
        ) {
            taskInfoToBeNotified = taskInfo
            taskInfoOnTaskMovedToFront = taskInfo
        }

        override fun onTaskChangedThroughTransition(taskInfo: ActivityManager.RunningTaskInfo) {
            taskInfoOnTaskChanged += taskInfo
        }
    }