Loading libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/TransitionUtil.java +17 −1 Original line number Diff line number Diff line Loading @@ -105,6 +105,21 @@ public class TransitionUtil { return false; } /** * Returns {@code true} if the transition has a display change that is not just an order-change. */ public static boolean hasNonOrderOnlyDisplayChange(@NonNull TransitionInfo info) { for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); if (change.getMode() == TRANSIT_CHANGE && change.hasFlags(FLAG_IS_DISPLAY) && !isOrderOnly(change)) { return true; } } return false; } /** Returns `true` if `change` is a wallpaper. */ public static boolean isWallpaper(TransitionInfo.Change change) { return (change.getTaskInfo() == null) Loading Loading @@ -135,7 +150,8 @@ public class TransitionUtil { && (change.getFlags() & FLAG_MOVED_TO_TOP) != 0 && change.getStartAbsBounds().equals(change.getEndAbsBounds()) && (change.getLastParent() == null || change.getLastParent().equals(change.getParent())); || change.getLastParent().equals(change.getParent())) && (change.getStartRotation() == change.getEndRotation()); } /** Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java +8 −1 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.window.WindowContainerTransaction; import androidx.annotation.BinderThread; import com.android.internal.protolog.ProtoLog; import com.android.window.flags.Flags; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.TransitionUtil; Loading Loading @@ -117,7 +118,13 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { if (!Transitions.SHELL_TRANSITIONS_ROTATION && TransitionUtil.hasDisplayChange(info)) { // Ignore the remote transition if the display changes size or rotation, since Launcher // doesn't have the necessary permission to deal with such changes. final boolean ignoreTransition = !Transitions.SHELL_TRANSITIONS_ROTATION && (Flags.enableCrossDisplaysAppLaunchTransition() ? TransitionUtil.hasNonOrderOnlyDisplayChange(info) : TransitionUtil.hasDisplayChange(info)); if (ignoreTransition) { // Note that if the remote doesn't have permission ACCESS_SURFACE_FLINGER, some // operations of the start transaction may be ignored. mRequestedRemotes.remove(transition); Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/RemoteTransitionHandlerTest.kt +55 −1 Original line number Diff line number Diff line Loading @@ -16,14 +16,17 @@ package com.android.wm.shell.transition import android.platform.test.annotations.EnableFlags import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.Surface import android.view.WindowManager import android.window.RemoteTransition import android.window.TransitionFilter import android.window.TransitionInfo import android.window.TransitionRequestInfo import android.window.WindowContainerTransaction import com.android.window.flags.Flags import com.android.wm.shell.ShellTestCase import com.android.wm.shell.TestSyncExecutor import org.junit.Assert.assertFalse Loading Loading @@ -100,6 +103,57 @@ class RemoteTransitionHandlerTest : ShellTestCase() { assertTrue(isHandled) } @Test @EnableFlags(Flags.FLAG_ENABLE_CROSS_DISPLAYS_APP_LAUNCH_TRANSITION) fun startAnimation_remoteTransition_displayRotationChange_returnsFalse() { val request = TransitionRequestInfo(WindowManager.TRANSIT_CHANGE, null, testRemoteTransition) handler.addFiltered(TransitionFilter(), testRemoteTransition) handler.handleRequest(mock(), request) val transitionInfo = TransitionInfo(WindowManager.TRANSIT_CHANGE, /* flags= */ 0).apply { addChange(createDisplayChange().apply { setRotation(Surface.ROTATION_0, Surface.ROTATION_90) }) } val isHandled = handler.startAnimation( /* transition= */ testRemoteTransition.remoteTransition.asBinder(), /* info= */ transitionInfo, /* startTransaction= */ mock(), /* finishTransaction= */ mock(), /* finishCallback= */ {}, ) assertFalse(isHandled) } @Test @EnableFlags(Flags.FLAG_ENABLE_CROSS_DISPLAYS_APP_LAUNCH_TRANSITION) fun startAnimation_remoteTransition_orderOnlyDisplayChange_returnsTrue() { val request = TransitionRequestInfo(WindowManager.TRANSIT_OPEN, null, testRemoteTransition) handler.addFiltered(TransitionFilter(), testRemoteTransition) handler.handleRequest(mock(), request) val transitionInfo = TransitionInfo(WindowManager.TRANSIT_CHANGE, /* flags= */ 0).apply { addChange(createDisplayChange()) } val isHandled = handler.startAnimation( /* transition= */ testRemoteTransition.remoteTransition.asBinder(), /* info= */ transitionInfo, /* startTransaction= */ mock(), /* finishTransaction= */ mock(), /* finishCallback= */ {}, ) assertTrue(isHandled) } private fun createDisplayChange(): TransitionInfo.Change = TransitionInfo.Change(/* container= */ mock(), /* leash= */ mock()).apply { mode = WindowManager.TRANSIT_CHANGE flags = TransitionInfo.FLAG_IS_DISPLAY or TransitionInfo.FLAG_MOVED_TO_TOP } private fun createTransitionInfo( type: Int = WindowManager.TRANSIT_OPEN, changeMode: Int = WindowManager.TRANSIT_CLOSE, Loading Loading
libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/TransitionUtil.java +17 −1 Original line number Diff line number Diff line Loading @@ -105,6 +105,21 @@ public class TransitionUtil { return false; } /** * Returns {@code true} if the transition has a display change that is not just an order-change. */ public static boolean hasNonOrderOnlyDisplayChange(@NonNull TransitionInfo info) { for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); if (change.getMode() == TRANSIT_CHANGE && change.hasFlags(FLAG_IS_DISPLAY) && !isOrderOnly(change)) { return true; } } return false; } /** Returns `true` if `change` is a wallpaper. */ public static boolean isWallpaper(TransitionInfo.Change change) { return (change.getTaskInfo() == null) Loading Loading @@ -135,7 +150,8 @@ public class TransitionUtil { && (change.getFlags() & FLAG_MOVED_TO_TOP) != 0 && change.getStartAbsBounds().equals(change.getEndAbsBounds()) && (change.getLastParent() == null || change.getLastParent().equals(change.getParent())); || change.getLastParent().equals(change.getParent())) && (change.getStartRotation() == change.getEndRotation()); } /** Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java +8 −1 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.window.WindowContainerTransaction; import androidx.annotation.BinderThread; import com.android.internal.protolog.ProtoLog; import com.android.window.flags.Flags; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.TransitionUtil; Loading Loading @@ -117,7 +118,13 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler { @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { if (!Transitions.SHELL_TRANSITIONS_ROTATION && TransitionUtil.hasDisplayChange(info)) { // Ignore the remote transition if the display changes size or rotation, since Launcher // doesn't have the necessary permission to deal with such changes. final boolean ignoreTransition = !Transitions.SHELL_TRANSITIONS_ROTATION && (Flags.enableCrossDisplaysAppLaunchTransition() ? TransitionUtil.hasNonOrderOnlyDisplayChange(info) : TransitionUtil.hasDisplayChange(info)); if (ignoreTransition) { // Note that if the remote doesn't have permission ACCESS_SURFACE_FLINGER, some // operations of the start transaction may be ignored. mRequestedRemotes.remove(transition); Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/RemoteTransitionHandlerTest.kt +55 −1 Original line number Diff line number Diff line Loading @@ -16,14 +16,17 @@ package com.android.wm.shell.transition import android.platform.test.annotations.EnableFlags import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.Surface import android.view.WindowManager import android.window.RemoteTransition import android.window.TransitionFilter import android.window.TransitionInfo import android.window.TransitionRequestInfo import android.window.WindowContainerTransaction import com.android.window.flags.Flags import com.android.wm.shell.ShellTestCase import com.android.wm.shell.TestSyncExecutor import org.junit.Assert.assertFalse Loading Loading @@ -100,6 +103,57 @@ class RemoteTransitionHandlerTest : ShellTestCase() { assertTrue(isHandled) } @Test @EnableFlags(Flags.FLAG_ENABLE_CROSS_DISPLAYS_APP_LAUNCH_TRANSITION) fun startAnimation_remoteTransition_displayRotationChange_returnsFalse() { val request = TransitionRequestInfo(WindowManager.TRANSIT_CHANGE, null, testRemoteTransition) handler.addFiltered(TransitionFilter(), testRemoteTransition) handler.handleRequest(mock(), request) val transitionInfo = TransitionInfo(WindowManager.TRANSIT_CHANGE, /* flags= */ 0).apply { addChange(createDisplayChange().apply { setRotation(Surface.ROTATION_0, Surface.ROTATION_90) }) } val isHandled = handler.startAnimation( /* transition= */ testRemoteTransition.remoteTransition.asBinder(), /* info= */ transitionInfo, /* startTransaction= */ mock(), /* finishTransaction= */ mock(), /* finishCallback= */ {}, ) assertFalse(isHandled) } @Test @EnableFlags(Flags.FLAG_ENABLE_CROSS_DISPLAYS_APP_LAUNCH_TRANSITION) fun startAnimation_remoteTransition_orderOnlyDisplayChange_returnsTrue() { val request = TransitionRequestInfo(WindowManager.TRANSIT_OPEN, null, testRemoteTransition) handler.addFiltered(TransitionFilter(), testRemoteTransition) handler.handleRequest(mock(), request) val transitionInfo = TransitionInfo(WindowManager.TRANSIT_CHANGE, /* flags= */ 0).apply { addChange(createDisplayChange()) } val isHandled = handler.startAnimation( /* transition= */ testRemoteTransition.remoteTransition.asBinder(), /* info= */ transitionInfo, /* startTransaction= */ mock(), /* finishTransaction= */ mock(), /* finishCallback= */ {}, ) assertTrue(isHandled) } private fun createDisplayChange(): TransitionInfo.Change = TransitionInfo.Change(/* container= */ mock(), /* leash= */ mock()).apply { mode = WindowManager.TRANSIT_CHANGE flags = TransitionInfo.FLAG_IS_DISPLAY or TransitionInfo.FLAG_MOVED_TO_TOP } private fun createTransitionInfo( type: Int = WindowManager.TRANSIT_OPEN, changeMode: Int = WindowManager.TRANSIT_CLOSE, Loading