From f17300e70640a95d255f634bc73afa6c039e0569 Mon Sep 17 00:00:00 2001 From: shawnlin Date: Fri, 19 Feb 2021 15:25:39 +0800 Subject: [PATCH] Add nav bar case to RemoteAnimationTarget of non-app window 1. Only send navigation bar target when: - The transitition is app launch - In gesture navigation bar mode - The navigation bar is not controlled by fixed rotation or recents 2. Add a windowType field to RemoteAnimationTarget so that the remote clients could use this to find the non-app window they want. Bug: 139273001 Test: atest RemoteAnimationControllerTest Change-Id: I7003011351913b040b47e6fb567eedb4baf34a55 --- .../android/view/RemoteAnimationTarget.java | 23 +++ .../system/RemoteAnimationTargetCompat.java | 7 + .../com/android/server/wm/AppTransition.java | 2 +- .../wm/NonAppWindowAnimationAdapter.java | 65 +++++-- .../server/wm/RemoteAnimationController.java | 16 +- .../android/server/wm/WindowContainer.java | 5 + .../com/android/server/wm/WindowState.java | 5 + .../com/android/server/wm/WindowToken.java | 5 + .../wm/RemoteAnimationControllerTest.java | 164 +++++++++++++++++- 9 files changed, 270 insertions(+), 22 deletions(-) diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java index b1b670f5e0c99..ff84aa57a628e 100644 --- a/core/java/android/view/RemoteAnimationTarget.java +++ b/core/java/android/view/RemoteAnimationTarget.java @@ -31,6 +31,7 @@ import static android.view.RemoteAnimationTargetProto.START_BOUNDS; import static android.view.RemoteAnimationTargetProto.START_LEASH; import static android.view.RemoteAnimationTargetProto.TASK_ID; import static android.view.RemoteAnimationTargetProto.WINDOW_CONFIGURATION; +import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; import android.annotation.IntDef; import android.app.PictureInPictureParams; @@ -195,12 +196,30 @@ public class RemoteAnimationTarget implements Parcelable { */ public PictureInPictureParams pictureInPictureParams; + /** + * The {@link android.view.WindowManager.LayoutParams.WindowType} of this window. It's only used + * for non-app window. + */ + public final @WindowManager.LayoutParams.WindowType int windowType; + public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent, Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position, Rect localBounds, Rect screenSpaceBounds, WindowConfiguration windowConfig, boolean isNotInRecents, SurfaceControl startLeash, Rect startBounds, PictureInPictureParams pictureInPictureParams) { + this(taskId, mode, leash, isTranslucent, clipRect, contentInsets, prefixOrderIndex, + position, localBounds, screenSpaceBounds, windowConfig, isNotInRecents, startLeash, + startBounds, pictureInPictureParams, INVALID_WINDOW_TYPE); + } + + public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent, + Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position, + Rect localBounds, Rect screenSpaceBounds, + WindowConfiguration windowConfig, boolean isNotInRecents, + SurfaceControl startLeash, Rect startBounds, + PictureInPictureParams pictureInPictureParams, + @WindowManager.LayoutParams.WindowType int windowType) { this.mode = mode; this.taskId = taskId; this.leash = leash; @@ -217,6 +236,7 @@ public class RemoteAnimationTarget implements Parcelable { this.startLeash = startLeash; this.startBounds = startBounds == null ? null : new Rect(startBounds); this.pictureInPictureParams = pictureInPictureParams; + this.windowType = windowType; } public RemoteAnimationTarget(Parcel in) { @@ -236,6 +256,7 @@ public class RemoteAnimationTarget implements Parcelable { startLeash = in.readTypedObject(SurfaceControl.CREATOR); startBounds = in.readTypedObject(Rect.CREATOR); pictureInPictureParams = in.readTypedObject(PictureInPictureParams.CREATOR); + windowType = in.readInt(); } @Override @@ -261,6 +282,7 @@ public class RemoteAnimationTarget implements Parcelable { dest.writeTypedObject(startLeash, 0 /* flags */); dest.writeTypedObject(startBounds, 0 /* flags */); dest.writeTypedObject(pictureInPictureParams, 0 /* flags */); + dest.writeInt(windowType); } public void dump(PrintWriter pw, String prefix) { @@ -274,6 +296,7 @@ public class RemoteAnimationTarget implements Parcelable { pw.print(" sourceContainerBounds="); sourceContainerBounds.printShortString(pw); pw.print(" screenSpaceBounds="); screenSpaceBounds.printShortString(pw); pw.print(" localBounds="); localBounds.printShortString(pw); + pw.print(" windowType="); pw.print(windowType); pw.println(); pw.print(prefix); pw.print("windowConfiguration="); pw.println(windowConfiguration); pw.print(prefix); pw.print("leash="); pw.println(leash); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java index 87f6b8202ded0..568fdea19219c 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java @@ -16,6 +16,8 @@ package com.android.systemui.shared.system; +import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; + import android.app.PictureInPictureParams; import android.app.WindowConfiguration; import android.graphics.Point; @@ -44,6 +46,9 @@ public class RemoteAnimationTargetCompat { public static final int ACTIVITY_TYPE_ASSISTANT = WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; public final int activityType; + public static final int TYPE_NAVIGATION_BAR = WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; + public final int windowType; + public final int taskId; public final SurfaceControlCompat leash; public final boolean isTranslucent; @@ -74,6 +79,7 @@ public class RemoteAnimationTargetCompat { contentInsets = app.contentInsets; activityType = app.windowConfiguration.getActivityType(); pictureInPictureParams = app.pictureInPictureParams; + windowType = app.windowType; mStartLeash = app.startLeash; } @@ -114,6 +120,7 @@ public class RemoteAnimationTargetCompat { activityType = ACTIVITY_TYPE_UNDEFINED; } pictureInPictureParams = null; + windowType = INVALID_WINDOW_TYPE; mStartLeash = null; } diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 5b685b4a0499b..99289e0139b0b 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -1305,7 +1305,7 @@ public class AppTransition implements Dump { if (isTransitionSet()) { clear(); mNextAppTransitionType = NEXT_TRANSIT_TYPE_REMOTE; - mRemoteAnimationController = new RemoteAnimationController(mService, + mRemoteAnimationController = new RemoteAnimationController(mService, mDisplayContent, remoteAnimationAdapter, mHandler); } } diff --git a/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java b/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java index 5d6d51377c3f3..e6e866d8965db 100644 --- a/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java +++ b/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java @@ -16,6 +16,12 @@ package com.android.server.wm; +import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY; +import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER; +import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN; +import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_FRONT; +import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_CLOSE; + import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS; import static com.android.server.wm.AnimationAdapterProto.REMOTE; import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET; @@ -26,6 +32,7 @@ import android.os.SystemClock; import android.util.proto.ProtoOutputStream; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; +import android.view.WindowManager; import com.android.internal.protolog.common.ProtoLog; import com.android.server.policy.WindowManagerPolicy; @@ -35,7 +42,7 @@ import java.util.ArrayList; class NonAppWindowAnimationAdapter implements AnimationAdapter { - private final WindowState mWindow; + private final WindowContainer mWindow; private RemoteAnimationTarget mTarget; private SurfaceControl mCapturedLeash; @@ -47,22 +54,43 @@ class NonAppWindowAnimationAdapter implements AnimationAdapter { return false; } - NonAppWindowAnimationAdapter(WindowState w, - long durationHint, long statusBarTransitionDelay) { + NonAppWindowAnimationAdapter(WindowContainer w, long durationHint, + long statusBarTransitionDelay) { mWindow = w; mDurationHint = durationHint; mStatusBarTransitionDelay = statusBarTransitionDelay; } + static RemoteAnimationTarget[] startNonAppWindowAnimations(WindowManagerService service, + DisplayContent displayContent, @WindowManager.TransitionOldType int transit, + long durationHint, long statusBarTransitionDelay) { + final ArrayList targets = new ArrayList<>(); + if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY + || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER) { + startNonAppWindowAnimationsForKeyguardExit( + service, durationHint, statusBarTransitionDelay, targets); + } else if (transit == TRANSIT_OLD_TASK_OPEN || transit == TRANSIT_OLD_TASK_TO_FRONT + || transit == TRANSIT_OLD_WALLPAPER_CLOSE) { + final boolean shouldAttachNavBarToApp = + displayContent.getDisplayPolicy().shouldAttachNavBarToAppDuringTransition() + && service.getRecentsAnimationController() == null + && displayContent.getFixedRotationAnimationController() == null; + if (shouldAttachNavBarToApp) { + startNavigationBarWindowAnimation( + displayContent, durationHint, statusBarTransitionDelay, targets); + } + } + return targets.toArray(new RemoteAnimationTarget[targets.size()]); + } + /** * Creates and starts remote animations for all the visible non app windows. * * @return RemoteAnimationTarget[] targets for all the visible non app windows */ - public static RemoteAnimationTarget[] startNonAppWindowAnimationsForKeyguardExit( - WindowManagerService service, long durationHint, long statusBarTransitionDelay) { - final ArrayList targets = new ArrayList<>(); - + private static void startNonAppWindowAnimationsForKeyguardExit(WindowManagerService service, + long durationHint, long statusBarTransitionDelay, + ArrayList targets) { final WindowManagerPolicy policy = service.mPolicy; service.mRoot.forAllWindows(nonAppWindow -> { if (nonAppWindow.mActivityRecord == null && policy.canBeHiddenByKeyguardLw(nonAppWindow) @@ -74,7 +102,22 @@ class NonAppWindowAnimationAdapter implements AnimationAdapter { targets.add(nonAppAdapter.createRemoteAnimationTarget()); } }, true /* traverseTopToBottom */); - return targets.toArray(new RemoteAnimationTarget[targets.size()]); + } + + /** + * Creates and starts remote animation for the navigation bar windows. + * + * @return RemoteAnimationTarget[] targets for all the visible non app windows + */ + private static void startNavigationBarWindowAnimation(DisplayContent displayContent, + long durationHint, long statusBarTransitionDelay, + ArrayList targets) { + final WindowState navWindow = displayContent.getDisplayPolicy().getNavigationBar(); + final NonAppWindowAnimationAdapter nonAppAdapter = new NonAppWindowAnimationAdapter( + navWindow.mToken, durationHint, statusBarTransitionDelay); + navWindow.mToken.startAnimation(navWindow.mToken.getPendingTransaction(), + nonAppAdapter, false /* hidden */, ANIMATION_TYPE_WINDOW_ANIMATION); + targets.add(nonAppAdapter.createRemoteAnimationTarget()); } /** @@ -84,7 +127,7 @@ class NonAppWindowAnimationAdapter implements AnimationAdapter { mTarget = new RemoteAnimationTarget(-1, -1, getLeash(), false, new Rect(), null, mWindow.getPrefixOrderIndex(), mWindow.getLastSurfacePosition(), mWindow.getBounds(), null, mWindow.getWindowConfiguration(), true, null, null, - null); + null, mWindow.getWindowType()); return mTarget; } @@ -120,8 +163,8 @@ class NonAppWindowAnimationAdapter implements AnimationAdapter { @Override public void dump(PrintWriter pw, String prefix) { pw.print(prefix); - pw.print("token="); - pw.println(mWindow.mToken); + pw.print("window="); + pw.println(mWindow); if (mTarget != null) { pw.print(prefix); pw.println("Target:"); diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java index 42cb96f65738c..31663b707004f 100644 --- a/services/core/java/com/android/server/wm/RemoteAnimationController.java +++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java @@ -16,9 +16,6 @@ package com.android.server.wm; -import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY; -import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER; - import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS; import static com.android.server.wm.AnimationAdapterProto.REMOTE; import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET; @@ -60,6 +57,7 @@ class RemoteAnimationController implements DeathRecipient { private static final long TIMEOUT_MS = 2000; private final WindowManagerService mService; + private final DisplayContent mDisplayContent; private final RemoteAnimationAdapter mRemoteAnimationAdapter; private final ArrayList mPendingAnimations = new ArrayList<>(); private final ArrayList mPendingWallpaperAnimations = @@ -72,9 +70,10 @@ class RemoteAnimationController implements DeathRecipient { private boolean mCanceled; private boolean mLinkedToDeathOfRunner; - RemoteAnimationController(WindowManagerService service, + RemoteAnimationController(WindowManagerService service, DisplayContent displayContent, RemoteAnimationAdapter remoteAnimationAdapter, Handler handler) { mService = service; + mDisplayContent = displayContent; mRemoteAnimationAdapter = remoteAnimationAdapter; mHandler = handler; } @@ -221,12 +220,11 @@ class RemoteAnimationController implements DeathRecipient { private RemoteAnimationTarget[] createNonAppWindowAnimations( @WindowManager.TransitionOldType int transit) { ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createNonAppWindowAnimations()"); - return (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY - || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER) - ? NonAppWindowAnimationAdapter.startNonAppWindowAnimationsForKeyguardExit(mService, + return NonAppWindowAnimationAdapter.startNonAppWindowAnimations(mService, + mDisplayContent, + transit, mRemoteAnimationAdapter.getDuration(), - mRemoteAnimationAdapter.getStatusBarTransitionDelay()) - : new RemoteAnimationTarget[0]; + mRemoteAnimationAdapter.getStatusBarTransitionDelay()); } private void onAnimationFinished() { diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 000889a16d4cd..1a031aafaa601 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -29,6 +29,7 @@ import static android.content.res.Configuration.ORIENTATION_UNDEFINED; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.os.UserHandle.USER_NULL; import static android.view.SurfaceControl.Transaction; +import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM; @@ -3299,4 +3300,8 @@ class WindowContainer extends ConfigurationContainer< mListeners.remove(listener); unregisterConfigurationChangeListener(listener); } + + @WindowManager.LayoutParams.WindowType int getWindowType() { + return INVALID_WINDOW_TYPE; + } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index fec715ec7f796..311f97a5fc43d 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -5818,4 +5818,9 @@ class WindowState extends WindowContainer implements WindowManagerP outSize.inset(-attrs.surfaceInsets.left, -attrs.surfaceInsets.top, -attrs.surfaceInsets.right, -attrs.surfaceInsets.bottom); } + + @Override + @WindowManager.LayoutParams.WindowType int getWindowType() { + return mAttrs.type; + } } diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 066cc1e105ab0..a1068b5b00b26 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -745,4 +745,9 @@ class WindowToken extends WindowContainer { forAllWindows(WindowState::clearFrozenInsetsState, true /* traverseTopToBottom */); } } + + @Override + @WindowManager.LayoutParams.WindowType int getWindowType() { + return windowType; + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java index 2fdd63ed93d52..ea971809c8f8b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java @@ -18,11 +18,13 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; +import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN; import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY; import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER; import static android.view.WindowManager.TRANSIT_OLD_NONE; import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE; +import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN; import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; @@ -35,7 +37,9 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITIO import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -94,7 +98,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { mAdapter = new RemoteAnimationAdapter(mMockRunner, 100, 50, true /* changeNeedsSnapshot */); mAdapter.setCallingPidUid(123, 456); runWithScissors(mWm.mH, () -> mHandler = new TestHandler(null, mClock), 0); - mController = new RemoteAnimationController(mWm, mAdapter, mHandler); + mController = new RemoteAnimationController(mWm, mDisplayContent, mAdapter, mHandler); } private WindowState createAppOverlayWindow() { @@ -520,6 +524,164 @@ public class RemoteAnimationControllerTest extends WindowTestsBase { } } + @Test + public void testNonAppTarget_sendNavBar() throws Exception { + final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin"); + mDisplayContent.mOpeningApps.add(win.mActivityRecord); + final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "NavigationBar"); + mDisplayContent.getDisplayPolicy().addWindowLw(navBar, navBar.mAttrs); + final DisplayPolicy policy = mDisplayContent.getDisplayPolicy(); + spyOn(policy); + doReturn(true).when(policy).shouldAttachNavBarToAppDuringTransition(); + + final AnimationAdapter adapter = mController.createRemoteAnimationRecord( + win.mActivityRecord, new Point(50, 100), null, + new Rect(50, 100, 150, 150), null).mAdapter; + adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION, + mFinishedCallback); + mController.goodToGo(TRANSIT_OLD_TASK_OPEN); + mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + final ArgumentCaptor appsCaptor = + ArgumentCaptor.forClass(RemoteAnimationTarget[].class); + final ArgumentCaptor wallpapersCaptor = + ArgumentCaptor.forClass(RemoteAnimationTarget[].class); + final ArgumentCaptor nonAppsCaptor = + ArgumentCaptor.forClass(RemoteAnimationTarget[].class); + final ArgumentCaptor finishedCaptor = + ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class); + verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_OPEN), + appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(), + finishedCaptor.capture()); + boolean containNavTarget = false; + for (int i = 0; i < nonAppsCaptor.getValue().length; i++) { + if (nonAppsCaptor.getValue()[0].windowType == TYPE_NAVIGATION_BAR) { + containNavTarget = true; + break; + } + } + assertTrue(containNavTarget); + } + + @Test + public void testNonAppTarget_notSendNavBar_notAttachToApp() throws Exception { + final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin"); + mDisplayContent.mOpeningApps.add(win.mActivityRecord); + final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "NavigationBar"); + mDisplayContent.getDisplayPolicy().addWindowLw(navBar, navBar.mAttrs); + final DisplayPolicy policy = mDisplayContent.getDisplayPolicy(); + spyOn(policy); + doReturn(false).when(policy).shouldAttachNavBarToAppDuringTransition(); + + final AnimationAdapter adapter = mController.createRemoteAnimationRecord( + win.mActivityRecord, new Point(50, 100), null, + new Rect(50, 100, 150, 150), null).mAdapter; + adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION, + mFinishedCallback); + mController.goodToGo(TRANSIT_OLD_TASK_OPEN); + mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + final ArgumentCaptor appsCaptor = + ArgumentCaptor.forClass(RemoteAnimationTarget[].class); + final ArgumentCaptor wallpapersCaptor = + ArgumentCaptor.forClass(RemoteAnimationTarget[].class); + final ArgumentCaptor nonAppsCaptor = + ArgumentCaptor.forClass(RemoteAnimationTarget[].class); + final ArgumentCaptor finishedCaptor = + ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class); + verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_OPEN), + appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(), + finishedCaptor.capture()); + boolean containNavTarget = false; + for (int i = 0; i < nonAppsCaptor.getValue().length; i++) { + if (nonAppsCaptor.getValue()[0].windowType == TYPE_NAVIGATION_BAR) { + containNavTarget = true; + break; + } + } + assertFalse(containNavTarget); + } + + @Test + public void testNonAppTarget_notSendNavBar_controlledByFixedRotation() throws Exception { + final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin"); + mDisplayContent.mOpeningApps.add(win.mActivityRecord); + final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "NavigationBar"); + mDisplayContent.getDisplayPolicy().addWindowLw(navBar, navBar.mAttrs); + final FixedRotationAnimationController mockController = + mock(FixedRotationAnimationController.class); + doReturn(mockController).when(mDisplayContent).getFixedRotationAnimationController(); + final DisplayPolicy policy = mDisplayContent.getDisplayPolicy(); + spyOn(policy); + doReturn(true).when(policy).shouldAttachNavBarToAppDuringTransition(); + + final AnimationAdapter adapter = mController.createRemoteAnimationRecord( + win.mActivityRecord, new Point(50, 100), null, + new Rect(50, 100, 150, 150), null).mAdapter; + adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION, + mFinishedCallback); + mController.goodToGo(TRANSIT_OLD_TASK_OPEN); + mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + final ArgumentCaptor appsCaptor = + ArgumentCaptor.forClass(RemoteAnimationTarget[].class); + final ArgumentCaptor wallpapersCaptor = + ArgumentCaptor.forClass(RemoteAnimationTarget[].class); + final ArgumentCaptor nonAppsCaptor = + ArgumentCaptor.forClass(RemoteAnimationTarget[].class); + final ArgumentCaptor finishedCaptor = + ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class); + verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_OPEN), + appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(), + finishedCaptor.capture()); + boolean containNavTarget = false; + for (int i = 0; i < nonAppsCaptor.getValue().length; i++) { + if (nonAppsCaptor.getValue()[0].windowType == TYPE_NAVIGATION_BAR) { + containNavTarget = true; + break; + } + } + assertFalse(containNavTarget); + } + + @Test + public void testNonAppTarget_notSendNavBar_controlledByRecents() throws Exception { + final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin"); + mDisplayContent.mOpeningApps.add(win.mActivityRecord); + final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "NavigationBar"); + mDisplayContent.getDisplayPolicy().addWindowLw(navBar, navBar.mAttrs); + final RecentsAnimationController mockController = + mock(RecentsAnimationController.class); + doReturn(mockController).when(mWm).getRecentsAnimationController(); + final DisplayPolicy policy = mDisplayContent.getDisplayPolicy(); + spyOn(policy); + doReturn(true).when(policy).shouldAttachNavBarToAppDuringTransition(); + + final AnimationAdapter adapter = mController.createRemoteAnimationRecord( + win.mActivityRecord, new Point(50, 100), null, + new Rect(50, 100, 150, 150), null).mAdapter; + adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION, + mFinishedCallback); + mController.goodToGo(TRANSIT_OLD_TASK_OPEN); + mWm.mAnimator.executeAfterPrepareSurfacesRunnables(); + final ArgumentCaptor appsCaptor = + ArgumentCaptor.forClass(RemoteAnimationTarget[].class); + final ArgumentCaptor wallpapersCaptor = + ArgumentCaptor.forClass(RemoteAnimationTarget[].class); + final ArgumentCaptor nonAppsCaptor = + ArgumentCaptor.forClass(RemoteAnimationTarget[].class); + final ArgumentCaptor finishedCaptor = + ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class); + verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_OPEN), + appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(), + finishedCaptor.capture()); + boolean containNavTarget = false; + for (int i = 0; i < nonAppsCaptor.getValue().length; i++) { + if (nonAppsCaptor.getValue()[0].windowType == TYPE_NAVIGATION_BAR) { + containNavTarget = true; + break; + } + } + assertFalse(containNavTarget); + } + private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) { verify(binder, atLeast(0)).asBinder(); verifyNoMoreInteractions(binder);