Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +13 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECI import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE; import static android.view.WindowManager.TRANSIT_RELAUNCH; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_OWNER_THUMBNAIL; import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_WORK_THUMBNAIL; import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS; Loading @@ -63,6 +64,7 @@ import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITI import static com.android.wm.shell.transition.TransitionAnimationHelper.edgeExtendWindow; import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionBackgroundColorIfSet; import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionTypeFromInfo; import static com.android.wm.shell.transition.TransitionAnimationHelper.isCoveredByOpaqueFullscreenChange; import static com.android.wm.shell.transition.TransitionAnimationHelper.loadAttributeAnimation; import android.animation.Animator; Loading Loading @@ -353,6 +355,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { continue; } final boolean isTask = change.getTaskInfo() != null; final boolean isFreeform = isTask && change.getTaskInfo().isFreeform(); final int mode = change.getMode(); boolean isSeamlessDisplayChange = false; Loading Loading @@ -459,6 +462,16 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { final int layer = zSplitLine + numChanges - i; startTransaction.setLayer(change.getLeash(), layer); } } else if (!isCoveredByOpaqueFullscreenChange(info, change) && isFreeform && TransitionUtil.isOpeningMode(type) && change.getMode() == TRANSIT_TO_BACK) { // Reparent the minimize-change to the root task so the minimizing Task // isn't shown in front of other Tasks. mRootTDAOrganizer.reparentToDisplayArea( change.getTaskInfo().displayId, change.getLeash(), startTransaction); } else if (isOnlyTranslucent && TransitionUtil.isOpeningType(info.getType()) && TransitionUtil.isClosingType(mode)) { // If there is a closing translucent task in an OPENING transition, we will Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java +43 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITI import android.annotation.ColorInt; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.WindowConfiguration; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; Loading Loading @@ -72,6 +73,9 @@ public class TransitionAnimationHelper { final int changeFlags = change.getFlags(); final boolean enter = TransitionUtil.isOpeningType(changeMode); final boolean isTask = change.getTaskInfo() != null; final boolean isFreeform = isTask && change.getTaskInfo().isFreeform(); final boolean isCoveredByOpaqueFullscreenChange = isCoveredByOpaqueFullscreenChange(info, change); final TransitionInfo.AnimationOptions options; if (Flags.moveAnimationOptionsToChange()) { options = change.getAnimationOptions(); Loading Loading @@ -107,6 +111,24 @@ public class TransitionAnimationHelper { animAttr = enter ? R.styleable.WindowAnimation_wallpaperCloseEnterAnimation : R.styleable.WindowAnimation_wallpaperCloseExitAnimation; } else if (!isCoveredByOpaqueFullscreenChange && isFreeform && TransitionUtil.isOpeningMode(type) && change.getMode() == TRANSIT_TO_BACK) { // Set translucent here so TransitionAnimation loads the appropriate animations for // translucent activities and tasks later translucent = (changeFlags & FLAG_TRANSLUCENT) != 0; // The main Task is launching or being brought to front, this Task is being minimized animAttr = R.styleable.WindowAnimation_activityCloseExitAnimation; } else if (!isCoveredByOpaqueFullscreenChange && isFreeform && type == TRANSIT_TO_FRONT && change.getMode() == TRANSIT_TO_FRONT) { // Set translucent here so TransitionAnimation loads the appropriate animations for // translucent activities and tasks later translucent = (changeFlags & FLAG_TRANSLUCENT) != 0; // Bring the minimized Task back to front animAttr = R.styleable.WindowAnimation_activityOpenEnterAnimation; } else if (type == TRANSIT_OPEN) { // We will translucent open animation for translucent activities and tasks. Choose // WindowAnimation_activityOpenEnterAnimation and set translucent here, then Loading Loading @@ -417,4 +439,25 @@ public class TransitionAnimationHelper { return edgeExtensionLayer; } /** * Returns whether there is an opaque fullscreen Change positioned in front of the given Change * in the given TransitionInfo. */ static boolean isCoveredByOpaqueFullscreenChange( TransitionInfo info, TransitionInfo.Change change) { // TransitionInfo#getChanges() are ordered from front to back for (TransitionInfo.Change coveringChange : info.getChanges()) { if (coveringChange == change) { return false; } if ((coveringChange.getFlags() & FLAG_TRANSLUCENT) == 0 && coveringChange.getTaskInfo() != null && coveringChange.getTaskInfo().getWindowingMode() == WindowConfiguration.WINDOWING_MODE_FULLSCREEN) { return true; } } return false; } } libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/DefaultTransitionHandlerTest.java +73 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.wm.shell.transition; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_SLEEP; Loading Loading @@ -185,6 +186,73 @@ public class DefaultTransitionHandlerTest extends ShellTestCase { verify(startT, never()).setColor(any(), any()); } @Test public void startAnimation_freeformOpenChange_doesntReparentTask() { final TransitionInfo.Change openChange = new ChangeBuilder(TRANSIT_OPEN) .setTask(createTaskInfo( /* taskId= */ 1, /* windowingMode= */ WINDOWING_MODE_FULLSCREEN)) .build(); final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN) .addChange(openChange) .build(); final IBinder token = new Binder(); final SurfaceControl.Transaction startT = MockTransactionPool.create(); final SurfaceControl.Transaction finishT = MockTransactionPool.create(); mTransitionHandler.startAnimation(token, info, startT, finishT, mock(Transitions.TransitionFinishCallback.class)); verify(startT, never()).reparent(any(), any()); } @Test public void startAnimation_freeformMinimizeChange_underFullscreenChange_doesntReparentTask() { final TransitionInfo.Change openChange = new ChangeBuilder(TRANSIT_OPEN) .setTask(createTaskInfo( /* taskId= */ 1, /* windowingMode= */ WINDOWING_MODE_FULLSCREEN)) .build(); final TransitionInfo.Change toBackChange = new ChangeBuilder(TRANSIT_TO_BACK) .setTask(createTaskInfo( /* taskId= */ 2, /* windowingMode= */ WINDOWING_MODE_FREEFORM)) .build(); final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN) .addChange(openChange) .addChange(toBackChange) .build(); final IBinder token = new Binder(); final SurfaceControl.Transaction startT = MockTransactionPool.create(); final SurfaceControl.Transaction finishT = MockTransactionPool.create(); mTransitionHandler.startAnimation(token, info, startT, finishT, mock(Transitions.TransitionFinishCallback.class)); verify(startT, never()).reparent(any(), any()); } @Test public void startAnimation_freeform_minimizeAnimation_reparentsTask() { final TransitionInfo.Change openChange = new ChangeBuilder(TRANSIT_OPEN) .setTask(createTaskInfo( /* taskId= */ 1, /* windowingMode= */ WINDOWING_MODE_FREEFORM)) .build(); final TransitionInfo.Change toBackChange = new ChangeBuilder(TRANSIT_TO_BACK) .setTask(createTaskInfo( /* taskId= */ 2, /* windowingMode= */ WINDOWING_MODE_FREEFORM)) .build(); final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN) .addChange(openChange) .addChange(toBackChange) .build(); final IBinder token = new Binder(); final SurfaceControl.Transaction startT = MockTransactionPool.create(); final SurfaceControl.Transaction finishT = MockTransactionPool.create(); mTransitionHandler.startAnimation(token, info, startT, finishT, mock(Transitions.TransitionFinishCallback.class)); verify(startT).reparent(any(), any()); } private static void mergeSync(Transitions.TransitionHandler handler, IBinder token) { handler.mergeAnimation( new Binder(), Loading @@ -195,10 +263,14 @@ public class DefaultTransitionHandlerTest extends ShellTestCase { } private static RunningTaskInfo createTaskInfo(int taskId) { return createTaskInfo(taskId, WINDOWING_MODE_FULLSCREEN); } private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode) { RunningTaskInfo taskInfo = new RunningTaskInfo(); taskInfo.taskId = taskId; taskInfo.topActivityType = ACTIVITY_TYPE_STANDARD; taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN); taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode); taskInfo.configuration.windowConfiguration.setActivityType(taskInfo.topActivityType); taskInfo.token = mock(WindowContainerToken.class); return taskInfo; Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/TransitionAnimationHelperTest.kt 0 → 100644 +126 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.transition import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration import android.view.WindowManager import android.window.TransitionInfo import android.window.TransitionInfo.FLAG_TRANSLUCENT import com.android.internal.R import com.android.internal.policy.TransitionAnimation import com.android.wm.shell.ShellTestCase import com.android.wm.shell.TestRunningTaskInfoBuilder import org.junit.Test import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.eq import org.mockito.Mock import org.mockito.Mockito.verify class TransitionAnimationHelperTest : ShellTestCase() { @Mock lateinit var transitionAnimation: TransitionAnimation @Test fun loadAttributeAnimation_freeform_taskOpen_taskToBackChange_returnsMinimizeAnim() { val openChange = ChangeBuilder(WindowManager.TRANSIT_OPEN) .setTask(createTaskInfo(WindowConfiguration.WINDOWING_MODE_FREEFORM)) .build() val toBackChange = ChangeBuilder(WindowManager.TRANSIT_TO_BACK) .setTask(createTaskInfo(WindowConfiguration.WINDOWING_MODE_FREEFORM)) .build() val info = TransitionInfoBuilder(WindowManager.TRANSIT_OPEN) .addChange(openChange) .addChange(toBackChange) .build() loadAttributeAnimation(WindowManager.TRANSIT_OPEN, info, toBackChange) verify(transitionAnimation).loadDefaultAnimationAttr( eq(R.styleable.WindowAnimation_activityCloseExitAnimation), anyBoolean()) } @Test fun loadAttributeAnimation_freeform_taskToFront_taskToFrontChange_returnsUnminimizeAnim() { val toFrontChange = ChangeBuilder(WindowManager.TRANSIT_TO_FRONT) .setTask(createTaskInfo(WindowConfiguration.WINDOWING_MODE_FREEFORM)) .build() val info = TransitionInfoBuilder(WindowManager.TRANSIT_TO_FRONT) .addChange(toFrontChange) .build() loadAttributeAnimation(WindowManager.TRANSIT_TO_FRONT, info, toFrontChange) verify(transitionAnimation).loadDefaultAnimationAttr( eq(R.styleable.WindowAnimation_activityOpenEnterAnimation), /* translucent= */ anyBoolean()) } @Test fun loadAttributeAnimation_fullscreen_taskOpen_returnsTaskOpenEnterAnim() { val openChange = ChangeBuilder(WindowManager.TRANSIT_OPEN) .setTask(createTaskInfo(WindowConfiguration.WINDOWING_MODE_FULLSCREEN)) .build() val info = TransitionInfoBuilder(WindowManager.TRANSIT_OPEN).addChange(openChange).build() loadAttributeAnimation(WindowManager.TRANSIT_OPEN, info, openChange) verify(transitionAnimation).loadDefaultAnimationAttr( eq(R.styleable.WindowAnimation_taskOpenEnterAnimation), /* translucent= */ anyBoolean()) } @Test fun loadAttributeAnimation_freeform_taskOpen_taskToBackChange_passesTranslucent() { val openChange = ChangeBuilder(WindowManager.TRANSIT_OPEN) .setTask(createTaskInfo(WindowConfiguration.WINDOWING_MODE_FREEFORM)) .build() val toBackChange = ChangeBuilder(WindowManager.TRANSIT_TO_BACK) .setTask(createTaskInfo(WindowConfiguration.WINDOWING_MODE_FREEFORM)) .setFlags(FLAG_TRANSLUCENT) .build() val info = TransitionInfoBuilder(WindowManager.TRANSIT_OPEN) .addChange(openChange) .addChange(toBackChange) .build() loadAttributeAnimation(WindowManager.TRANSIT_OPEN, info, toBackChange) verify(transitionAnimation).loadDefaultAnimationAttr( eq(R.styleable.WindowAnimation_activityCloseExitAnimation), /* translucent= */ eq(true)) } private fun loadAttributeAnimation( @WindowManager.TransitionType type: Int, info: TransitionInfo, change: TransitionInfo.Change, wallpaperTransit: Int = TransitionAnimation.WALLPAPER_TRANSITION_NONE, isDreamTransition: Boolean = false, ) { TransitionAnimationHelper.loadAttributeAnimation( type, info, change, wallpaperTransit, transitionAnimation, isDreamTransition) } private fun createTaskInfo(windowingMode: Int): RunningTaskInfo { val taskInfo = TestRunningTaskInfoBuilder() .setWindowingMode(windowingMode) .build() return taskInfo } } No newline at end of file Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +13 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECI import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE; import static android.view.WindowManager.TRANSIT_RELAUNCH; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_OWNER_THUMBNAIL; import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_WORK_THUMBNAIL; import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS; Loading @@ -63,6 +64,7 @@ import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITI import static com.android.wm.shell.transition.TransitionAnimationHelper.edgeExtendWindow; import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionBackgroundColorIfSet; import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionTypeFromInfo; import static com.android.wm.shell.transition.TransitionAnimationHelper.isCoveredByOpaqueFullscreenChange; import static com.android.wm.shell.transition.TransitionAnimationHelper.loadAttributeAnimation; import android.animation.Animator; Loading Loading @@ -353,6 +355,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { continue; } final boolean isTask = change.getTaskInfo() != null; final boolean isFreeform = isTask && change.getTaskInfo().isFreeform(); final int mode = change.getMode(); boolean isSeamlessDisplayChange = false; Loading Loading @@ -459,6 +462,16 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { final int layer = zSplitLine + numChanges - i; startTransaction.setLayer(change.getLeash(), layer); } } else if (!isCoveredByOpaqueFullscreenChange(info, change) && isFreeform && TransitionUtil.isOpeningMode(type) && change.getMode() == TRANSIT_TO_BACK) { // Reparent the minimize-change to the root task so the minimizing Task // isn't shown in front of other Tasks. mRootTDAOrganizer.reparentToDisplayArea( change.getTaskInfo().displayId, change.getLeash(), startTransaction); } else if (isOnlyTranslucent && TransitionUtil.isOpeningType(info.getType()) && TransitionUtil.isClosingType(mode)) { // If there is a closing translucent task in an OPENING transition, we will Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java +43 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITI import android.annotation.ColorInt; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.WindowConfiguration; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; Loading Loading @@ -72,6 +73,9 @@ public class TransitionAnimationHelper { final int changeFlags = change.getFlags(); final boolean enter = TransitionUtil.isOpeningType(changeMode); final boolean isTask = change.getTaskInfo() != null; final boolean isFreeform = isTask && change.getTaskInfo().isFreeform(); final boolean isCoveredByOpaqueFullscreenChange = isCoveredByOpaqueFullscreenChange(info, change); final TransitionInfo.AnimationOptions options; if (Flags.moveAnimationOptionsToChange()) { options = change.getAnimationOptions(); Loading Loading @@ -107,6 +111,24 @@ public class TransitionAnimationHelper { animAttr = enter ? R.styleable.WindowAnimation_wallpaperCloseEnterAnimation : R.styleable.WindowAnimation_wallpaperCloseExitAnimation; } else if (!isCoveredByOpaqueFullscreenChange && isFreeform && TransitionUtil.isOpeningMode(type) && change.getMode() == TRANSIT_TO_BACK) { // Set translucent here so TransitionAnimation loads the appropriate animations for // translucent activities and tasks later translucent = (changeFlags & FLAG_TRANSLUCENT) != 0; // The main Task is launching or being brought to front, this Task is being minimized animAttr = R.styleable.WindowAnimation_activityCloseExitAnimation; } else if (!isCoveredByOpaqueFullscreenChange && isFreeform && type == TRANSIT_TO_FRONT && change.getMode() == TRANSIT_TO_FRONT) { // Set translucent here so TransitionAnimation loads the appropriate animations for // translucent activities and tasks later translucent = (changeFlags & FLAG_TRANSLUCENT) != 0; // Bring the minimized Task back to front animAttr = R.styleable.WindowAnimation_activityOpenEnterAnimation; } else if (type == TRANSIT_OPEN) { // We will translucent open animation for translucent activities and tasks. Choose // WindowAnimation_activityOpenEnterAnimation and set translucent here, then Loading Loading @@ -417,4 +439,25 @@ public class TransitionAnimationHelper { return edgeExtensionLayer; } /** * Returns whether there is an opaque fullscreen Change positioned in front of the given Change * in the given TransitionInfo. */ static boolean isCoveredByOpaqueFullscreenChange( TransitionInfo info, TransitionInfo.Change change) { // TransitionInfo#getChanges() are ordered from front to back for (TransitionInfo.Change coveringChange : info.getChanges()) { if (coveringChange == change) { return false; } if ((coveringChange.getFlags() & FLAG_TRANSLUCENT) == 0 && coveringChange.getTaskInfo() != null && coveringChange.getTaskInfo().getWindowingMode() == WindowConfiguration.WINDOWING_MODE_FULLSCREEN) { return true; } } return false; } }
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/DefaultTransitionHandlerTest.java +73 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.wm.shell.transition; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_SLEEP; Loading Loading @@ -185,6 +186,73 @@ public class DefaultTransitionHandlerTest extends ShellTestCase { verify(startT, never()).setColor(any(), any()); } @Test public void startAnimation_freeformOpenChange_doesntReparentTask() { final TransitionInfo.Change openChange = new ChangeBuilder(TRANSIT_OPEN) .setTask(createTaskInfo( /* taskId= */ 1, /* windowingMode= */ WINDOWING_MODE_FULLSCREEN)) .build(); final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN) .addChange(openChange) .build(); final IBinder token = new Binder(); final SurfaceControl.Transaction startT = MockTransactionPool.create(); final SurfaceControl.Transaction finishT = MockTransactionPool.create(); mTransitionHandler.startAnimation(token, info, startT, finishT, mock(Transitions.TransitionFinishCallback.class)); verify(startT, never()).reparent(any(), any()); } @Test public void startAnimation_freeformMinimizeChange_underFullscreenChange_doesntReparentTask() { final TransitionInfo.Change openChange = new ChangeBuilder(TRANSIT_OPEN) .setTask(createTaskInfo( /* taskId= */ 1, /* windowingMode= */ WINDOWING_MODE_FULLSCREEN)) .build(); final TransitionInfo.Change toBackChange = new ChangeBuilder(TRANSIT_TO_BACK) .setTask(createTaskInfo( /* taskId= */ 2, /* windowingMode= */ WINDOWING_MODE_FREEFORM)) .build(); final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN) .addChange(openChange) .addChange(toBackChange) .build(); final IBinder token = new Binder(); final SurfaceControl.Transaction startT = MockTransactionPool.create(); final SurfaceControl.Transaction finishT = MockTransactionPool.create(); mTransitionHandler.startAnimation(token, info, startT, finishT, mock(Transitions.TransitionFinishCallback.class)); verify(startT, never()).reparent(any(), any()); } @Test public void startAnimation_freeform_minimizeAnimation_reparentsTask() { final TransitionInfo.Change openChange = new ChangeBuilder(TRANSIT_OPEN) .setTask(createTaskInfo( /* taskId= */ 1, /* windowingMode= */ WINDOWING_MODE_FREEFORM)) .build(); final TransitionInfo.Change toBackChange = new ChangeBuilder(TRANSIT_TO_BACK) .setTask(createTaskInfo( /* taskId= */ 2, /* windowingMode= */ WINDOWING_MODE_FREEFORM)) .build(); final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN) .addChange(openChange) .addChange(toBackChange) .build(); final IBinder token = new Binder(); final SurfaceControl.Transaction startT = MockTransactionPool.create(); final SurfaceControl.Transaction finishT = MockTransactionPool.create(); mTransitionHandler.startAnimation(token, info, startT, finishT, mock(Transitions.TransitionFinishCallback.class)); verify(startT).reparent(any(), any()); } private static void mergeSync(Transitions.TransitionHandler handler, IBinder token) { handler.mergeAnimation( new Binder(), Loading @@ -195,10 +263,14 @@ public class DefaultTransitionHandlerTest extends ShellTestCase { } private static RunningTaskInfo createTaskInfo(int taskId) { return createTaskInfo(taskId, WINDOWING_MODE_FULLSCREEN); } private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode) { RunningTaskInfo taskInfo = new RunningTaskInfo(); taskInfo.taskId = taskId; taskInfo.topActivityType = ACTIVITY_TYPE_STANDARD; taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN); taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode); taskInfo.configuration.windowConfiguration.setActivityType(taskInfo.topActivityType); taskInfo.token = mock(WindowContainerToken.class); return taskInfo; Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/TransitionAnimationHelperTest.kt 0 → 100644 +126 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.transition import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration import android.view.WindowManager import android.window.TransitionInfo import android.window.TransitionInfo.FLAG_TRANSLUCENT import com.android.internal.R import com.android.internal.policy.TransitionAnimation import com.android.wm.shell.ShellTestCase import com.android.wm.shell.TestRunningTaskInfoBuilder import org.junit.Test import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.eq import org.mockito.Mock import org.mockito.Mockito.verify class TransitionAnimationHelperTest : ShellTestCase() { @Mock lateinit var transitionAnimation: TransitionAnimation @Test fun loadAttributeAnimation_freeform_taskOpen_taskToBackChange_returnsMinimizeAnim() { val openChange = ChangeBuilder(WindowManager.TRANSIT_OPEN) .setTask(createTaskInfo(WindowConfiguration.WINDOWING_MODE_FREEFORM)) .build() val toBackChange = ChangeBuilder(WindowManager.TRANSIT_TO_BACK) .setTask(createTaskInfo(WindowConfiguration.WINDOWING_MODE_FREEFORM)) .build() val info = TransitionInfoBuilder(WindowManager.TRANSIT_OPEN) .addChange(openChange) .addChange(toBackChange) .build() loadAttributeAnimation(WindowManager.TRANSIT_OPEN, info, toBackChange) verify(transitionAnimation).loadDefaultAnimationAttr( eq(R.styleable.WindowAnimation_activityCloseExitAnimation), anyBoolean()) } @Test fun loadAttributeAnimation_freeform_taskToFront_taskToFrontChange_returnsUnminimizeAnim() { val toFrontChange = ChangeBuilder(WindowManager.TRANSIT_TO_FRONT) .setTask(createTaskInfo(WindowConfiguration.WINDOWING_MODE_FREEFORM)) .build() val info = TransitionInfoBuilder(WindowManager.TRANSIT_TO_FRONT) .addChange(toFrontChange) .build() loadAttributeAnimation(WindowManager.TRANSIT_TO_FRONT, info, toFrontChange) verify(transitionAnimation).loadDefaultAnimationAttr( eq(R.styleable.WindowAnimation_activityOpenEnterAnimation), /* translucent= */ anyBoolean()) } @Test fun loadAttributeAnimation_fullscreen_taskOpen_returnsTaskOpenEnterAnim() { val openChange = ChangeBuilder(WindowManager.TRANSIT_OPEN) .setTask(createTaskInfo(WindowConfiguration.WINDOWING_MODE_FULLSCREEN)) .build() val info = TransitionInfoBuilder(WindowManager.TRANSIT_OPEN).addChange(openChange).build() loadAttributeAnimation(WindowManager.TRANSIT_OPEN, info, openChange) verify(transitionAnimation).loadDefaultAnimationAttr( eq(R.styleable.WindowAnimation_taskOpenEnterAnimation), /* translucent= */ anyBoolean()) } @Test fun loadAttributeAnimation_freeform_taskOpen_taskToBackChange_passesTranslucent() { val openChange = ChangeBuilder(WindowManager.TRANSIT_OPEN) .setTask(createTaskInfo(WindowConfiguration.WINDOWING_MODE_FREEFORM)) .build() val toBackChange = ChangeBuilder(WindowManager.TRANSIT_TO_BACK) .setTask(createTaskInfo(WindowConfiguration.WINDOWING_MODE_FREEFORM)) .setFlags(FLAG_TRANSLUCENT) .build() val info = TransitionInfoBuilder(WindowManager.TRANSIT_OPEN) .addChange(openChange) .addChange(toBackChange) .build() loadAttributeAnimation(WindowManager.TRANSIT_OPEN, info, toBackChange) verify(transitionAnimation).loadDefaultAnimationAttr( eq(R.styleable.WindowAnimation_activityCloseExitAnimation), /* translucent= */ eq(true)) } private fun loadAttributeAnimation( @WindowManager.TransitionType type: Int, info: TransitionInfo, change: TransitionInfo.Change, wallpaperTransit: Int = TransitionAnimation.WALLPAPER_TRANSITION_NONE, isDreamTransition: Boolean = false, ) { TransitionAnimationHelper.loadAttributeAnimation( type, info, change, wallpaperTransit, transitionAnimation, isDreamTransition) } private fun createTaskInfo(windowingMode: Int): RunningTaskInfo { val taskInfo = TestRunningTaskInfoBuilder() .setWindowingMode(windowingMode) .build() return taskInfo } } No newline at end of file