diff options
2 files changed, 169 insertions, 0 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java index a5f071af6973..09ba4d3b75e8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java @@ -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; @@ -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(); @@ -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 @@ -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. + */ + private 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; + } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/TransitionAnimationHelperTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/TransitionAnimationHelperTest.kt new file mode 100644 index 000000000000..bad14bbdb141 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/TransitionAnimationHelperTest.kt @@ -0,0 +1,126 @@ +/* + * 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 |