diff options
4 files changed, 98 insertions, 13 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxTransitionObserver.kt index b50716ad07a3..8b830e769c70 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxTransitionObserver.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/LetterboxTransitionObserver.kt @@ -22,6 +22,7 @@ import android.view.SurfaceControl import android.window.TransitionInfo import com.android.internal.protolog.ProtoLog import com.android.window.flags.Flags.appCompatRefactoring +import com.android.wm.shell.common.transition.TransitionStateHolder import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_APP_COMPAT import com.android.wm.shell.shared.TransitionUtil.isClosingType import com.android.wm.shell.sysui.ShellInit @@ -33,7 +34,8 @@ import com.android.wm.shell.transition.Transitions class LetterboxTransitionObserver( shellInit: ShellInit, private val transitions: Transitions, - private val letterboxController: LetterboxController + private val letterboxController: LetterboxController, + private val transitionStateHolder: TransitionStateHolder ) : Transitions.TransitionObserver { companion object { @@ -71,11 +73,11 @@ class LetterboxTransitionObserver( change.endAbsBounds.height() ) with(letterboxController) { - if (isClosingType(change.mode)) { - destroyLetterboxSurface( - key, - startTransaction - ) + // TODO(b/380274087) Handle return to home from a recents transition. + if (isClosingType(change.mode) && + !transitionStateHolder.isRecentsTransitionRunning()) { + // For the other types of close we need to check the recents. + destroyLetterboxSurface(key, finishTransaction) } else { val isTopActivityLetterboxed = ti.appCompatTaskInfo.isTopActivityLetterboxed if (isTopActivityLetterboxed) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index 974535385334..860431a80851 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -68,6 +68,7 @@ import com.android.wm.shell.common.MultiInstanceHelper; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TaskStackListenerImpl; +import com.android.wm.shell.common.transition.TransitionStateHolder; import com.android.wm.shell.compatui.letterbox.LetterboxCommandHandler; import com.android.wm.shell.compatui.letterbox.LetterboxController; import com.android.wm.shell.compatui.letterbox.LetterboxTransitionObserver; @@ -1316,9 +1317,11 @@ public abstract class WMShellModule { static LetterboxTransitionObserver provideLetterboxTransitionObserver( @NonNull ShellInit shellInit, @NonNull Transitions transitions, - @NonNull LetterboxController letterboxController + @NonNull LetterboxController letterboxController, + @NonNull TransitionStateHolder transitionStateHolder ) { - return new LetterboxTransitionObserver(shellInit, transitions, letterboxController); + return new LetterboxTransitionObserver(shellInit, transitions, letterboxController, + transitionStateHolder); } @WMSingleton diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxTransitionObserverTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxTransitionObserverTest.kt index 9c6afcb8be63..07bfefe0b275 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxTransitionObserverTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/LetterboxTransitionObserverTest.kt @@ -25,9 +25,12 @@ import android.testing.AndroidTestingRunner import android.view.SurfaceControl import android.view.WindowManager.TRANSIT_CLOSE import androidx.test.filters.SmallTest +import com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn import com.android.window.flags.Flags import com.android.wm.shell.ShellTestCase import com.android.wm.shell.common.ShellExecutor +import com.android.wm.shell.common.transition.TransitionStateHolder +import com.android.wm.shell.recents.RecentsTransitionHandler import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.Transitions import com.android.wm.shell.util.TransitionObserverInputBuilder @@ -37,6 +40,7 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.any +import org.mockito.kotlin.doReturn import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.never @@ -154,21 +158,38 @@ class LetterboxTransitionObserverTest : ShellTestCase() { } @Test - fun `When closing change letterbox surface destroy is triggered`() { + fun `When closing change with no recents running letterbox surfaces are destroyed`() { runTestScenario { r -> executeTransitionObserverTest(observerFactory = r.observerFactory) { r.invokeShellInit() inputBuilder { buildTransitionInfo() + r.configureRecentsState(running = false) r.createClosingChange(inputBuilder = this) } validateOutput { r.destroyEventDetected(expected = true) - r.creationEventDetected(expected = false) - r.visibilityEventDetected(expected = false, visible = false) - r.updateSurfaceBoundsEventDetected(expected = false) + } + } + } + } + + @Test + fun `When closing change and recents are running letterbox surfaces are not destroyed`() { + runTestScenario { r -> + executeTransitionObserverTest(observerFactory = r.observerFactory) { + r.invokeShellInit() + + inputBuilder { + buildTransitionInfo() + r.createClosingChange(inputBuilder = this) + r.configureRecentsState(running = true) + } + + validateOutput { + r.destroyEventDetected(expected = false) } } } @@ -197,6 +218,7 @@ class LetterboxTransitionObserverTest : ShellTestCase() { private val transitions: Transitions private val letterboxController: LetterboxController private val letterboxObserver: LetterboxTransitionObserver + private val transitionStateHolder: TransitionStateHolder val observerFactory: () -> LetterboxTransitionObserver @@ -205,8 +227,16 @@ class LetterboxTransitionObserverTest : ShellTestCase() { shellInit = ShellInit(executor) transitions = mock<Transitions>() letterboxController = mock<LetterboxController>() + transitionStateHolder = + TransitionStateHolder(shellInit, mock<RecentsTransitionHandler>()) + spyOn(transitionStateHolder) letterboxObserver = - LetterboxTransitionObserver(shellInit, transitions, letterboxController) + LetterboxTransitionObserver( + shellInit, + transitions, + letterboxController, + transitionStateHolder + ) observerFactory = { letterboxObserver } } @@ -218,6 +248,10 @@ class LetterboxTransitionObserverTest : ShellTestCase() { verify(transitions, expected.asMode()).registerObserver(observer()) } + fun configureRecentsState(running: Boolean) { + doReturn(running).`when`(transitionStateHolder).isRecentsTransitionRunning() + } + fun creationEventDetected( expected: Boolean, displayId: Int = DISPLAY_ID, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/TransitionObserverTestUtils.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/TransitionObserverTestUtils.kt index 0e15668a05a7..a328b5b2bb6b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/TransitionObserverTestUtils.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/util/TransitionObserverTestUtils.kt @@ -77,6 +77,30 @@ class TransitionObserverTestContext : TransitionObserverTestStep { validateObj.validate() } + fun validateOnMerged( + validate: + TransitionObserverOnTransitionMergedValidation.() -> Unit + ) { + val validateObj = TransitionObserverOnTransitionMergedValidation() + transitionObserver.onTransitionMerged( + validateObj.playing, + validateObj.merged + ) + validateObj.validate() + } + + fun validateOnFinished( + validate: + TransitionObserverOnTransitionFinishedValidation.() -> Unit + ) { + val validateObj = TransitionObserverOnTransitionFinishedValidation() + transitionObserver.onTransitionFinished( + transitionReadyInput.transition, + validateObj.aborted + ) + validateObj.validate() + } + fun invokeObservable() { transitionObserver.onTransitionReady( transitionReadyInput.transition, @@ -162,6 +186,28 @@ class TransitionObserverInputBuilder : TransitionObserverTestStep { class TransitionObserverResultValidation : TransitionObserverTestStep /** + * Phase responsible for the execution of validation methods after the + * [TransitionObservable#onTransitionMerged] has been executed. + */ +class TransitionObserverOnTransitionMergedValidation : TransitionObserverTestStep { + val merged = mock<IBinder>() + val playing = mock<IBinder>() + + init { + spyOn(merged) + spyOn(playing) + } +} + +/** + * Phase responsible for the execution of validation methods after the + * [TransitionObservable#onTransitionFinished] has been executed. + */ +class TransitionObserverOnTransitionFinishedValidation : TransitionObserverTestStep { + var aborted: Boolean = false +} + +/** * Allows to run a test about a specific [TransitionObserver] passing the specific * implementation and input value as parameters for the [TransitionObserver#onTransitionReady] * method. |