Attach nav bar to app during transition for non-remote animation case
- Play fade-out/in animation in AppTransition.goodToGo() if it's not a
remote animation.
- Create a new class NavFadeAnimationAdapter:
- Able to play fade-out and fade-in sequentially.
- Able to reparent the animation leash to the specified parent when
the animation starts.
- This CL also refines a case when users launch an app and then swipe up
immediately to enter recent app by canceling animation of the nav
token in RecentsAnimationController.attachNavigationBarToApp().
In this case, the swipe-up gesture should have higher priority to
control the nav bar.
Bug: 185303414
Test: - atest RecentsAnimationControllerTest
- Launch clock widget from launcher and observe the transition
- Launch an app and then swipe up immediately to enter recent app
Change-Id: Ic8ad3dfe4fe3efcf88cf3cfcf362d18e3c47f632
This commit is contained in:
@@ -449,6 +449,19 @@ public class AppTransition implements Dump {
|
||||
|
||||
if (mRemoteAnimationController != null) {
|
||||
mRemoteAnimationController.goodToGo(transit);
|
||||
} else if ((isTaskOpenTransitOld(transit) || transit == TRANSIT_OLD_WALLPAPER_CLOSE)
|
||||
&& topOpeningAnim != null) {
|
||||
if (mDisplayContent.getDisplayPolicy().shouldAttachNavBarToAppDuringTransition()
|
||||
&& mService.getRecentsAnimationController() == null) {
|
||||
final NavBarFadeAnimationController controller =
|
||||
new NavBarFadeAnimationController(mDisplayContent);
|
||||
// For remote animation case, the nav bar fades out and in is controlled by the
|
||||
// remote side. For non-remote animation case, we play the fade out/in animation
|
||||
// here. We play the nav bar fade-out animation when the app transition animation
|
||||
// starts and play the fade-in animation sequentially once the fade-out is finished.
|
||||
controller.fadeOutAndInSequentially(topOpeningAnim.getDurationHint(),
|
||||
null /* fadeOutParent */, topOpeningApp.getSurfaceControl());
|
||||
}
|
||||
}
|
||||
return redoLayout;
|
||||
}
|
||||
|
||||
@@ -373,7 +373,6 @@ public class DisplayPolicy {
|
||||
* when the navigation bar mode is changed.
|
||||
*/
|
||||
private boolean mShouldAttachNavBarToAppDuringTransition;
|
||||
private NavBarFadeAnimationController mNavBarFadeAnimationController;
|
||||
|
||||
// -------- PolicyHandler --------
|
||||
private static final int MSG_REQUEST_TRANSIENT_BARS = 2;
|
||||
@@ -1088,7 +1087,6 @@ public class DisplayPolicy {
|
||||
break;
|
||||
case TYPE_NAVIGATION_BAR:
|
||||
mNavigationBar = win;
|
||||
updateNavBarFadeController();
|
||||
mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, win,
|
||||
(displayFrames, windowState, inOutFrame) -> {
|
||||
|
||||
@@ -1234,7 +1232,6 @@ public class DisplayPolicy {
|
||||
mDisplayContent.setInsetProvider(ITYPE_STATUS_BAR, null, null);
|
||||
} else if (mNavigationBar == win || mNavigationBarAlt == win) {
|
||||
mNavigationBar = null;
|
||||
updateNavBarFadeController();
|
||||
mNavigationBarAlt = null;
|
||||
mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, null, null);
|
||||
} else if (mNotificationShade == win) {
|
||||
@@ -2060,7 +2057,6 @@ public class DisplayPolicy {
|
||||
res.getBoolean(R.bool.config_attachNavBarToAppDuringTransition);
|
||||
if (mShouldAttachNavBarToAppDuringTransition != shouldAttach) {
|
||||
mShouldAttachNavBarToAppDuringTransition = shouldAttach;
|
||||
updateNavBarFadeController();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3062,19 +3058,4 @@ public class DisplayPolicy {
|
||||
boolean shouldAttachNavBarToAppDuringTransition() {
|
||||
return mShouldAttachNavBarToAppDuringTransition && mNavigationBar != null;
|
||||
}
|
||||
|
||||
@Nullable NavBarFadeAnimationController getNavBarFadeAnimationController() {
|
||||
return mNavBarFadeAnimationController;
|
||||
}
|
||||
|
||||
private void updateNavBarFadeController() {
|
||||
if (shouldAttachNavBarToAppDuringTransition()) {
|
||||
if (mNavBarFadeAnimationController == null) {
|
||||
mNavBarFadeAnimationController =
|
||||
new NavBarFadeAnimationController(mDisplayContent);
|
||||
}
|
||||
} else {
|
||||
mNavBarFadeAnimationController = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ import java.io.PrintWriter;
|
||||
*/
|
||||
public class FadeAnimationController {
|
||||
protected final Context mContext;
|
||||
private final ArrayMap<WindowToken, Runnable> mDeferredFinishCallbacks = new ArrayMap<>();
|
||||
protected final ArrayMap<WindowToken, Runnable> mDeferredFinishCallbacks = new ArrayMap<>();
|
||||
|
||||
public FadeAnimationController(DisplayContent displayContent) {
|
||||
mContext = displayContent.mWmService.mContext;
|
||||
@@ -69,17 +69,11 @@ public class FadeAnimationController {
|
||||
return;
|
||||
}
|
||||
|
||||
final Animation animation = show ? getFadeInAnimation() : getFadeOutAnimation();
|
||||
if (animation == null) {
|
||||
final FadeAnimationAdapter animationAdapter = createAdapter(show, windowToken);
|
||||
if (animationAdapter == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final LocalAnimationAdapter.AnimationSpec windowAnimationSpec =
|
||||
createAnimationSpec(animation);
|
||||
|
||||
final FadeAnimationAdapter animationAdapter = new FadeAnimationAdapter(
|
||||
windowAnimationSpec, windowToken.getSurfaceAnimationRunner(), show, windowToken);
|
||||
|
||||
// We deferred the end of the animation when hiding the token, so we need to end it now that
|
||||
// it's shown again.
|
||||
final SurfaceAnimator.OnAnimationFinishedCallback finishedCallback = show ? (t, r) -> {
|
||||
@@ -92,7 +86,21 @@ public class FadeAnimationController {
|
||||
show /* hidden */, animationType, finishedCallback);
|
||||
}
|
||||
|
||||
private LocalAnimationAdapter.AnimationSpec createAnimationSpec(@NonNull Animation animation) {
|
||||
protected FadeAnimationAdapter createAdapter(boolean show, WindowToken windowToken) {
|
||||
final Animation animation = show ? getFadeInAnimation() : getFadeOutAnimation();
|
||||
if (animation == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final LocalAnimationAdapter.AnimationSpec windowAnimationSpec =
|
||||
createAnimationSpec(animation);
|
||||
|
||||
return new FadeAnimationAdapter(
|
||||
windowAnimationSpec, windowToken.getSurfaceAnimationRunner(), show, windowToken);
|
||||
}
|
||||
|
||||
protected LocalAnimationAdapter.AnimationSpec createAnimationSpec(
|
||||
@NonNull Animation animation) {
|
||||
return new LocalAnimationAdapter.AnimationSpec() {
|
||||
|
||||
final Transformation mTransformation = new Transformation();
|
||||
@@ -130,8 +138,8 @@ public class FadeAnimationController {
|
||||
};
|
||||
}
|
||||
|
||||
private class FadeAnimationAdapter extends LocalAnimationAdapter {
|
||||
private final boolean mShow;
|
||||
protected class FadeAnimationAdapter extends LocalAnimationAdapter {
|
||||
protected final boolean mShow;
|
||||
private final WindowToken mToken;
|
||||
|
||||
FadeAnimationAdapter(AnimationSpec windowAnimationSpec,
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server.wm;
|
||||
|
||||
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
|
||||
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.animation.AlphaAnimation;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.Interpolator;
|
||||
@@ -35,12 +36,17 @@ public class NavBarFadeAnimationController extends FadeAnimationController{
|
||||
private static final Interpolator FADE_OUT_INTERPOLATOR =
|
||||
new PathInterpolator(0.2f, 0f, 1f, 1f);
|
||||
|
||||
private DisplayContent mDisplayContent;
|
||||
private final WindowState mNavigationBar;
|
||||
private Animation mFadeInAnimation;
|
||||
private Animation mFadeOutAnimation;
|
||||
private SurfaceControl mFadeInParent;
|
||||
private SurfaceControl mFadeOutParent;
|
||||
private boolean mPlaySequentially = false;
|
||||
|
||||
public NavBarFadeAnimationController(DisplayContent displayContent) {
|
||||
super(displayContent);
|
||||
mDisplayContent = displayContent;
|
||||
mNavigationBar = displayContent.getDisplayPolicy().getNavigationBar();
|
||||
mFadeInAnimation = new AlphaAnimation(0f, 1f);
|
||||
mFadeInAnimation.setDuration(FADE_IN_DURATION);
|
||||
@@ -61,12 +67,103 @@ public class NavBarFadeAnimationController extends FadeAnimationController{
|
||||
return mFadeOutAnimation;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FadeAnimationAdapter createAdapter(boolean show, WindowToken windowToken) {
|
||||
final Animation animation = show ? getFadeInAnimation() : getFadeOutAnimation();
|
||||
if (animation == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final LocalAnimationAdapter.AnimationSpec windowAnimationSpec =
|
||||
createAnimationSpec(animation);
|
||||
return new NavFadeAnimationAdapter(
|
||||
windowAnimationSpec, windowToken.getSurfaceAnimationRunner(), show, windowToken,
|
||||
show ? mFadeInParent : mFadeOutParent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the fade-in/out animation for the navigation bar.
|
||||
*
|
||||
* @param show true for fade-in, otherwise for fade-out.
|
||||
*/
|
||||
public void fadeWindowToken(boolean show) {
|
||||
fadeWindowToken(show, mNavigationBar.mToken, ANIMATION_TYPE_APP_TRANSITION);
|
||||
final FadeRotationAnimationController controller =
|
||||
mDisplayContent.getFadeRotationAnimationController();
|
||||
final Runnable fadeAnim = () -> fadeWindowToken(show, mNavigationBar.mToken,
|
||||
ANIMATION_TYPE_APP_TRANSITION);
|
||||
if (controller == null) {
|
||||
fadeAnim.run();
|
||||
} else if (!controller.isTargetToken(mNavigationBar.mToken)) {
|
||||
// If fade rotation animation is running and the nav bar is not controlled by it:
|
||||
// - For fade-in animation, defer the animation until fade rotation animation finishes.
|
||||
// - For fade-out animation, just play the animation.
|
||||
if (show) {
|
||||
controller.setOnShowRunnable(fadeAnim);
|
||||
} else {
|
||||
fadeAnim.run();
|
||||
}
|
||||
} else {
|
||||
// If fade rotation animation is running and controlling the nav bar, make sure we empty
|
||||
// the mDeferredFinishCallbacks and defer the runnable until fade rotation animation
|
||||
// finishes.
|
||||
final Runnable runnable = mDeferredFinishCallbacks.remove(mNavigationBar.mToken);
|
||||
if (runnable != null) {
|
||||
controller.setOnShowRunnable(runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fadeOutAndInSequentially(long totalDuration, SurfaceControl fadeOutParent,
|
||||
SurfaceControl fadeInParent) {
|
||||
mPlaySequentially = true;
|
||||
if (totalDuration > 0) {
|
||||
// The animation duration of each animation varies so we set the fade-out duration to
|
||||
// 1/3 of the total app transition duration and set the fade-in duration to 2/3 of it.
|
||||
final long fadeInDuration = totalDuration * 2L / 3L;
|
||||
mFadeOutAnimation.setDuration(totalDuration - fadeInDuration);
|
||||
mFadeInAnimation.setDuration(fadeInDuration);
|
||||
}
|
||||
mFadeOutParent = fadeOutParent;
|
||||
mFadeInParent = fadeInParent;
|
||||
fadeWindowToken(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The animation adapter that is capable of playing fade-out and fade-in sequentially and
|
||||
* reparenting the navigation bar to a specified SurfaceControl when fade animation starts.
|
||||
*/
|
||||
protected class NavFadeAnimationAdapter extends FadeAnimationAdapter {
|
||||
private SurfaceControl mParent;
|
||||
|
||||
NavFadeAnimationAdapter(AnimationSpec windowAnimationSpec,
|
||||
SurfaceAnimationRunner surfaceAnimationRunner, boolean show,
|
||||
WindowToken token, SurfaceControl parent) {
|
||||
super(windowAnimationSpec, surfaceAnimationRunner, show, token);
|
||||
mParent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t,
|
||||
int type, SurfaceAnimator.OnAnimationFinishedCallback finishCallback) {
|
||||
super.startAnimation(animationLeash, t, type, finishCallback);
|
||||
if (mParent != null && mParent.isValid()) {
|
||||
t.reparent(animationLeash, mParent);
|
||||
// Place the nav bar on top of anything else (e.g. ime and starting window) in the
|
||||
// parent.
|
||||
t.setLayer(animationLeash, Integer.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
|
||||
if (mPlaySequentially) {
|
||||
if (!mShow) {
|
||||
fadeWindowToken(true);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return super.shouldDeferAnimationFinish(endDeferFinishCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -633,6 +633,7 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
return;
|
||||
}
|
||||
mNavigationBarAttachedToApp = true;
|
||||
navWindow.mToken.cancelAnimation();
|
||||
final SurfaceControl.Transaction t = navWindow.mToken.getPendingTransaction();
|
||||
final SurfaceControl navSurfaceControl = navWindow.mToken.getSurfaceControl();
|
||||
if (shouldTranslateNavBar) {
|
||||
@@ -653,7 +654,8 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
}
|
||||
}
|
||||
|
||||
private void restoreNavigationBarFromApp(boolean animate) {
|
||||
@VisibleForTesting
|
||||
void restoreNavigationBarFromApp(boolean animate) {
|
||||
if (!mNavigationBarAttachedToApp) {
|
||||
return;
|
||||
}
|
||||
@@ -676,23 +678,9 @@ public class RecentsAnimationController implements DeathRecipient {
|
||||
t.setLayer(navToken.getSurfaceControl(), navToken.getLastLayer());
|
||||
|
||||
if (animate) {
|
||||
final NavBarFadeAnimationController navBarFadeAnimationController =
|
||||
mDisplayContent.getDisplayPolicy().getNavBarFadeAnimationController();
|
||||
final Runnable fadeInAnim = () -> {
|
||||
// Reparent the SurfaceControl of nav bar token back.
|
||||
t.reparent(navToken.getSurfaceControl(), parent.getSurfaceControl());
|
||||
// Run fade-in animation to show navigation bar back to bottom of the display.
|
||||
if (navBarFadeAnimationController != null) {
|
||||
navBarFadeAnimationController.fadeWindowToken(true);
|
||||
}
|
||||
};
|
||||
final FadeRotationAnimationController fadeRotationAnimationController =
|
||||
mDisplayContent.getFadeRotationAnimationController();
|
||||
if (fadeRotationAnimationController != null) {
|
||||
fadeRotationAnimationController.setOnShowRunnable(fadeInAnim);
|
||||
} else {
|
||||
fadeInAnim.run();
|
||||
}
|
||||
final NavBarFadeAnimationController controller =
|
||||
new NavBarFadeAnimationController(mDisplayContent);
|
||||
controller.fadeWindowToken(true);
|
||||
} else {
|
||||
// Reparent the SurfaceControl of nav bar token back.
|
||||
t.reparent(navToken.getSurfaceControl(), parent.getSurfaceControl());
|
||||
|
||||
@@ -516,20 +516,15 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
|
||||
final SurfaceControl.Transaction transaction = navToken.getPendingTransaction();
|
||||
|
||||
verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
|
||||
mDefaultDisplay.mDisplayId, false);
|
||||
eq(mDefaultDisplay.mDisplayId), eq(false));
|
||||
verify(transaction).reparent(navToken.getSurfaceControl(), activity.getSurfaceControl());
|
||||
verify(transaction).setLayer(navToken.getSurfaceControl(), Integer.MAX_VALUE);
|
||||
|
||||
final WindowContainer parent = navToken.getParent();
|
||||
final NavBarFadeAnimationController navBarFadeAnimationController =
|
||||
mDefaultDisplay.getDisplayPolicy().getNavBarFadeAnimationController();
|
||||
|
||||
mController.cleanupAnimation(REORDER_MOVE_TO_TOP);
|
||||
verify(mController).restoreNavigationBarFromApp(eq(true));
|
||||
verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
|
||||
mDefaultDisplay.mDisplayId, true);
|
||||
eq(mDefaultDisplay.mDisplayId), eq(true));
|
||||
verify(transaction).setLayer(navToken.getSurfaceControl(), 0);
|
||||
verify(transaction).reparent(navToken.getSurfaceControl(), parent.getSurfaceControl());
|
||||
verify(navBarFadeAnimationController).fadeWindowToken(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -543,20 +538,18 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
|
||||
final SurfaceControl.Transaction transaction = navToken.getPendingTransaction();
|
||||
|
||||
verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
|
||||
mDefaultDisplay.mDisplayId, false);
|
||||
eq(mDefaultDisplay.mDisplayId), eq(false));
|
||||
verify(transaction).reparent(navToken.getSurfaceControl(), activity.getSurfaceControl());
|
||||
verify(transaction).setLayer(navToken.getSurfaceControl(), Integer.MAX_VALUE);
|
||||
|
||||
final WindowContainer parent = navToken.getParent();
|
||||
final NavBarFadeAnimationController navBarFadeAnimationController =
|
||||
mDefaultDisplay.getDisplayPolicy().getNavBarFadeAnimationController();
|
||||
|
||||
mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
|
||||
verify(mController).restoreNavigationBarFromApp(eq(false));
|
||||
verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
|
||||
mDefaultDisplay.mDisplayId, true);
|
||||
eq(mDefaultDisplay.mDisplayId), eq(true));
|
||||
verify(transaction).setLayer(navToken.getSurfaceControl(), 0);
|
||||
verify(transaction).reparent(navToken.getSurfaceControl(), parent.getSurfaceControl());
|
||||
verify(navBarFadeAnimationController, never()).fadeWindowToken(anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -570,39 +563,6 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
|
||||
assertFalse(mController.isNavigationBarAttachedToApp());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFadeRotationAfterAttachAndBeforeRestore_notRestoreNavImmediately() {
|
||||
setupForShouldAttachNavBarDuringTransition();
|
||||
final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
|
||||
final ActivityRecord homeActivity = createHomeActivity();
|
||||
initializeRecentsAnimationController(mController, homeActivity);
|
||||
|
||||
final WindowToken navToken = mDefaultDisplay.getDisplayPolicy().getNavigationBar().mToken;
|
||||
final SurfaceControl.Transaction transaction = navToken.getPendingTransaction();
|
||||
|
||||
verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
|
||||
mDefaultDisplay.mDisplayId, false);
|
||||
verify(transaction).reparent(navToken.getSurfaceControl(), activity.getSurfaceControl());
|
||||
verify(transaction).setLayer(navToken.getSurfaceControl(), Integer.MAX_VALUE);
|
||||
|
||||
final WindowContainer parent = navToken.getParent();
|
||||
final NavBarFadeAnimationController navBarFadeAnimationController =
|
||||
mDefaultDisplay.getDisplayPolicy().getNavBarFadeAnimationController();
|
||||
|
||||
FadeRotationAnimationController mockController =
|
||||
mock(FadeRotationAnimationController.class);
|
||||
doReturn(mockController).when(mDefaultDisplay).getFadeRotationAnimationController();
|
||||
|
||||
mController.cleanupAnimation(REORDER_MOVE_TO_TOP);
|
||||
verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
|
||||
mDefaultDisplay.mDisplayId, true);
|
||||
verify(transaction).setLayer(navToken.getSurfaceControl(), 0);
|
||||
verify(mockController).setOnShowRunnable(any());
|
||||
verify(transaction, times(0)).reparent(navToken.getSurfaceControl(),
|
||||
parent.getSurfaceControl());
|
||||
verify(navBarFadeAnimationController, times(0)).fadeWindowToken(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttachNavBarInSplitScreenMode() {
|
||||
setupForShouldAttachNavBarDuringTransition();
|
||||
@@ -619,20 +579,18 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
|
||||
final SurfaceControl.Transaction transaction = navToken.getPendingTransaction();
|
||||
|
||||
verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
|
||||
mDefaultDisplay.mDisplayId, false);
|
||||
eq(mDefaultDisplay.mDisplayId), eq(false));
|
||||
verify(navWindow).setSurfaceTranslationY(-secondary.getBounds().top);
|
||||
verify(transaction).reparent(navToken.getSurfaceControl(), secondary.getSurfaceControl());
|
||||
reset(navWindow);
|
||||
|
||||
mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
|
||||
final WindowContainer parent = navToken.getParent();
|
||||
final NavBarFadeAnimationController navBarFadeAnimationController =
|
||||
mDefaultDisplay.getDisplayPolicy().getNavBarFadeAnimationController();
|
||||
verify(mController.mStatusBar).setNavigationBarLumaSamplingEnabled(
|
||||
mDefaultDisplay.mDisplayId, true);
|
||||
eq(mDefaultDisplay.mDisplayId), eq(true));
|
||||
verify(navWindow).setSurfaceTranslationY(0);
|
||||
verify(transaction).reparent(navToken.getSurfaceControl(), parent.getSurfaceControl());
|
||||
verify(navBarFadeAnimationController, never()).fadeWindowToken(anyBoolean());
|
||||
verify(mController).restoreNavigationBarFromApp(eq(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -696,12 +654,8 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
|
||||
mDefaultDisplay.getDisplayPolicy().addWindowLw(navBar, navBar.mAttrs);
|
||||
mWm.setRecentsAnimationController(mController);
|
||||
doReturn(navBar).when(mController).getNavigationBarWindow();
|
||||
final NavBarFadeAnimationController mockNavBarFadeAnimationController =
|
||||
mock(NavBarFadeAnimationController.class);
|
||||
final DisplayPolicy displayPolicy = spy(mDefaultDisplay.getDisplayPolicy());
|
||||
doReturn(displayPolicy).when(mDefaultDisplay).getDisplayPolicy();
|
||||
doReturn(mockNavBarFadeAnimationController).when(displayPolicy)
|
||||
.getNavBarFadeAnimationController();
|
||||
}
|
||||
|
||||
private static void initializeRecentsAnimationController(RecentsAnimationController controller,
|
||||
|
||||
Reference in New Issue
Block a user