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

Commit 5b32d181 authored by Orhan Uysal's avatar Orhan Uysal
Browse files

Clear transitions from the map on merge

When a transition is merged, onTransitionFinished is never called for
it. This resulted on having leftover binder objects in the map. This cl
removes them on merge.

Also don't add transitions that are not TRANSIT_OPEN to the map.

Bug: 347517200
Test: atest TaskStackTransitionObserverTest
Flag: com.android.window.flags.enable_task_stack_observer_in_shell
Change-Id: I0492e1bf5e75c82db87dfd352a425d67e85dc3b9
parent 4cfeabc6
Loading
Loading
Loading
Loading
+31 −7
Original line number Diff line number Diff line
@@ -76,21 +76,40 @@ class TaskStackTransitionObserver(
                    continue
                }

                // Filter out changes that we care about
                if (change.mode == WindowManager.TRANSIT_OPEN) {
                    change.taskInfo?.let { taskInfoList.add(it) }
                    transitionTypeList.add(change.mode)
                }
            }
            // Only add the transition to map if it has a change we care about
            if (taskInfoList.isNotEmpty()) {
                transitionToTransitionChanges.put(
                    transition,
                    TransitionChanges(taskInfoList, transitionTypeList)
                )
            }
        }
    }

    override fun onTransitionStarting(transition: IBinder) {}

    override fun onTransitionMerged(merged: IBinder, playing: IBinder) {}
    override fun onTransitionMerged(merged: IBinder, playing: IBinder) {
        val mergedTransitionChanges =
            transitionToTransitionChanges.get(merged)
                ?:
                // We are adding changes of the merged transition to changes of the playing
                // transition so if there is no changes nothing to do.
                return

        transitionToTransitionChanges.remove(merged)
        val playingTransitionChanges = transitionToTransitionChanges.get(playing)
        if (playingTransitionChanges != null) {
            playingTransitionChanges.merge(mergedTransitionChanges)
        } else {
            transitionToTransitionChanges.put(playing, mergedTransitionChanges)
        }
    }

    override fun onTransitionFinished(transition: IBinder, aborted: Boolean) {
        val taskInfoList =
@@ -138,6 +157,11 @@ class TaskStackTransitionObserver(

    private data class TransitionChanges(
        val taskInfoList: MutableList<RunningTaskInfo> = ArrayList(),
        val transitionTypeList: MutableList<Int> = ArrayList()
    )
        val transitionTypeList: MutableList<Int> = ArrayList(),
    ) {
        fun merge(transitionChanges: TransitionChanges) {
            taskInfoList.addAll(transitionChanges.taskInfoList)
            transitionTypeList.addAll(transitionChanges.transitionTypeList)
        }
    }
}
+84 −3
Original line number Diff line number Diff line
@@ -48,7 +48,6 @@ import org.mockito.kotlin.same
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever


/**
 * Test class for {@link TaskStackTransitionObserver}
 *
@@ -168,6 +167,80 @@ class TaskStackTransitionObserverTest {
            .isEqualTo(freeformOpenChange.taskInfo?.windowingMode)
    }

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

        // Create open transition
        val change =
            createChange(
                WindowManager.TRANSIT_OPEN,
                createTaskInfo(1, WindowConfiguration.WINDOWING_MODE_FREEFORM)
            )
        val transitionInfo =
            TransitionInfoBuilder(WindowManager.TRANSIT_OPEN, 0).addChange(change).build()

        // create change transition to be merged to above transition
        val mergedChange =
            createChange(
                WindowManager.TRANSIT_CHANGE,
                createTaskInfo(2, WindowConfiguration.WINDOWING_MODE_FREEFORM)
            )
        val mergedTransitionInfo =
            TransitionInfoBuilder(WindowManager.TRANSIT_CHANGE, 0).addChange(mergedChange).build()
        val mergedTransition = Mockito.mock(IBinder::class.java)

        callOnTransitionReady(transitionInfo)
        callOnTransitionReady(mergedTransitionInfo, mergedTransition)
        callOnTransitionMerged(mergedTransition)
        callOnTransitionFinished()
        executor.flushAll()

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

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

        // Create open transition
        val change =
            createChange(
                WindowManager.TRANSIT_OPEN,
                createTaskInfo(1, WindowConfiguration.WINDOWING_MODE_FREEFORM)
            )
        val transitionInfo =
            TransitionInfoBuilder(WindowManager.TRANSIT_OPEN, 0).addChange(change).build()

        // create change transition to be merged to above transition
        val mergedChange =
            createChange(
                WindowManager.TRANSIT_OPEN,
                createTaskInfo(2, WindowConfiguration.WINDOWING_MODE_FREEFORM)
            )
        val mergedTransitionInfo =
            TransitionInfoBuilder(WindowManager.TRANSIT_OPEN, 0).addChange(mergedChange).build()
        val mergedTransition = Mockito.mock(IBinder::class.java)

        callOnTransitionReady(transitionInfo)
        callOnTransitionReady(mergedTransitionInfo, mergedTransition)
        callOnTransitionMerged(mergedTransition)
        callOnTransitionFinished()
        executor.flushAll()

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

    class TestListener : TaskStackTransitionObserver.TaskStackTransitionObserverListener {
        var taskInfoToBeNotified = ActivityManager.RunningTaskInfo()

@@ -179,11 +252,14 @@ class TaskStackTransitionObserverTest {
    }

    /** Simulate calling the onTransitionReady() method */
    private fun callOnTransitionReady(transitionInfo: TransitionInfo) {
    private fun callOnTransitionReady(
        transitionInfo: TransitionInfo,
        transition: IBinder = mockTransitionBinder
    ) {
        val startT = Mockito.mock(SurfaceControl.Transaction::class.java)
        val finishT = Mockito.mock(SurfaceControl.Transaction::class.java)

        transitionObserver.onTransitionReady(mockTransitionBinder, transitionInfo, startT, finishT)
        transitionObserver.onTransitionReady(transition, transitionInfo, startT, finishT)
    }

    /** Simulate calling the onTransitionFinished() method */
@@ -191,6 +267,11 @@ class TaskStackTransitionObserverTest {
        transitionObserver.onTransitionFinished(mockTransitionBinder, false)
    }

    /** Simulate calling the onTransitionMerged() method */
    private fun callOnTransitionMerged(merged: IBinder, playing: IBinder = mockTransitionBinder) {
        transitionObserver.onTransitionMerged(merged, playing)
    }

    companion object {
        fun createTaskInfo(taskId: Int, windowingMode: Int): ActivityManager.RunningTaskInfo {
            val taskInfo = ActivityManager.RunningTaskInfo()