/*
 * Copyright (C) 2018 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.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;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;

import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.fail;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;

import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;

import androidx.test.filters.SmallTest;

import com.android.server.testutils.OffsettableClock;
import com.android.server.testutils.TestHandler;
import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

/**
 * Build/Install/Run:
 *  atest WmTests:RemoteAnimationControllerTest
 */
@SmallTest
@Presubmit
@RunWith(WindowTestRunner.class)
public class RemoteAnimationControllerTest extends WindowTestsBase {

    @Mock SurfaceControl mMockLeash;
    @Mock SurfaceControl mMockThumbnailLeash;
    @Mock Transaction mMockTransaction;
    @Mock OnAnimationFinishedCallback mFinishedCallback;
    @Mock OnAnimationFinishedCallback mThumbnailFinishedCallback;
    @Mock IRemoteAnimationRunner mMockRunner;
    private RemoteAnimationAdapter mAdapter;
    private RemoteAnimationController mController;
    private final OffsettableClock mClock = new OffsettableClock.Stopped();
    private TestHandler mHandler;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        when(mMockRunner.asBinder()).thenReturn(new Binder());
        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, mDisplayContent, mAdapter, mHandler);
    }

    private WindowState createAppOverlayWindow() {
        final WindowState win = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY,
                "testOverlayWindow");
        win.mActivityRecord = null;
        win.mHasSurface = true;
        return win;
    }

    @Test
    public void testRun() throws Exception {
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        mDisplayContent.mOpeningApps.add(win.mActivityRecord);
        final WindowState overlayWin = createAppOverlayWindow();
        try {
            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_ACTIVITY_OPEN);
            mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
            final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
                    ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
            verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_ACTIVITY_OPEN),
                    appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
                    finishedCaptor.capture());
            assertEquals(1, appsCaptor.getValue().length);
            final RemoteAnimationTarget app = appsCaptor.getValue()[0];
            assertEquals(new Point(50, 100), app.position);
            assertEquals(new Rect(50, 100, 150, 150), app.sourceContainerBounds);
            assertEquals(win.mActivityRecord.getPrefixOrderIndex(), app.prefixOrderIndex);
            assertEquals(win.mActivityRecord.getTask().mTaskId, app.taskId);
            assertEquals(mMockLeash, app.leash);
            assertEquals(false, app.isTranslucent);
            verify(mMockTransaction).setPosition(mMockLeash, app.position.x, app.position.y);
            verify(mMockTransaction).setWindowCrop(mMockLeash, 100, 50);

            finishedCaptor.getValue().onAnimationFinished();
            verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
                    eq(adapter));
            assertEquals(0, nonAppsCaptor.getValue().length);
        } finally {
            mDisplayContent.mOpeningApps.clear();
        }
    }

    @Test
    public void testCancel() throws Exception {
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        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_ACTIVITY_OPEN);

        adapter.onAnimationCancelled(mMockLeash);
        verify(mMockRunner).onAnimationCancelled(anyBoolean());
    }

    @Test
    public void testTimeout() throws Exception {
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        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_ACTIVITY_OPEN);

        mClock.fastForward(10500);
        mHandler.timeAdvance();

        verify(mMockRunner).onAnimationCancelled(anyBoolean());
        verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
                eq(adapter));
    }

    @Test
    public void testTimeout_scaled() throws Exception {
        try {
            mWm.setAnimationScale(2, 5.0f);
            final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
                    "testWin");
            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_ACTIVITY_OPEN);

            mClock.fastForward(10500);
            mHandler.timeAdvance();

            verify(mMockRunner, never()).onAnimationCancelled(anyBoolean());

            mClock.fastForward(52500);
            mHandler.timeAdvance();

            verify(mMockRunner).onAnimationCancelled(anyBoolean());
            verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
                    eq(adapter));
        } finally {
            mWm.setAnimationScale(2, 1.0f);
        }
    }

    @Test
    public void testZeroAnimations() throws Exception {
        mController.goodToGo(TRANSIT_OLD_NONE);
        verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
        verify(mMockRunner).onAnimationCancelled(anyBoolean());
    }

    @Test
    public void testNotReallyStarted() throws Exception {
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        mController.createRemoteAnimationRecord(win.mActivityRecord,
                new Point(50, 100), null, new Rect(50, 100, 150, 150), null);
        mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
        verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
        verify(mMockRunner).onAnimationCancelled(anyBoolean());
    }

    @Test
    public void testOneNotStarted() throws Exception {
        final WindowState win1 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin1");
        final WindowState win2 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin2");
        mController.createRemoteAnimationRecord(win1.mActivityRecord,
                new Point(50, 100), null, new Rect(50, 100, 150, 150), null);
        final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win2.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_ACTIVITY_OPEN);
        mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
        final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
                ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
        final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
                ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
        final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
                ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
        final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
                ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
        verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_ACTIVITY_OPEN),
                appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
                finishedCaptor.capture());
        assertEquals(1, appsCaptor.getValue().length);
        assertEquals(mMockLeash, appsCaptor.getValue()[0].leash);
    }

    @Test
    public void testRemovedBeforeStarted() throws Exception {
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        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);
        win.mActivityRecord.removeImmediately();
        mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
        verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
        verify(mMockRunner).onAnimationCancelled(anyBoolean());
        verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
                eq(adapter));
    }

    @Test
    public void testOpeningTaskWithTopFinishingActivity() {
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "win");
        final Task task = win.getTask();
        final ActivityRecord topFinishing = new ActivityBuilder(mAtm).setTask(task).build();
        // Now the task contains:
        //     - Activity[1] (top, finishing, no window)
        //     - Activity[0] (has window)
        topFinishing.finishing = true;
        spyOn(mDisplayContent.mAppTransition);
        doReturn(mController).when(mDisplayContent.mAppTransition).getRemoteAnimationController();
        task.applyAnimationUnchecked(null /* lp */, true /* enter */, TRANSIT_OLD_TASK_OPEN,
                false /* isVoiceInteraction */, null /* sources */);
        mController.goodToGo(TRANSIT_OLD_TASK_OPEN);
        mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
        final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
                ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
        try {
            verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_OPEN),
                    appsCaptor.capture(), any(), any(), any());
        } catch (RemoteException ignored) {
        }
        assertEquals(1, appsCaptor.getValue().length);
        assertEquals(RemoteAnimationTarget.MODE_OPENING, appsCaptor.getValue()[0].mode);
    }

    @Test
    public void testChangeToSmallerSize() throws Exception {
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        mDisplayContent.mChangingContainers.add(win.mActivityRecord);
        try {
            final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
                    win.mActivityRecord, new Point(50, 100), null, new Rect(50, 100, 150, 150),
                    new Rect(0, 0, 200, 200));
            assertNotNull(record.mThumbnailAdapter);
            ((AnimationAdapter) record.mAdapter)
                    .startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION,
                            mFinishedCallback);
            ((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash,
                    mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback);
            mController.goodToGo(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE);
            mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
            final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
                    ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
            verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE),
                    appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
                    finishedCaptor.capture());
            assertEquals(1, appsCaptor.getValue().length);
            final RemoteAnimationTarget app = appsCaptor.getValue()[0];
            assertEquals(RemoteAnimationTarget.MODE_CHANGING, app.mode);
            assertEquals(new Point(50, 100), app.position);
            assertEquals(new Rect(50, 100, 150, 150), app.sourceContainerBounds);
            assertEquals(new Rect(0, 0, 200, 200), app.startBounds);
            assertEquals(mMockLeash, app.leash);
            assertEquals(mMockThumbnailLeash, app.startLeash);
            assertEquals(false, app.isTranslucent);
            verify(mMockTransaction).setPosition(
                    mMockLeash, app.startBounds.left, app.startBounds.top);
            verify(mMockTransaction).setWindowCrop(
                    mMockLeash, app.startBounds.width(), app.startBounds.height());
            verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
            verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, app.startBounds.width(),
                    app.startBounds.height());

            finishedCaptor.getValue().onAnimationFinished();
            verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
                    eq(record.mAdapter));
            verify(mThumbnailFinishedCallback).onAnimationFinished(
                    eq(ANIMATION_TYPE_WINDOW_ANIMATION), eq(record.mThumbnailAdapter));
        } finally {
            mDisplayContent.mChangingContainers.clear();
        }
    }

    @Test
    public void testChangeTolargerSize() throws Exception {
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        mDisplayContent.mChangingContainers.add(win.mActivityRecord);
        try {
            final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
                    win.mActivityRecord, new Point(0, 0), null, new Rect(0, 0, 200, 200),
                    new Rect(50, 100, 150, 150));
            assertNotNull(record.mThumbnailAdapter);
            ((AnimationAdapter) record.mAdapter)
                    .startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION,
                            mFinishedCallback);
            ((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash,
                    mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback);
            mController.goodToGo(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE);
            mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
            final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
                    ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
            verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE),
                    appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
                    finishedCaptor.capture());
            assertEquals(1, appsCaptor.getValue().length);
            final RemoteAnimationTarget app = appsCaptor.getValue()[0];
            assertEquals(RemoteAnimationTarget.MODE_CHANGING, app.mode);
            assertEquals(new Point(0, 0), app.position);
            assertEquals(new Rect(0, 0, 200, 200), app.sourceContainerBounds);
            assertEquals(new Rect(50, 100, 150, 150), app.startBounds);
            assertEquals(mMockLeash, app.leash);
            assertEquals(mMockThumbnailLeash, app.startLeash);
            assertEquals(false, app.isTranslucent);
            verify(mMockTransaction).setPosition(
                    mMockLeash, app.startBounds.left, app.startBounds.top);
            verify(mMockTransaction).setWindowCrop(
                    mMockLeash, app.startBounds.width(), app.startBounds.height());
            verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
            verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, app.startBounds.width(),
                    app.startBounds.height());

            finishedCaptor.getValue().onAnimationFinished();
            verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
                    eq(record.mAdapter));
            verify(mThumbnailFinishedCallback).onAnimationFinished(
                    eq(ANIMATION_TYPE_WINDOW_ANIMATION), eq(record.mThumbnailAdapter));
        } finally {
            mDisplayContent.mChangingContainers.clear();
        }
    }

    @Test
    public void testChangeToDifferentPosition() throws Exception {
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        mDisplayContent.mChangingContainers.add(win.mActivityRecord);
        try {
            final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
                    win.mActivityRecord, new Point(100, 100), null, new Rect(150, 150, 400, 400),
                    new Rect(50, 100, 150, 150));
            assertNotNull(record.mThumbnailAdapter);
            ((AnimationAdapter) record.mAdapter)
                    .startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION,
                            mFinishedCallback);
            ((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash,
                    mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback);
            mController.goodToGo(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE);
            mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
            final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
                    ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
            verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE),
                    appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
                    finishedCaptor.capture());
            assertEquals(1, appsCaptor.getValue().length);
            final RemoteAnimationTarget app = appsCaptor.getValue()[0];
            assertEquals(RemoteAnimationTarget.MODE_CHANGING, app.mode);
            assertEquals(new Point(100, 100), app.position);
            assertEquals(new Rect(150, 150, 400, 400), app.sourceContainerBounds);
            assertEquals(new Rect(50, 100, 150, 150), app.startBounds);
            assertEquals(mMockLeash, app.leash);
            assertEquals(mMockThumbnailLeash, app.startLeash);
            assertEquals(false, app.isTranslucent);
            verify(mMockTransaction).setPosition(
                    mMockLeash, app.position.x + app.startBounds.left - app.screenSpaceBounds.left,
                    app.position.y + app.startBounds.top - app.screenSpaceBounds.top);
            verify(mMockTransaction).setWindowCrop(
                    mMockLeash, app.startBounds.width(), app.startBounds.height());
            verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
            verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, app.startBounds.width(),
                    app.startBounds.height());

            finishedCaptor.getValue().onAnimationFinished();
            verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
                    eq(record.mAdapter));
            verify(mThumbnailFinishedCallback).onAnimationFinished(
                    eq(ANIMATION_TYPE_WINDOW_ANIMATION), eq(record.mThumbnailAdapter));
        } finally {
            mDisplayContent.mChangingContainers.clear();
        }
    }

    @Test
    public void testWallpaperIncluded_expectTarget() throws Exception {
        final WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class),
                true, mDisplayContent, true /* ownerCanManageAppTokens */);
        spyOn(mDisplayContent.mWallpaperController);
        doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        mDisplayContent.mOpeningApps.add(win.mActivityRecord);
        try {
            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_ACTIVITY_OPEN);
            mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
            final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
                    ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
            verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_ACTIVITY_OPEN),
                    appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
                    finishedCaptor.capture());
            assertEquals(1, wallpapersCaptor.getValue().length);
        } finally {
            mDisplayContent.mOpeningApps.clear();
        }
    }

    @Test
    public void testWallpaperAnimatorCanceled_expectAnimationKeepsRunning() throws Exception {
        final WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class),
                true, mDisplayContent, true /* ownerCanManageAppTokens */);
        spyOn(mDisplayContent.mWallpaperController);
        doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        mDisplayContent.mOpeningApps.add(win.mActivityRecord);
        try {
            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_ACTIVITY_OPEN);
            mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
            final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> nonAPpsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
                    ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
            verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_ACTIVITY_OPEN),
                    appsCaptor.capture(), wallpapersCaptor.capture(), nonAPpsCaptor.capture(),
                    finishedCaptor.capture());
            assertEquals(1, wallpapersCaptor.getValue().length);

            // Cancel the wallpaper window animator and ensure the runner is not canceled
            wallpaperWindowToken.cancelAnimation();
            verify(mMockRunner, never()).onAnimationCancelled(anyBoolean());
        } finally {
            mDisplayContent.mOpeningApps.clear();
        }
    }

    @Test
    public void testNonAppIncluded_keygaurdGoingAway() throws Exception {
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        mDisplayContent.mOpeningApps.add(win.mActivityRecord);
        // Add overlay window hidden by the keyguard.
        final WindowState overlayWin = createAppOverlayWindow();
        overlayWin.hide(false /* doAnimation */, false /* requestAnim */);
        try {
            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_KEYGUARD_GOING_AWAY);
            mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
            final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
                    ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
            verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_KEYGUARD_GOING_AWAY),
                    appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
                    finishedCaptor.capture());
            assertEquals(1, appsCaptor.getValue().length);
            final RemoteAnimationTarget app = appsCaptor.getValue()[0];
            assertEquals(new Point(50, 100), app.position);
            assertEquals(new Rect(50, 100, 150, 150), app.sourceContainerBounds);
            assertEquals(win.mActivityRecord.getPrefixOrderIndex(), app.prefixOrderIndex);
            assertEquals(win.mActivityRecord.getTask().mTaskId, app.taskId);
            assertEquals(mMockLeash, app.leash);
            assertEquals(false, app.isTranslucent);
            verify(mMockTransaction).setPosition(mMockLeash, app.position.x, app.position.y);
            verify(mMockTransaction).setWindowCrop(mMockLeash, 100, 50);

            finishedCaptor.getValue().onAnimationFinished();
            verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
                    eq(adapter));
            assertEquals(1, nonAppsCaptor.getValue().length);
        } finally {
            mDisplayContent.mOpeningApps.clear();
        }
    }

    @Test
    public void testNonAppIncluded_keygaurdGoingAwayToWallpaper() throws Exception {
        final WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class),
                true, mDisplayContent, true /* ownerCanManageAppTokens */);
        spyOn(mDisplayContent.mWallpaperController);
        doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        mDisplayContent.mOpeningApps.add(win.mActivityRecord);
        // Add overlay window hidden by the keyguard.
        final WindowState overlayWin = createAppOverlayWindow();
        overlayWin.hide(false /* doAnimation */, false /* requestAnim */);
        try {
            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_KEYGUARD_GOING_AWAY_ON_WALLPAPER);
            mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
            final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
                    ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
            verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER),
                    appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
                    finishedCaptor.capture());
            assertEquals(1, wallpapersCaptor.getValue().length);
            assertEquals(1, nonAppsCaptor.getValue().length);
        } finally {
            mDisplayContent.mOpeningApps.clear();
        }
    }

    @Test
    public void testNonAppTarget_sendNavBar() throws Exception {
        final int transit = TRANSIT_OLD_TASK_OPEN;
        final AnimationAdapter adapter = setupForNonAppTargetNavBar(transit, true);

        final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
                ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
        final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
                ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
        verify(mMockRunner).onAnimationStart(eq(transit), any(), any(),
                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);
        assertEquals(1, mController.mPendingNonAppAnimations.size());
        final NonAppWindowAnimationAdapter nonAppAdapter =
                mController.mPendingNonAppAnimations.get(0);
        spyOn(nonAppAdapter.getLeashFinishedCallback());

        finishedCaptor.getValue().onAnimationFinished();
        verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
                eq(adapter));
        verify(nonAppAdapter.getLeashFinishedCallback())
                .onAnimationFinished(nonAppAdapter.getLastAnimationType(), nonAppAdapter);
    }

    @Test
    public void testNonAppTarget_notSendNavBar_notAttachToApp() throws Exception {
        final int transit = TRANSIT_OLD_TASK_OPEN;
        setupForNonAppTargetNavBar(transit, false);

        final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
                ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
        verify(mMockRunner).onAnimationStart(eq(transit),
                any(), any(), nonAppsCaptor.capture(), any());
        for (int i = 0; i < nonAppsCaptor.getValue().length; i++) {
            if (nonAppsCaptor.getValue()[0].windowType == TYPE_NAVIGATION_BAR) {
                fail("Non-app animation target must not contain navbar");
            }
        }
    }

    @Test
    public void testNonAppTarget_notSendNavBar_controlledByFadeRotation() throws Exception {
        final AsyncRotationController mockController =
                mock(AsyncRotationController.class);
        doReturn(mockController).when(mDisplayContent).getAsyncRotationController();
        final int transit = TRANSIT_OLD_TASK_OPEN;
        setupForNonAppTargetNavBar(transit, true);

        final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
                ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
        verify(mMockRunner).onAnimationStart(eq(transit),
                any(), any(), nonAppsCaptor.capture(), any());
        for (int i = 0; i < nonAppsCaptor.getValue().length; i++) {
            if (nonAppsCaptor.getValue()[0].windowType == TYPE_NAVIGATION_BAR) {
                fail("Non-app animation target must not contain navbar");
            }
        }
    }

    @Test
    public void testNonAppTarget_notSendNavBar_controlledByRecents() throws Exception {
        final RecentsAnimationController mockController =
                mock(RecentsAnimationController.class);
        doReturn(mockController).when(mWm).getRecentsAnimationController();
        final int transit = TRANSIT_OLD_TASK_OPEN;
        setupForNonAppTargetNavBar(transit, true);

        final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
                ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
        verify(mMockRunner).onAnimationStart(eq(transit),
                any(), any(), nonAppsCaptor.capture(), any());
        for (int i = 0; i < nonAppsCaptor.getValue().length; i++) {
            if (nonAppsCaptor.getValue()[0].windowType == TYPE_NAVIGATION_BAR) {
                fail("Non-app animation target must not contain navbar");
            }
        }
    }

    @UseTestDisplay(addWindows = W_INPUT_METHOD)
    @Test
    public void testLaunchRemoteAnimationWithoutImeBehind() {
        final WindowState win1 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin1");
        final WindowState win2 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin2");

        // Simulating win1 has shown IME and being IME layering/input target
        mDisplayContent.setImeLayeringTarget(win1);
        mDisplayContent.setImeInputTarget(win1);
        mImeWindow.mWinAnimator.mSurfaceController = mock(WindowSurfaceController.class);
        mImeWindow.mWinAnimator.hide(mDisplayContent.getPendingTransaction(), "test");
        spyOn(mDisplayContent);
        doReturn(true).when(mImeWindow.mWinAnimator.mSurfaceController).hasSurface();
        doReturn(true).when(mImeWindow.mWinAnimator.mSurfaceController)
                .prepareToShowInTransaction(any(), anyFloat());
        makeWindowVisibleAndDrawn(mImeWindow);
        assertTrue(mImeWindow.isOnScreen());
        assertFalse(mImeWindow.isParentWindowHidden());

        try {
            // Simulating now win1 is being covered by the lockscreen which has no surface,
            // and then launching an activity win2 with the remote animation
            win1.mHasSurface = false;
            mDisplayContent.mOpeningApps.add(win2.mActivityRecord);
            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
                    win2.mActivityRecord, new Point(50, 100), null,
                    new Rect(50, 100, 150, 150), null).mAdapter;
            adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
                    mFinishedCallback);

            mDisplayContent.applySurfaceChangesTransaction();
            mController.goodToGo(TRANSIT_OLD_TASK_OPEN);
            mWm.mAnimator.executeAfterPrepareSurfacesRunnables();

            verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_OPEN),
                    any(), any(), any(), any());
            // Verify the IME window won't apply surface change transaction with forAllImeWindows
            verify(mDisplayContent, never()).forAllImeWindows(any(), eq(true));
        } catch (Exception e) {
            // no-op
        } finally {
            mDisplayContent.mOpeningApps.clear();
        }
    }

    private AnimationAdapter setupForNonAppTargetNavBar(int transit, boolean shouldAttachNavBar) {
        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(shouldAttachNavBar).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);
        mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
        return adapter;
    }

    private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) {
        verify(binder, atLeast(0)).asBinder();
        verifyNoMoreInteractions(binder);
    }
}
