Loading services/core/java/com/android/server/wm/AppTransition.java +40 −9 Original line number Diff line number Diff line Loading @@ -169,7 +169,8 @@ public class AppTransition implements Dump { private final WindowManagerService mService; private final DisplayContent mDisplayContent; private final TransitionAnimation mTransitionAnimation; @VisibleForTesting final TransitionAnimation mTransitionAnimation; private @TransitionFlags int mNextAppTransitionFlags = 0; private final ArrayList<Integer> mNextAppTransitionRequests = new ArrayList<>(); Loading Loading @@ -315,10 +316,33 @@ public class AppTransition implements Dump { setAppTransitionState(APP_STATE_TIMEOUT); } /** * Gets the animation overridden by app via {@link #overridePendingAppTransition}. */ @Nullable Animation getNextAppRequestedAnimation(boolean enter) { final Animation a = mTransitionAnimation.loadAppTransitionAnimation( mNextAppTransitionPackage, enter ? mNextAppTransitionEnter : mNextAppTransitionExit); if (mNextAppTransitionBackgroundColor != 0 && a != null) { a.setBackdropColor(mNextAppTransitionBackgroundColor); } return a; } /** * Gets the animation background color overridden by app via * {@link #overridePendingAppTransition}. */ @ColorInt int getNextAppTransitionBackgroundColor() { return mNextAppTransitionBackgroundColor; } @VisibleForTesting boolean isNextAppTransitionOverrideRequested() { return mNextAppTransitionOverrideRequested; } HardwareBuffer getAppTransitionThumbnailHeader(WindowContainer container) { AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get( container.hashCode()); Loading Loading @@ -411,9 +435,12 @@ public class AppTransition implements Dump { } void clear() { clear(true /* clearAppOverride */); } private void clear(boolean clearAppOverride) { mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE; mNextAppTransitionOverrideRequested = false; mNextAppTransitionPackage = null; mNextAppTransitionAnimationsSpecs.clear(); mRemoteAnimationController = null; mNextAppTransitionAnimationsSpecsFuture = null; Loading @@ -421,6 +448,12 @@ public class AppTransition implements Dump { mAnimationFinishedCallback = null; mOverrideTaskTransition = false; mNextAppTransitionIsSync = false; if (clearAppOverride) { mNextAppTransitionPackage = null; mNextAppTransitionEnter = 0; mNextAppTransitionExit = 0; mNextAppTransitionBackgroundColor = 0; } } void freeze() { Loading Loading @@ -528,7 +561,7 @@ public class AppTransition implements Dump { return TransitionAnimation.loadAnimationSafely(context, resId, TAG); } static int mapOpenCloseTransitTypes(int transit, boolean enter) { private static int mapOpenCloseTransitTypes(int transit, boolean enter) { int animAttr = 0; switch (transit) { case TRANSIT_OLD_ACTIVITY_OPEN: Loading Loading @@ -788,11 +821,7 @@ public class AppTransition implements Dump { "applyAnimation: anim=%s transit=%s Callers=%s", a, appTransitionOldToString(transit), Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) { a = mTransitionAnimation.loadAppTransitionAnimation(mNextAppTransitionPackage, enter ? mNextAppTransitionEnter : mNextAppTransitionExit); if (mNextAppTransitionBackgroundColor != 0) { a.setBackdropColor(mNextAppTransitionBackgroundColor); } a = getNextAppRequestedAnimation(enter); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM transit=%s " + "isEntrance=%b Callers=%s", Loading Loading @@ -1032,7 +1061,9 @@ public class AppTransition implements Dump { ProtoLog.i(WM_DEBUG_APP_TRANSITIONS, "Override pending remote transitionSet=%b adapter=%s", isTransitionSet(), remoteAnimationAdapter); if (isTransitionSet() && !mNextAppTransitionIsSync) { clear(); // ActivityEmbedding animation will run by the app process for which we want to respect // the app override for whether or not to show background color. clear(!isActivityEmbedding /* clearAppOverride */); mNextAppTransitionType = NEXT_TRANSIT_TYPE_REMOTE; mRemoteAnimationController = new RemoteAnimationController(mService, mDisplayContent, remoteAnimationAdapter, mHandler, isActivityEmbedding); Loading services/core/java/com/android/server/wm/WindowContainer.java +3 −4 Original line number Diff line number Diff line Loading @@ -2995,10 +2995,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< // screen empty. Show background color to cover that. showBackdrop = getDisplayContent().mChangingContainers.size() > 1; } else { // Check whether or not to show backdrop for open/close transition. final int animAttr = AppTransition.mapOpenCloseTransitTypes(transit, enter); final Animation a = animAttr != 0 ? appTransition.loadAnimationAttr(lp, animAttr, transit) : null; // Check whether the app has requested to show backdrop for open/close // transition. final Animation a = appTransition.getNextAppRequestedAnimation(enter); showBackdrop = a != null && a.getShowBackdrop(); } backdropColor = appTransition.getNextAppTransitionBackgroundColor(); Loading services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java +78 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeFalse; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.mock; Loading @@ -67,11 +68,14 @@ import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.WindowManager; import android.view.animation.Animation; import android.window.ITaskFragmentOrganizer; import android.window.TaskFragmentOrganizer; import androidx.test.filters.SmallTest; import com.android.internal.policy.TransitionAnimation; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; Loading Loading @@ -495,6 +499,80 @@ public class AppTransitionTests extends WindowTestsBase { assertEquals(startBounds, taskFragment.mSurfaceFreezer.mFreezeBounds); } @Test public void testGetNextAppTransitionBackgroundColor() { assumeFalse(WindowManagerService.sEnableShellTransitions); // No override by default. assertEquals(0, mDc.mAppTransition.getNextAppTransitionBackgroundColor()); // Override with a custom color. mDc.mAppTransition.prepareAppTransition(TRANSIT_OPEN, 0); final int testColor = 123; mDc.mAppTransition.overridePendingAppTransition("testPackage", 0 /* enterAnim */, 0 /* exitAnim */, testColor, null /* startedCallback */, null /* endedCallback */, false /* overrideTaskTransaction */); assertEquals(testColor, mDc.mAppTransition.getNextAppTransitionBackgroundColor()); assertTrue(mDc.mAppTransition.isNextAppTransitionOverrideRequested()); // Override with ActivityEmbedding remote animation. Background color should be kept. mDc.mAppTransition.overridePendingAppTransitionRemote(mock(RemoteAnimationAdapter.class), false /* sync */, true /* isActivityEmbedding */); assertEquals(testColor, mDc.mAppTransition.getNextAppTransitionBackgroundColor()); assertFalse(mDc.mAppTransition.isNextAppTransitionOverrideRequested()); // Background color should not be cleared anymore after #clear(). mDc.mAppTransition.clear(); assertEquals(0, mDc.mAppTransition.getNextAppTransitionBackgroundColor()); assertFalse(mDc.mAppTransition.isNextAppTransitionOverrideRequested()); } @Test public void testGetNextAppRequestedAnimation() { assumeFalse(WindowManagerService.sEnableShellTransitions); final String packageName = "testPackage"; final int enterAnimResId = 1; final int exitAnimResId = 2; final int testColor = 123; final Animation enterAnim = mock(Animation.class); final Animation exitAnim = mock(Animation.class); final TransitionAnimation transitionAnimation = mDc.mAppTransition.mTransitionAnimation; spyOn(transitionAnimation); doReturn(enterAnim).when(transitionAnimation) .loadAppTransitionAnimation(packageName, enterAnimResId); doReturn(exitAnim).when(transitionAnimation) .loadAppTransitionAnimation(packageName, exitAnimResId); // No override by default. assertNull(mDc.mAppTransition.getNextAppRequestedAnimation(true /* enter */)); assertNull(mDc.mAppTransition.getNextAppRequestedAnimation(false /* enter */)); // Override with a custom animation. mDc.mAppTransition.prepareAppTransition(TRANSIT_OPEN, 0); mDc.mAppTransition.overridePendingAppTransition(packageName, enterAnimResId, exitAnimResId, testColor, null /* startedCallback */, null /* endedCallback */, false /* overrideTaskTransaction */); assertEquals(enterAnim, mDc.mAppTransition.getNextAppRequestedAnimation(true /* enter */)); assertEquals(exitAnim, mDc.mAppTransition.getNextAppRequestedAnimation(false /* enter */)); assertTrue(mDc.mAppTransition.isNextAppTransitionOverrideRequested()); // Override with ActivityEmbedding remote animation. Custom animation should be kept. mDc.mAppTransition.overridePendingAppTransitionRemote(mock(RemoteAnimationAdapter.class), false /* sync */, true /* isActivityEmbedding */); assertEquals(enterAnim, mDc.mAppTransition.getNextAppRequestedAnimation(true /* enter */)); assertEquals(exitAnim, mDc.mAppTransition.getNextAppRequestedAnimation(false /* enter */)); assertFalse(mDc.mAppTransition.isNextAppTransitionOverrideRequested()); // Custom animation should not be cleared anymore after #clear(). mDc.mAppTransition.clear(); assertNull(mDc.mAppTransition.getNextAppRequestedAnimation(true /* enter */)); assertNull(mDc.mAppTransition.getNextAppRequestedAnimation(false /* enter */)); } private class TestRemoteAnimationRunner implements IRemoteAnimationRunner { boolean mCancelled = false; @Override Loading Loading
services/core/java/com/android/server/wm/AppTransition.java +40 −9 Original line number Diff line number Diff line Loading @@ -169,7 +169,8 @@ public class AppTransition implements Dump { private final WindowManagerService mService; private final DisplayContent mDisplayContent; private final TransitionAnimation mTransitionAnimation; @VisibleForTesting final TransitionAnimation mTransitionAnimation; private @TransitionFlags int mNextAppTransitionFlags = 0; private final ArrayList<Integer> mNextAppTransitionRequests = new ArrayList<>(); Loading Loading @@ -315,10 +316,33 @@ public class AppTransition implements Dump { setAppTransitionState(APP_STATE_TIMEOUT); } /** * Gets the animation overridden by app via {@link #overridePendingAppTransition}. */ @Nullable Animation getNextAppRequestedAnimation(boolean enter) { final Animation a = mTransitionAnimation.loadAppTransitionAnimation( mNextAppTransitionPackage, enter ? mNextAppTransitionEnter : mNextAppTransitionExit); if (mNextAppTransitionBackgroundColor != 0 && a != null) { a.setBackdropColor(mNextAppTransitionBackgroundColor); } return a; } /** * Gets the animation background color overridden by app via * {@link #overridePendingAppTransition}. */ @ColorInt int getNextAppTransitionBackgroundColor() { return mNextAppTransitionBackgroundColor; } @VisibleForTesting boolean isNextAppTransitionOverrideRequested() { return mNextAppTransitionOverrideRequested; } HardwareBuffer getAppTransitionThumbnailHeader(WindowContainer container) { AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get( container.hashCode()); Loading Loading @@ -411,9 +435,12 @@ public class AppTransition implements Dump { } void clear() { clear(true /* clearAppOverride */); } private void clear(boolean clearAppOverride) { mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE; mNextAppTransitionOverrideRequested = false; mNextAppTransitionPackage = null; mNextAppTransitionAnimationsSpecs.clear(); mRemoteAnimationController = null; mNextAppTransitionAnimationsSpecsFuture = null; Loading @@ -421,6 +448,12 @@ public class AppTransition implements Dump { mAnimationFinishedCallback = null; mOverrideTaskTransition = false; mNextAppTransitionIsSync = false; if (clearAppOverride) { mNextAppTransitionPackage = null; mNextAppTransitionEnter = 0; mNextAppTransitionExit = 0; mNextAppTransitionBackgroundColor = 0; } } void freeze() { Loading Loading @@ -528,7 +561,7 @@ public class AppTransition implements Dump { return TransitionAnimation.loadAnimationSafely(context, resId, TAG); } static int mapOpenCloseTransitTypes(int transit, boolean enter) { private static int mapOpenCloseTransitTypes(int transit, boolean enter) { int animAttr = 0; switch (transit) { case TRANSIT_OLD_ACTIVITY_OPEN: Loading Loading @@ -788,11 +821,7 @@ public class AppTransition implements Dump { "applyAnimation: anim=%s transit=%s Callers=%s", a, appTransitionOldToString(transit), Debug.getCallers(3)); } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) { a = mTransitionAnimation.loadAppTransitionAnimation(mNextAppTransitionPackage, enter ? mNextAppTransitionEnter : mNextAppTransitionExit); if (mNextAppTransitionBackgroundColor != 0) { a.setBackdropColor(mNextAppTransitionBackgroundColor); } a = getNextAppRequestedAnimation(enter); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM transit=%s " + "isEntrance=%b Callers=%s", Loading Loading @@ -1032,7 +1061,9 @@ public class AppTransition implements Dump { ProtoLog.i(WM_DEBUG_APP_TRANSITIONS, "Override pending remote transitionSet=%b adapter=%s", isTransitionSet(), remoteAnimationAdapter); if (isTransitionSet() && !mNextAppTransitionIsSync) { clear(); // ActivityEmbedding animation will run by the app process for which we want to respect // the app override for whether or not to show background color. clear(!isActivityEmbedding /* clearAppOverride */); mNextAppTransitionType = NEXT_TRANSIT_TYPE_REMOTE; mRemoteAnimationController = new RemoteAnimationController(mService, mDisplayContent, remoteAnimationAdapter, mHandler, isActivityEmbedding); Loading
services/core/java/com/android/server/wm/WindowContainer.java +3 −4 Original line number Diff line number Diff line Loading @@ -2995,10 +2995,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< // screen empty. Show background color to cover that. showBackdrop = getDisplayContent().mChangingContainers.size() > 1; } else { // Check whether or not to show backdrop for open/close transition. final int animAttr = AppTransition.mapOpenCloseTransitTypes(transit, enter); final Animation a = animAttr != 0 ? appTransition.loadAnimationAttr(lp, animAttr, transit) : null; // Check whether the app has requested to show backdrop for open/close // transition. final Animation a = appTransition.getNextAppRequestedAnimation(enter); showBackdrop = a != null && a.getShowBackdrop(); } backdropColor = appTransition.getNextAppTransitionBackgroundColor(); Loading
services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java +78 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeFalse; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.mock; Loading @@ -67,11 +68,14 @@ import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.WindowManager; import android.view.animation.Animation; import android.window.ITaskFragmentOrganizer; import android.window.TaskFragmentOrganizer; import androidx.test.filters.SmallTest; import com.android.internal.policy.TransitionAnimation; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; Loading Loading @@ -495,6 +499,80 @@ public class AppTransitionTests extends WindowTestsBase { assertEquals(startBounds, taskFragment.mSurfaceFreezer.mFreezeBounds); } @Test public void testGetNextAppTransitionBackgroundColor() { assumeFalse(WindowManagerService.sEnableShellTransitions); // No override by default. assertEquals(0, mDc.mAppTransition.getNextAppTransitionBackgroundColor()); // Override with a custom color. mDc.mAppTransition.prepareAppTransition(TRANSIT_OPEN, 0); final int testColor = 123; mDc.mAppTransition.overridePendingAppTransition("testPackage", 0 /* enterAnim */, 0 /* exitAnim */, testColor, null /* startedCallback */, null /* endedCallback */, false /* overrideTaskTransaction */); assertEquals(testColor, mDc.mAppTransition.getNextAppTransitionBackgroundColor()); assertTrue(mDc.mAppTransition.isNextAppTransitionOverrideRequested()); // Override with ActivityEmbedding remote animation. Background color should be kept. mDc.mAppTransition.overridePendingAppTransitionRemote(mock(RemoteAnimationAdapter.class), false /* sync */, true /* isActivityEmbedding */); assertEquals(testColor, mDc.mAppTransition.getNextAppTransitionBackgroundColor()); assertFalse(mDc.mAppTransition.isNextAppTransitionOverrideRequested()); // Background color should not be cleared anymore after #clear(). mDc.mAppTransition.clear(); assertEquals(0, mDc.mAppTransition.getNextAppTransitionBackgroundColor()); assertFalse(mDc.mAppTransition.isNextAppTransitionOverrideRequested()); } @Test public void testGetNextAppRequestedAnimation() { assumeFalse(WindowManagerService.sEnableShellTransitions); final String packageName = "testPackage"; final int enterAnimResId = 1; final int exitAnimResId = 2; final int testColor = 123; final Animation enterAnim = mock(Animation.class); final Animation exitAnim = mock(Animation.class); final TransitionAnimation transitionAnimation = mDc.mAppTransition.mTransitionAnimation; spyOn(transitionAnimation); doReturn(enterAnim).when(transitionAnimation) .loadAppTransitionAnimation(packageName, enterAnimResId); doReturn(exitAnim).when(transitionAnimation) .loadAppTransitionAnimation(packageName, exitAnimResId); // No override by default. assertNull(mDc.mAppTransition.getNextAppRequestedAnimation(true /* enter */)); assertNull(mDc.mAppTransition.getNextAppRequestedAnimation(false /* enter */)); // Override with a custom animation. mDc.mAppTransition.prepareAppTransition(TRANSIT_OPEN, 0); mDc.mAppTransition.overridePendingAppTransition(packageName, enterAnimResId, exitAnimResId, testColor, null /* startedCallback */, null /* endedCallback */, false /* overrideTaskTransaction */); assertEquals(enterAnim, mDc.mAppTransition.getNextAppRequestedAnimation(true /* enter */)); assertEquals(exitAnim, mDc.mAppTransition.getNextAppRequestedAnimation(false /* enter */)); assertTrue(mDc.mAppTransition.isNextAppTransitionOverrideRequested()); // Override with ActivityEmbedding remote animation. Custom animation should be kept. mDc.mAppTransition.overridePendingAppTransitionRemote(mock(RemoteAnimationAdapter.class), false /* sync */, true /* isActivityEmbedding */); assertEquals(enterAnim, mDc.mAppTransition.getNextAppRequestedAnimation(true /* enter */)); assertEquals(exitAnim, mDc.mAppTransition.getNextAppRequestedAnimation(false /* enter */)); assertFalse(mDc.mAppTransition.isNextAppTransitionOverrideRequested()); // Custom animation should not be cleared anymore after #clear(). mDc.mAppTransition.clear(); assertNull(mDc.mAppTransition.getNextAppRequestedAnimation(true /* enter */)); assertNull(mDc.mAppTransition.getNextAppRequestedAnimation(false /* enter */)); } private class TestRemoteAnimationRunner implements IRemoteAnimationRunner { boolean mCancelled = false; @Override Loading