Loading data/etc/services.core.protolog.json +6 −0 Original line number Original line Diff line number Diff line Loading @@ -961,6 +961,12 @@ "group": "WM_DEBUG_RECENTS_ANIMATIONS", "group": "WM_DEBUG_RECENTS_ANIMATIONS", "at": "com\/android\/server\/wm\/RecentsAnimationController.java" "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, }, "-1204565480": { "message": "Adding display switch to existing collecting transition", "level": "DEBUG", "group": "WM_DEBUG_WINDOW_TRANSITIONS", "at": "com\/android\/server\/wm\/PhysicalDisplaySwitchTransitionLauncher.java" }, "-1198579104": { "-1198579104": { "message": "Pushing next activity %s out to target's task %s", "message": "Pushing next activity %s out to target's task %s", "level": "VERBOSE", "level": "VERBOSE", Loading libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java +39 −1 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.view.WindowManager.TRANSIT_CHANGE; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TRANSITIONS; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TRANSITIONS; import android.animation.ValueAnimator; import android.app.ActivityManager; import android.app.ActivityManager; import android.os.IBinder; import android.os.IBinder; import android.view.SurfaceControl; import android.view.SurfaceControl; Loading Loading @@ -74,9 +75,9 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene Executor executor, Executor executor, Transitions transitions) { Transitions transitions) { mUnfoldProgressProvider = unfoldProgressProvider; mUnfoldProgressProvider = unfoldProgressProvider; mTransitions = transitions; mTransactionPool = transactionPool; mTransactionPool = transactionPool; mExecutor = executor; mExecutor = executor; mTransitions = transitions; mAnimators.add(splitUnfoldTaskAnimator); mAnimators.add(splitUnfoldTaskAnimator); mAnimators.add(fullscreenUnfoldAnimator); mAnimators.add(fullscreenUnfoldAnimator); Loading Loading @@ -104,6 +105,16 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull TransitionFinishCallback finishCallback) { @NonNull TransitionFinishCallback finishCallback) { if (hasUnfold(info) && transition != mTransition) { // Take over transition that has unfold, we might receive it if no other handler // accepted request in handleRequest, e.g. for rotation + unfold or // TRANSIT_NONE + unfold transitions mTransition = transition; ProtoLog.v(WM_SHELL_TRANSITIONS, "UnfoldTransitionHandler: " + "take over startAnimation"); } if (transition != mTransition) return false; if (transition != mTransition) return false; for (int i = 0; i < mAnimators.size(); i++) { for (int i = 0; i < mAnimators.size(); i++) { Loading Loading @@ -203,6 +214,33 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene && request.getDisplayChange().isPhysicalDisplayChanged()); && request.getDisplayChange().isPhysicalDisplayChanged()); } } /** Whether `transitionInfo` contains an unfold action. */ public boolean hasUnfold(@NonNull TransitionInfo transitionInfo) { // Unfold animation won't play when animations are disabled if (!ValueAnimator.areAnimatorsEnabled()) return false; for (int i = 0; i < transitionInfo.getChanges().size(); i++) { final TransitionInfo.Change change = transitionInfo.getChanges().get(i); if ((change.getFlags() & TransitionInfo.FLAG_IS_DISPLAY) != 0) { if (change.getEndAbsBounds() == null || change.getStartAbsBounds() == null) { continue; } // Handle only unfolding, currently we don't have an animation when folding final int afterArea = change.getEndAbsBounds().width() * change.getEndAbsBounds().height(); final int beforeArea = change.getStartAbsBounds().width() * change.getStartAbsBounds().height(); if (afterArea > beforeArea) { return true; } } } return false; } @Nullable @Nullable @Override @Override public WindowContainerTransaction handleRequest(@NonNull IBinder transition, public WindowContainerTransaction handleRequest(@NonNull IBinder transition, Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java +95 −0 Original line number Original line Diff line number Diff line Loading @@ -17,9 +17,12 @@ package com.android.wm.shell.unfold; package com.android.wm.shell.unfold; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_NONE; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock; Loading @@ -27,6 +30,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify; import android.app.ActivityManager; import android.app.ActivityManager; import android.graphics.Rect; import android.os.Binder; import android.os.Binder; import android.os.IBinder; import android.os.IBinder; import android.view.Display; import android.view.Display; Loading @@ -35,6 +39,9 @@ import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerTransaction; import android.window.WindowContainerTransaction; import com.android.window.flags.FakeFeatureFlagsImpl; import com.android.window.flags.FeatureFlags; import com.android.window.flags.Flags; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.sysui.ShellInit; Loading @@ -45,6 +52,8 @@ import com.android.wm.shell.unfold.animation.SplitTaskUnfoldAnimator; import org.junit.Before; import org.junit.Before; import org.junit.Test; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.ArrayList; import java.util.ArrayList; import java.util.List; import java.util.List; Loading Loading @@ -131,6 +140,55 @@ public class UnfoldTransitionHandlerTest { verify(finishCallback, never()).onTransitionFinished(any()); verify(finishCallback, never()).onTransitionFinished(any()); } } @Test public void startAnimation_sameTransitionAsHandleRequest_startsAnimation() { TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo(); mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class); boolean animationStarted = mUnfoldTransitionHandler.startAnimation( mTransition, mock(TransitionInfo.class), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); assertThat(animationStarted).isTrue(); } @Test public void startAnimation_differentTransitionFromRequestWithUnfold_startsAnimation() { mUnfoldTransitionHandler.handleRequest(new Binder(), createNoneTransitionInfo()); TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class); boolean animationStarted = mUnfoldTransitionHandler.startAnimation( mTransition, createUnfoldTransitionInfo(), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); assertThat(animationStarted).isTrue(); } @Test public void startAnimation_differentTransitionFromRequestWithoutUnfold_doesNotStart() { mUnfoldTransitionHandler.handleRequest(new Binder(), createNoneTransitionInfo()); TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class); boolean animationStarted = mUnfoldTransitionHandler.startAnimation( mTransition, createNonUnfoldTransitionInfo(), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); assertThat(animationStarted).isFalse(); } @Test @Test public void startAnimation_animationFinishes_finishesTheTransition() { public void startAnimation_animationFinishes_finishesTheTransition() { TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo(); TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo(); Loading Loading @@ -215,6 +273,12 @@ public class UnfoldTransitionHandlerTest { triggerTaskInfo, /* remoteTransition= */ null, displayChange, 0 /* flags */); triggerTaskInfo, /* remoteTransition= */ null, displayChange, 0 /* flags */); } } private TransitionRequestInfo createNoneTransitionInfo() { return new TransitionRequestInfo(TRANSIT_NONE, /* triggerTask= */ null, /* remoteTransition= */ null, /* displayChange= */ null, /* flags= */ 0); } private static class TestShellUnfoldProgressProvider implements ShellUnfoldProgressProvider, private static class TestShellUnfoldProgressProvider implements ShellUnfoldProgressProvider, ShellUnfoldProgressProvider.UnfoldListener { ShellUnfoldProgressProvider.UnfoldListener { Loading Loading @@ -277,4 +341,35 @@ public class UnfoldTransitionHandlerTest { return false; return false; } } } } static class TestCase { private final boolean mShouldHandleMixedUnfold; public TestCase(boolean shouldHandleMixedUnfold) { mShouldHandleMixedUnfold = shouldHandleMixedUnfold; } public boolean mixedUnfoldFlagEnabled() { return mShouldHandleMixedUnfold; } @Override public String toString() { return "shouldHandleMixedUnfold flag = " + mShouldHandleMixedUnfold; } } private TransitionInfo createUnfoldTransitionInfo() { TransitionInfo transitionInfo = new TransitionInfo(TRANSIT_CHANGE, /* flags= */ 0); TransitionInfo.Change change = new TransitionInfo.Change(null, mock(SurfaceControl.class)); change.setStartAbsBounds(new Rect(0, 0, 10, 10)); change.setEndAbsBounds(new Rect(0, 0, 100, 100)); change.setFlags(TransitionInfo.FLAG_IS_DISPLAY); transitionInfo.addChange(change); return transitionInfo; } private TransitionInfo createNonUnfoldTransitionInfo() { return new TransitionInfo(TRANSIT_CHANGE, /* flags= */ 0); } } } No newline at end of file services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java +22 −7 Original line number Original line Diff line number Diff line Loading @@ -34,6 +34,8 @@ import android.window.TransitionRequestInfo; import android.window.WindowContainerTransaction; import android.window.WindowContainerTransaction; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.ProtoLogGroup; import com.android.internal.protolog.common.ProtoLog; import com.android.server.wm.DeviceStateController.DeviceState; import com.android.server.wm.DeviceStateController.DeviceState; public class PhysicalDisplaySwitchTransitionLauncher { public class PhysicalDisplaySwitchTransitionLauncher { Loading Loading @@ -117,14 +119,27 @@ public class PhysicalDisplaySwitchTransitionLauncher { displayChange.setEndAbsBounds(endAbsBounds); displayChange.setEndAbsBounds(endAbsBounds); displayChange.setPhysicalDisplayChanged(true); displayChange.setPhysicalDisplayChanged(true); final Transition t = mTransitionController.requestTransitionIfNeeded(TRANSIT_CHANGE, mTransition = null; if (mTransitionController.isCollecting()) { // Add display container to the currently collecting transition mTransitionController.collect(mDisplayContent); mTransition = mTransitionController.getCollectingTransition(); // Make sure that transition is not ready until we finish the remote display change mTransition.setReady(mDisplayContent, false); ProtoLog.d(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Adding display switch to existing collecting transition"); } else { mTransition = mTransitionController.requestTransitionIfNeeded(TRANSIT_CHANGE, 0 /* flags */, 0 /* flags */, mDisplayContent, mDisplayContent, null /* remoteTransition */, mDisplayContent, mDisplayContent, null /* remoteTransition */, displayChange); displayChange); } if (t != null) { if (mTransition != null) { mDisplayContent.mAtmService.startPowerMode(POWER_MODE_REASON_CHANGE_DISPLAY); mAtmService.startPowerMode(POWER_MODE_REASON_CHANGE_DISPLAY); mTransition = t; } } mShouldRequestTransitionOnDisplaySwitch = false; mShouldRequestTransitionOnDisplaySwitch = false; Loading services/tests/wmtests/src/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncherTest.java +27 −2 Original line number Original line Diff line number Diff line Loading @@ -34,6 +34,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.Mockito.when; import android.animation.ValueAnimator; import android.animation.ValueAnimator; import android.annotation.Nullable; import android.content.Context; import android.content.Context; import android.content.res.Resources; import android.content.res.Resources; import android.graphics.Rect; import android.graphics.Rect; Loading Loading @@ -61,8 +62,7 @@ import org.mockito.MockitoAnnotations; */ */ @SmallTest @SmallTest @Presubmit @Presubmit @RunWith(WindowTestRunner.class) public class PhysicalDisplaySwitchTransitionLauncherTest { public class PhysicalDisplaySwitchTransitionLauncherTest extends WindowTestsBase { @Mock @Mock DisplayContent mDisplayContent; DisplayContent mDisplayContent; Loading @@ -73,6 +73,8 @@ public class PhysicalDisplaySwitchTransitionLauncherTest extends WindowTestsBase @Mock @Mock ActivityTaskManagerService mActivityTaskManagerService; ActivityTaskManagerService mActivityTaskManagerService; @Mock @Mock BLASTSyncEngine mSyncEngine; @Mock TransitionController mTransitionController; TransitionController mTransitionController; private PhysicalDisplaySwitchTransitionLauncher mTarget; private PhysicalDisplaySwitchTransitionLauncher mTarget; Loading Loading @@ -216,6 +218,20 @@ public class PhysicalDisplaySwitchTransitionLauncherTest extends WindowTestsBase assertTransitionNotRequested(); assertTransitionNotRequested(); } } @Test public void testDisplaySwitchAfterUnfolding_otherCollectingTransition_collectsDisplaySwitch() { givenCollectingTransition(createTransition(TRANSIT_CHANGE)); givenAllAnimationsEnabled(); mTarget.foldStateChanged(FOLDED); mTarget.foldStateChanged(OPEN); requestDisplaySwitch(); // Collects to the current transition verify(mTransitionController).collect(mDisplayContent); } @Test @Test public void testDisplaySwitch_whenNoContentInDisplayContent_noTransition() { public void testDisplaySwitch_whenNoContentInDisplayContent_noTransition() { givenAllAnimationsEnabled(); givenAllAnimationsEnabled(); Loading Loading @@ -267,6 +283,15 @@ public class PhysicalDisplaySwitchTransitionLauncherTest extends WindowTestsBase when(mTransitionController.isShellTransitionsEnabled()).thenReturn(enabled); when(mTransitionController.isShellTransitionsEnabled()).thenReturn(enabled); } } private void givenCollectingTransition(@Nullable Transition transition) { when(mTransitionController.isCollecting()).thenReturn(transition != null); when(mTransitionController.getCollectingTransition()).thenReturn(transition); } private Transition createTransition(int type) { return new Transition(type, /* flags= */ 0, mTransitionController, mSyncEngine); } private void givenDisplayContentHasContent(boolean hasContent) { private void givenDisplayContentHasContent(boolean hasContent) { when(mDisplayContent.getLastHasContent()).thenReturn(hasContent); when(mDisplayContent.getLastHasContent()).thenReturn(hasContent); } } Loading Loading
data/etc/services.core.protolog.json +6 −0 Original line number Original line Diff line number Diff line Loading @@ -961,6 +961,12 @@ "group": "WM_DEBUG_RECENTS_ANIMATIONS", "group": "WM_DEBUG_RECENTS_ANIMATIONS", "at": "com\/android\/server\/wm\/RecentsAnimationController.java" "at": "com\/android\/server\/wm\/RecentsAnimationController.java" }, }, "-1204565480": { "message": "Adding display switch to existing collecting transition", "level": "DEBUG", "group": "WM_DEBUG_WINDOW_TRANSITIONS", "at": "com\/android\/server\/wm\/PhysicalDisplaySwitchTransitionLauncher.java" }, "-1198579104": { "-1198579104": { "message": "Pushing next activity %s out to target's task %s", "message": "Pushing next activity %s out to target's task %s", "level": "VERBOSE", "level": "VERBOSE", Loading
libs/WindowManager/Shell/src/com/android/wm/shell/unfold/UnfoldTransitionHandler.java +39 −1 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.view.WindowManager.TRANSIT_CHANGE; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TRANSITIONS; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TRANSITIONS; import android.animation.ValueAnimator; import android.app.ActivityManager; import android.app.ActivityManager; import android.os.IBinder; import android.os.IBinder; import android.view.SurfaceControl; import android.view.SurfaceControl; Loading Loading @@ -74,9 +75,9 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene Executor executor, Executor executor, Transitions transitions) { Transitions transitions) { mUnfoldProgressProvider = unfoldProgressProvider; mUnfoldProgressProvider = unfoldProgressProvider; mTransitions = transitions; mTransactionPool = transactionPool; mTransactionPool = transactionPool; mExecutor = executor; mExecutor = executor; mTransitions = transitions; mAnimators.add(splitUnfoldTaskAnimator); mAnimators.add(splitUnfoldTaskAnimator); mAnimators.add(fullscreenUnfoldAnimator); mAnimators.add(fullscreenUnfoldAnimator); Loading Loading @@ -104,6 +105,16 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull TransitionFinishCallback finishCallback) { @NonNull TransitionFinishCallback finishCallback) { if (hasUnfold(info) && transition != mTransition) { // Take over transition that has unfold, we might receive it if no other handler // accepted request in handleRequest, e.g. for rotation + unfold or // TRANSIT_NONE + unfold transitions mTransition = transition; ProtoLog.v(WM_SHELL_TRANSITIONS, "UnfoldTransitionHandler: " + "take over startAnimation"); } if (transition != mTransition) return false; if (transition != mTransition) return false; for (int i = 0; i < mAnimators.size(); i++) { for (int i = 0; i < mAnimators.size(); i++) { Loading Loading @@ -203,6 +214,33 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene && request.getDisplayChange().isPhysicalDisplayChanged()); && request.getDisplayChange().isPhysicalDisplayChanged()); } } /** Whether `transitionInfo` contains an unfold action. */ public boolean hasUnfold(@NonNull TransitionInfo transitionInfo) { // Unfold animation won't play when animations are disabled if (!ValueAnimator.areAnimatorsEnabled()) return false; for (int i = 0; i < transitionInfo.getChanges().size(); i++) { final TransitionInfo.Change change = transitionInfo.getChanges().get(i); if ((change.getFlags() & TransitionInfo.FLAG_IS_DISPLAY) != 0) { if (change.getEndAbsBounds() == null || change.getStartAbsBounds() == null) { continue; } // Handle only unfolding, currently we don't have an animation when folding final int afterArea = change.getEndAbsBounds().width() * change.getEndAbsBounds().height(); final int beforeArea = change.getStartAbsBounds().width() * change.getStartAbsBounds().height(); if (afterArea > beforeArea) { return true; } } } return false; } @Nullable @Nullable @Override @Override public WindowContainerTransaction handleRequest(@NonNull IBinder transition, public WindowContainerTransaction handleRequest(@NonNull IBinder transition, Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/unfold/UnfoldTransitionHandlerTest.java +95 −0 Original line number Original line Diff line number Diff line Loading @@ -17,9 +17,12 @@ package com.android.wm.shell.unfold; package com.android.wm.shell.unfold; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_NONE; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock; Loading @@ -27,6 +30,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify; import android.app.ActivityManager; import android.app.ActivityManager; import android.graphics.Rect; import android.os.Binder; import android.os.Binder; import android.os.IBinder; import android.os.IBinder; import android.view.Display; import android.view.Display; Loading @@ -35,6 +39,9 @@ import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerTransaction; import android.window.WindowContainerTransaction; import com.android.window.flags.FakeFeatureFlagsImpl; import com.android.window.flags.FeatureFlags; import com.android.window.flags.Flags; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.sysui.ShellInit; Loading @@ -45,6 +52,8 @@ import com.android.wm.shell.unfold.animation.SplitTaskUnfoldAnimator; import org.junit.Before; import org.junit.Before; import org.junit.Test; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.ArrayList; import java.util.ArrayList; import java.util.List; import java.util.List; Loading Loading @@ -131,6 +140,55 @@ public class UnfoldTransitionHandlerTest { verify(finishCallback, never()).onTransitionFinished(any()); verify(finishCallback, never()).onTransitionFinished(any()); } } @Test public void startAnimation_sameTransitionAsHandleRequest_startsAnimation() { TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo(); mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo); TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class); boolean animationStarted = mUnfoldTransitionHandler.startAnimation( mTransition, mock(TransitionInfo.class), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); assertThat(animationStarted).isTrue(); } @Test public void startAnimation_differentTransitionFromRequestWithUnfold_startsAnimation() { mUnfoldTransitionHandler.handleRequest(new Binder(), createNoneTransitionInfo()); TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class); boolean animationStarted = mUnfoldTransitionHandler.startAnimation( mTransition, createUnfoldTransitionInfo(), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); assertThat(animationStarted).isTrue(); } @Test public void startAnimation_differentTransitionFromRequestWithoutUnfold_doesNotStart() { mUnfoldTransitionHandler.handleRequest(new Binder(), createNoneTransitionInfo()); TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class); boolean animationStarted = mUnfoldTransitionHandler.startAnimation( mTransition, createNonUnfoldTransitionInfo(), mock(SurfaceControl.Transaction.class), mock(SurfaceControl.Transaction.class), finishCallback ); assertThat(animationStarted).isFalse(); } @Test @Test public void startAnimation_animationFinishes_finishesTheTransition() { public void startAnimation_animationFinishes_finishesTheTransition() { TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo(); TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo(); Loading Loading @@ -215,6 +273,12 @@ public class UnfoldTransitionHandlerTest { triggerTaskInfo, /* remoteTransition= */ null, displayChange, 0 /* flags */); triggerTaskInfo, /* remoteTransition= */ null, displayChange, 0 /* flags */); } } private TransitionRequestInfo createNoneTransitionInfo() { return new TransitionRequestInfo(TRANSIT_NONE, /* triggerTask= */ null, /* remoteTransition= */ null, /* displayChange= */ null, /* flags= */ 0); } private static class TestShellUnfoldProgressProvider implements ShellUnfoldProgressProvider, private static class TestShellUnfoldProgressProvider implements ShellUnfoldProgressProvider, ShellUnfoldProgressProvider.UnfoldListener { ShellUnfoldProgressProvider.UnfoldListener { Loading Loading @@ -277,4 +341,35 @@ public class UnfoldTransitionHandlerTest { return false; return false; } } } } static class TestCase { private final boolean mShouldHandleMixedUnfold; public TestCase(boolean shouldHandleMixedUnfold) { mShouldHandleMixedUnfold = shouldHandleMixedUnfold; } public boolean mixedUnfoldFlagEnabled() { return mShouldHandleMixedUnfold; } @Override public String toString() { return "shouldHandleMixedUnfold flag = " + mShouldHandleMixedUnfold; } } private TransitionInfo createUnfoldTransitionInfo() { TransitionInfo transitionInfo = new TransitionInfo(TRANSIT_CHANGE, /* flags= */ 0); TransitionInfo.Change change = new TransitionInfo.Change(null, mock(SurfaceControl.class)); change.setStartAbsBounds(new Rect(0, 0, 10, 10)); change.setEndAbsBounds(new Rect(0, 0, 100, 100)); change.setFlags(TransitionInfo.FLAG_IS_DISPLAY); transitionInfo.addChange(change); return transitionInfo; } private TransitionInfo createNonUnfoldTransitionInfo() { return new TransitionInfo(TRANSIT_CHANGE, /* flags= */ 0); } } } No newline at end of file
services/core/java/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncher.java +22 −7 Original line number Original line Diff line number Diff line Loading @@ -34,6 +34,8 @@ import android.window.TransitionRequestInfo; import android.window.WindowContainerTransaction; import android.window.WindowContainerTransaction; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.ProtoLogGroup; import com.android.internal.protolog.common.ProtoLog; import com.android.server.wm.DeviceStateController.DeviceState; import com.android.server.wm.DeviceStateController.DeviceState; public class PhysicalDisplaySwitchTransitionLauncher { public class PhysicalDisplaySwitchTransitionLauncher { Loading Loading @@ -117,14 +119,27 @@ public class PhysicalDisplaySwitchTransitionLauncher { displayChange.setEndAbsBounds(endAbsBounds); displayChange.setEndAbsBounds(endAbsBounds); displayChange.setPhysicalDisplayChanged(true); displayChange.setPhysicalDisplayChanged(true); final Transition t = mTransitionController.requestTransitionIfNeeded(TRANSIT_CHANGE, mTransition = null; if (mTransitionController.isCollecting()) { // Add display container to the currently collecting transition mTransitionController.collect(mDisplayContent); mTransition = mTransitionController.getCollectingTransition(); // Make sure that transition is not ready until we finish the remote display change mTransition.setReady(mDisplayContent, false); ProtoLog.d(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Adding display switch to existing collecting transition"); } else { mTransition = mTransitionController.requestTransitionIfNeeded(TRANSIT_CHANGE, 0 /* flags */, 0 /* flags */, mDisplayContent, mDisplayContent, null /* remoteTransition */, mDisplayContent, mDisplayContent, null /* remoteTransition */, displayChange); displayChange); } if (t != null) { if (mTransition != null) { mDisplayContent.mAtmService.startPowerMode(POWER_MODE_REASON_CHANGE_DISPLAY); mAtmService.startPowerMode(POWER_MODE_REASON_CHANGE_DISPLAY); mTransition = t; } } mShouldRequestTransitionOnDisplaySwitch = false; mShouldRequestTransitionOnDisplaySwitch = false; Loading
services/tests/wmtests/src/com/android/server/wm/PhysicalDisplaySwitchTransitionLauncherTest.java +27 −2 Original line number Original line Diff line number Diff line Loading @@ -34,6 +34,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.Mockito.when; import android.animation.ValueAnimator; import android.animation.ValueAnimator; import android.annotation.Nullable; import android.content.Context; import android.content.Context; import android.content.res.Resources; import android.content.res.Resources; import android.graphics.Rect; import android.graphics.Rect; Loading Loading @@ -61,8 +62,7 @@ import org.mockito.MockitoAnnotations; */ */ @SmallTest @SmallTest @Presubmit @Presubmit @RunWith(WindowTestRunner.class) public class PhysicalDisplaySwitchTransitionLauncherTest { public class PhysicalDisplaySwitchTransitionLauncherTest extends WindowTestsBase { @Mock @Mock DisplayContent mDisplayContent; DisplayContent mDisplayContent; Loading @@ -73,6 +73,8 @@ public class PhysicalDisplaySwitchTransitionLauncherTest extends WindowTestsBase @Mock @Mock ActivityTaskManagerService mActivityTaskManagerService; ActivityTaskManagerService mActivityTaskManagerService; @Mock @Mock BLASTSyncEngine mSyncEngine; @Mock TransitionController mTransitionController; TransitionController mTransitionController; private PhysicalDisplaySwitchTransitionLauncher mTarget; private PhysicalDisplaySwitchTransitionLauncher mTarget; Loading Loading @@ -216,6 +218,20 @@ public class PhysicalDisplaySwitchTransitionLauncherTest extends WindowTestsBase assertTransitionNotRequested(); assertTransitionNotRequested(); } } @Test public void testDisplaySwitchAfterUnfolding_otherCollectingTransition_collectsDisplaySwitch() { givenCollectingTransition(createTransition(TRANSIT_CHANGE)); givenAllAnimationsEnabled(); mTarget.foldStateChanged(FOLDED); mTarget.foldStateChanged(OPEN); requestDisplaySwitch(); // Collects to the current transition verify(mTransitionController).collect(mDisplayContent); } @Test @Test public void testDisplaySwitch_whenNoContentInDisplayContent_noTransition() { public void testDisplaySwitch_whenNoContentInDisplayContent_noTransition() { givenAllAnimationsEnabled(); givenAllAnimationsEnabled(); Loading Loading @@ -267,6 +283,15 @@ public class PhysicalDisplaySwitchTransitionLauncherTest extends WindowTestsBase when(mTransitionController.isShellTransitionsEnabled()).thenReturn(enabled); when(mTransitionController.isShellTransitionsEnabled()).thenReturn(enabled); } } private void givenCollectingTransition(@Nullable Transition transition) { when(mTransitionController.isCollecting()).thenReturn(transition != null); when(mTransitionController.getCollectingTransition()).thenReturn(transition); } private Transition createTransition(int type) { return new Transition(type, /* flags= */ 0, mTransitionController, mSyncEngine); } private void givenDisplayContentHasContent(boolean hasContent) { private void givenDisplayContentHasContent(boolean hasContent) { when(mDisplayContent.getLastHasContent()).thenReturn(hasContent); when(mDisplayContent.getLastHasContent()).thenReturn(hasContent); } } Loading