Loading libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java +31 −3 Original line number Diff line number Diff line Loading @@ -26,8 +26,12 @@ import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.android.window.flags.Flags.FLAG_EXCLUDE_TASK_FROM_RECENTS; import static com.android.window.flags.Flags.enableHandlersDebuggingMode; import static com.android.wm.shell.Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BUBBLES_NOISY; import static com.android.wm.shell.transition.TransitionDispatchState.CAPTURED_CHANGE_IN_WRONG_TRANSITION; import static com.android.wm.shell.transition.TransitionDispatchState.CAPTURED_UNRELATED_CHANGE; import static com.android.wm.shell.transition.TransitionDispatchState.LOST_RELEVANT_CHANGE; import static com.android.wm.shell.transition.Transitions.transitTypeToString; import android.annotation.NonNull; Loading Loading @@ -59,6 +63,7 @@ import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.shared.TransitionUtil; import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper; import com.android.wm.shell.transition.TransitionDispatchState; import com.android.wm.shell.transition.Transitions; import java.util.ArrayList; Loading Loading @@ -716,11 +721,26 @@ public class TaskViewTransitions implements Transitions.TransitionHandler, TaskV @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { if (!Flags.taskViewTransitionsRefactor()) { return startAnimationLegacy(transition, info, startTransaction, finishTransaction, finishCallback); return startAnimation(transition, info, TransitionDispatchState.getDummyInstance(), startTransaction, finishTransaction, finishCallback); } @Override public boolean startAnimation(@NonNull IBinder transition, @Nullable TransitionInfo transitionInfo, @NonNull TransitionDispatchState dispatchState, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { if (!Flags.taskViewTransitionsRefactor() && !enableHandlersDebuggingMode()) { return startAnimationLegacy(transition, transitionInfo, startTransaction, finishTransaction, finishCallback); } final boolean inDataCollectionModeOnly = enableHandlersDebuggingMode() && transitionInfo == null; final boolean inAnimationMode = !inDataCollectionModeOnly; final TransitionInfo info = inDataCollectionModeOnly ? dispatchState.mInfo : transitionInfo; final PendingTransition pending = findPending(transition); ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "Transitions.startAnimation(): taskView=%d " + "type=%s transition=%s", pending != null ? pending.mTaskView.hashCode() : -1, Loading @@ -744,10 +764,16 @@ public class TaskViewTransitions implements Transitions.TransitionHandler, TaskV final TransitionInfo.Change chg = info.getChanges().get(i); if (isValidTaskView(chg, pending)) { taskViews.add(chg); if (inDataCollectionModeOnly) { dispatchState.addError(this, chg, LOST_RELEVANT_CHANGE); } } else { alienChanges.add(chg); } } if (inDataCollectionModeOnly) { return false; } // Prepare taskViews for animation for (int i = 0; i < taskViews.size(); ++i) { Loading Loading @@ -822,10 +848,12 @@ public class TaskViewTransitions implements Transitions.TransitionHandler, TaskV Slog.e(TAG, "Found a launching TaskView in the wrong transition. All " + "TaskView launches should be initiated by shell and in their " + "own transition: " + taskInfo.taskId); dispatchState.addError(this, change, CAPTURED_CHANGE_IN_WRONG_TRANSITION); } else { Slog.w(TAG, "Found a non-TaskView task in a TaskView Transition. This " + "shouldn't happen, so there may be a visual artifact: " + taskInfo.taskId); dispatchState.addError(this, change, CAPTURED_UNRELATED_CHANGE); } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionDispatchState.java +3 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ public class TransitionDispatchState { // Change-related errors public static final int LOST_RELEVANT_CHANGE = 3; public static final int CAPTURED_UNRELATED_CHANGE = 4; public static final int CAPTURED_CHANGE_IN_WRONG_TRANSITION = 5; @IntDef( value = { Loading @@ -44,6 +45,7 @@ public class TransitionDispatchState { CAPTURED_UNRELATED_FLAG, LOST_RELEVANT_CHANGE, CAPTURED_UNRELATED_CHANGE, CAPTURED_CHANGE_IN_WRONG_TRANSITION, }) public @interface ErrorCode {} Loading @@ -54,6 +56,7 @@ public class TransitionDispatchState { case CAPTURED_UNRELATED_FLAG -> "CAPTURED_UNRELATED_FLAG"; case LOST_RELEVANT_CHANGE -> "LOST_RELEVANT_CHANGE"; case CAPTURED_UNRELATED_CHANGE -> "CAPTURED_UNRELATED_CHANGE"; case CAPTURED_CHANGE_IN_WRONG_TRANSITION -> "CAPTURED_CHANGE_IN_WRONG_TRANSITION"; default -> "UNKNOWN"; }; } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionStartAnimationTest.java +93 −4 Original line number Diff line number Diff line Loading @@ -22,7 +22,11 @@ import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.android.window.flags.Flags.enableHandlersDebuggingMode; import static com.android.wm.shell.Flags.FLAG_TASK_VIEW_TRANSITIONS_REFACTOR; import static com.android.wm.shell.Flags.taskViewTransitionsRefactor; import static com.android.wm.shell.transition.TransitionDispatchState.CAPTURED_UNRELATED_CHANGE; import static com.android.wm.shell.transition.TransitionDispatchState.LOST_RELEVANT_CHANGE; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; Loading @@ -44,6 +48,7 @@ import android.os.IBinder; import android.platform.test.annotations.UsesFlags; import android.platform.test.flag.junit.FlagsParameterization; import android.testing.TestableLooper; import android.util.Slog; import android.view.SurfaceControl; import android.window.TransitionInfo; import android.window.WindowContainerToken; Loading @@ -55,6 +60,7 @@ import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper; import com.android.wm.shell.transition.TransitionDispatchState; import com.android.wm.shell.transition.TransitionInfoBuilder; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.util.StubTransaction; Loading @@ -73,9 +79,10 @@ import java.util.List; /** * Class to verify the behavior of startAnimation. * Verifies that changes behind FLAG_ENABLE_HANDLERS_DEBUGGING_MODE don't change the behavior * of startAnimation. The refactor tests' life span matches the flag's. Permanent tests are meant * to be added to TaskViewTransitionsTest. * 1. Verifies that startAnimation populates TransitionDispatchState correctly. * 2. Verifies that changes behind FLAG_ENABLE_HANDLERS_DEBUGGING_MODE don't change the behavior * of startAnimation. Refactor test's life span matches the flag's. Permanent tests are meant to * be added to TaskViewTransitionsTest. * Test failures that manifest only when the flag is on mean that the behavior diverged. */ @SmallTest Loading Loading @@ -123,6 +130,8 @@ public class TaskViewTransitionStartAnimationTest extends ShellTestCase { TaskViewTransitions.PendingTransition mPendingFront; TaskViewTransitions.PendingTransition mPendingBack; static final String TAG = "TVstartAnimTest"; public TaskViewTransitionStartAnimationTest(FlagsParameterization flags) { mSetFlagsRule.setFlagsParameterization(flags); } Loading @@ -147,6 +156,7 @@ public class TaskViewTransitionStartAnimationTest extends ShellTestCase { mUnregisteredTaskInfo.token = mUnregisteredToken; // Same id as the other to match pending info id mUnregisteredTaskInfo.taskId = 314; mUnregisteredTaskInfo.launchCookies.add(mock(IBinder.class)); mTaskInfo.taskDescription = mock(ActivityManager.TaskDescription.class); mBounds = new Rect(0, 0, 100, 100); Loading Loading @@ -208,6 +218,85 @@ public class TaskViewTransitionStartAnimationTest extends ShellTestCase { return pending; } /** * Tests on TransitionDispatchState */ @Test public void taskView_dispatchStateFindsIncompatible_animationMode() { assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS); assumeTrue(enableHandlersDebuggingMode()); assumeTrue(taskViewTransitionsRefactor()); // To avoid running twice TransitionInfo.Change showingTV = getTaskView(TRANSIT_TO_FRONT); TransitionInfo.Change nonTV = getTask(TRANSIT_TO_BACK, false /* registered */); TaskViewTransitions.PendingTransition pending = setPendingTransaction(true /* visible*/, false /* opening */); // Showing taskView + normal task. // TaskView is accepted, but normal task is detected as error final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_TO_FRONT) .addChange(showingTV) .addChange(nonTV) .build(); TransitionDispatchState dispatchState = spy(new TransitionDispatchState(pending.mClaimed, info)); boolean handled = mTaskViewTransitions.startAnimation(pending.mClaimed, info, dispatchState, mStartTransaction, mFinishTransaction, mFinishCallback); Slog.v(TAG, "DispatchState:\n" + dispatchState.getDebugInfo()); // Has animated the taskView assertWithMessage("Handler should play the transition") .that(handled).isTrue(); ArgumentCaptor<WindowContainerTransaction> wctCaptor = ArgumentCaptor.forClass(WindowContainerTransaction.class); verify(mFinishCallback).onTransitionFinished(wctCaptor.capture()); assertWithMessage("Expected wct to be created and sent to callback") .that(wctCaptor.getValue()).isNotNull(); verify(pending.mTaskView).notifyAppeared(eq(false)); // Non task-view spotted as intruder verify(dispatchState).addError(eq(mTaskViewTransitions), eq(nonTV), eq(CAPTURED_UNRELATED_CHANGE)); assertThat(dispatchState.hasErrors(mTaskViewTransitions)).isTrue(); } @Test public void taskView_dispatchStateFindsCompatible_dataCollectionMode() { assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS); assumeTrue(enableHandlersDebuggingMode()); assumeTrue(taskViewTransitionsRefactor()); // To avoid running twice TransitionInfo.Change showingTV = getTaskView(TRANSIT_TO_FRONT); TransitionInfo.Change nonTV = getTask(TRANSIT_TO_BACK, false /* registered */); TaskViewTransitions.PendingTransition pending = setPendingTransaction(true /* visible*/, false /* opening */); // Showing taskView + normal task. // TaskView is detected as change that could have played final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_TO_FRONT) .addChange(showingTV) .addChange(nonTV) .build(); TransitionDispatchState dispatchState = spy(new TransitionDispatchState(pending.mClaimed, info)); boolean handled = mTaskViewTransitions.startAnimation(pending.mClaimed, null, dispatchState, mStartTransaction, mFinishTransaction, mFinishCallback); Slog.v(TAG, "DispatchState:\n" + dispatchState.getDebugInfo()); // Has not animated the taskView assertWithMessage("Handler should not play the transition") .that(handled).isFalse(); verify(mFinishCallback, never()).onTransitionFinished(any()); verify(pending.mTaskView, never()).notifyAppeared(anyBoolean()); // Non task-view spotted as intruder verify(dispatchState) .addError(eq(mTaskViewTransitions), eq(showingTV), eq(LOST_RELEVANT_CHANGE)); assertThat(dispatchState.hasErrors(mTaskViewTransitions)).isTrue(); } /** * Refactor tests on taskViews */ Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java +31 −3 Original line number Diff line number Diff line Loading @@ -26,8 +26,12 @@ import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.android.window.flags.Flags.FLAG_EXCLUDE_TASK_FROM_RECENTS; import static com.android.window.flags.Flags.enableHandlersDebuggingMode; import static com.android.wm.shell.Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BUBBLES_NOISY; import static com.android.wm.shell.transition.TransitionDispatchState.CAPTURED_CHANGE_IN_WRONG_TRANSITION; import static com.android.wm.shell.transition.TransitionDispatchState.CAPTURED_UNRELATED_CHANGE; import static com.android.wm.shell.transition.TransitionDispatchState.LOST_RELEVANT_CHANGE; import static com.android.wm.shell.transition.Transitions.transitTypeToString; import android.annotation.NonNull; Loading Loading @@ -59,6 +63,7 @@ import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.shared.TransitionUtil; import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper; import com.android.wm.shell.transition.TransitionDispatchState; import com.android.wm.shell.transition.Transitions; import java.util.ArrayList; Loading Loading @@ -716,11 +721,26 @@ public class TaskViewTransitions implements Transitions.TransitionHandler, TaskV @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { if (!Flags.taskViewTransitionsRefactor()) { return startAnimationLegacy(transition, info, startTransaction, finishTransaction, finishCallback); return startAnimation(transition, info, TransitionDispatchState.getDummyInstance(), startTransaction, finishTransaction, finishCallback); } @Override public boolean startAnimation(@NonNull IBinder transition, @Nullable TransitionInfo transitionInfo, @NonNull TransitionDispatchState dispatchState, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { if (!Flags.taskViewTransitionsRefactor() && !enableHandlersDebuggingMode()) { return startAnimationLegacy(transition, transitionInfo, startTransaction, finishTransaction, finishCallback); } final boolean inDataCollectionModeOnly = enableHandlersDebuggingMode() && transitionInfo == null; final boolean inAnimationMode = !inDataCollectionModeOnly; final TransitionInfo info = inDataCollectionModeOnly ? dispatchState.mInfo : transitionInfo; final PendingTransition pending = findPending(transition); ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "Transitions.startAnimation(): taskView=%d " + "type=%s transition=%s", pending != null ? pending.mTaskView.hashCode() : -1, Loading @@ -744,10 +764,16 @@ public class TaskViewTransitions implements Transitions.TransitionHandler, TaskV final TransitionInfo.Change chg = info.getChanges().get(i); if (isValidTaskView(chg, pending)) { taskViews.add(chg); if (inDataCollectionModeOnly) { dispatchState.addError(this, chg, LOST_RELEVANT_CHANGE); } } else { alienChanges.add(chg); } } if (inDataCollectionModeOnly) { return false; } // Prepare taskViews for animation for (int i = 0; i < taskViews.size(); ++i) { Loading Loading @@ -822,10 +848,12 @@ public class TaskViewTransitions implements Transitions.TransitionHandler, TaskV Slog.e(TAG, "Found a launching TaskView in the wrong transition. All " + "TaskView launches should be initiated by shell and in their " + "own transition: " + taskInfo.taskId); dispatchState.addError(this, change, CAPTURED_CHANGE_IN_WRONG_TRANSITION); } else { Slog.w(TAG, "Found a non-TaskView task in a TaskView Transition. This " + "shouldn't happen, so there may be a visual artifact: " + taskInfo.taskId); dispatchState.addError(this, change, CAPTURED_UNRELATED_CHANGE); } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionDispatchState.java +3 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ public class TransitionDispatchState { // Change-related errors public static final int LOST_RELEVANT_CHANGE = 3; public static final int CAPTURED_UNRELATED_CHANGE = 4; public static final int CAPTURED_CHANGE_IN_WRONG_TRANSITION = 5; @IntDef( value = { Loading @@ -44,6 +45,7 @@ public class TransitionDispatchState { CAPTURED_UNRELATED_FLAG, LOST_RELEVANT_CHANGE, CAPTURED_UNRELATED_CHANGE, CAPTURED_CHANGE_IN_WRONG_TRANSITION, }) public @interface ErrorCode {} Loading @@ -54,6 +56,7 @@ public class TransitionDispatchState { case CAPTURED_UNRELATED_FLAG -> "CAPTURED_UNRELATED_FLAG"; case LOST_RELEVANT_CHANGE -> "LOST_RELEVANT_CHANGE"; case CAPTURED_UNRELATED_CHANGE -> "CAPTURED_UNRELATED_CHANGE"; case CAPTURED_CHANGE_IN_WRONG_TRANSITION -> "CAPTURED_CHANGE_IN_WRONG_TRANSITION"; default -> "UNKNOWN"; }; } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionStartAnimationTest.java +93 −4 Original line number Diff line number Diff line Loading @@ -22,7 +22,11 @@ import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static com.android.window.flags.Flags.enableHandlersDebuggingMode; import static com.android.wm.shell.Flags.FLAG_TASK_VIEW_TRANSITIONS_REFACTOR; import static com.android.wm.shell.Flags.taskViewTransitionsRefactor; import static com.android.wm.shell.transition.TransitionDispatchState.CAPTURED_UNRELATED_CHANGE; import static com.android.wm.shell.transition.TransitionDispatchState.LOST_RELEVANT_CHANGE; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; Loading @@ -44,6 +48,7 @@ import android.os.IBinder; import android.platform.test.annotations.UsesFlags; import android.platform.test.flag.junit.FlagsParameterization; import android.testing.TestableLooper; import android.util.Slog; import android.view.SurfaceControl; import android.window.TransitionInfo; import android.window.WindowContainerToken; Loading @@ -55,6 +60,7 @@ import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper; import com.android.wm.shell.transition.TransitionDispatchState; import com.android.wm.shell.transition.TransitionInfoBuilder; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.util.StubTransaction; Loading @@ -73,9 +79,10 @@ import java.util.List; /** * Class to verify the behavior of startAnimation. * Verifies that changes behind FLAG_ENABLE_HANDLERS_DEBUGGING_MODE don't change the behavior * of startAnimation. The refactor tests' life span matches the flag's. Permanent tests are meant * to be added to TaskViewTransitionsTest. * 1. Verifies that startAnimation populates TransitionDispatchState correctly. * 2. Verifies that changes behind FLAG_ENABLE_HANDLERS_DEBUGGING_MODE don't change the behavior * of startAnimation. Refactor test's life span matches the flag's. Permanent tests are meant to * be added to TaskViewTransitionsTest. * Test failures that manifest only when the flag is on mean that the behavior diverged. */ @SmallTest Loading Loading @@ -123,6 +130,8 @@ public class TaskViewTransitionStartAnimationTest extends ShellTestCase { TaskViewTransitions.PendingTransition mPendingFront; TaskViewTransitions.PendingTransition mPendingBack; static final String TAG = "TVstartAnimTest"; public TaskViewTransitionStartAnimationTest(FlagsParameterization flags) { mSetFlagsRule.setFlagsParameterization(flags); } Loading @@ -147,6 +156,7 @@ public class TaskViewTransitionStartAnimationTest extends ShellTestCase { mUnregisteredTaskInfo.token = mUnregisteredToken; // Same id as the other to match pending info id mUnregisteredTaskInfo.taskId = 314; mUnregisteredTaskInfo.launchCookies.add(mock(IBinder.class)); mTaskInfo.taskDescription = mock(ActivityManager.TaskDescription.class); mBounds = new Rect(0, 0, 100, 100); Loading Loading @@ -208,6 +218,85 @@ public class TaskViewTransitionStartAnimationTest extends ShellTestCase { return pending; } /** * Tests on TransitionDispatchState */ @Test public void taskView_dispatchStateFindsIncompatible_animationMode() { assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS); assumeTrue(enableHandlersDebuggingMode()); assumeTrue(taskViewTransitionsRefactor()); // To avoid running twice TransitionInfo.Change showingTV = getTaskView(TRANSIT_TO_FRONT); TransitionInfo.Change nonTV = getTask(TRANSIT_TO_BACK, false /* registered */); TaskViewTransitions.PendingTransition pending = setPendingTransaction(true /* visible*/, false /* opening */); // Showing taskView + normal task. // TaskView is accepted, but normal task is detected as error final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_TO_FRONT) .addChange(showingTV) .addChange(nonTV) .build(); TransitionDispatchState dispatchState = spy(new TransitionDispatchState(pending.mClaimed, info)); boolean handled = mTaskViewTransitions.startAnimation(pending.mClaimed, info, dispatchState, mStartTransaction, mFinishTransaction, mFinishCallback); Slog.v(TAG, "DispatchState:\n" + dispatchState.getDebugInfo()); // Has animated the taskView assertWithMessage("Handler should play the transition") .that(handled).isTrue(); ArgumentCaptor<WindowContainerTransaction> wctCaptor = ArgumentCaptor.forClass(WindowContainerTransaction.class); verify(mFinishCallback).onTransitionFinished(wctCaptor.capture()); assertWithMessage("Expected wct to be created and sent to callback") .that(wctCaptor.getValue()).isNotNull(); verify(pending.mTaskView).notifyAppeared(eq(false)); // Non task-view spotted as intruder verify(dispatchState).addError(eq(mTaskViewTransitions), eq(nonTV), eq(CAPTURED_UNRELATED_CHANGE)); assertThat(dispatchState.hasErrors(mTaskViewTransitions)).isTrue(); } @Test public void taskView_dispatchStateFindsCompatible_dataCollectionMode() { assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS); assumeTrue(enableHandlersDebuggingMode()); assumeTrue(taskViewTransitionsRefactor()); // To avoid running twice TransitionInfo.Change showingTV = getTaskView(TRANSIT_TO_FRONT); TransitionInfo.Change nonTV = getTask(TRANSIT_TO_BACK, false /* registered */); TaskViewTransitions.PendingTransition pending = setPendingTransaction(true /* visible*/, false /* opening */); // Showing taskView + normal task. // TaskView is detected as change that could have played final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_TO_FRONT) .addChange(showingTV) .addChange(nonTV) .build(); TransitionDispatchState dispatchState = spy(new TransitionDispatchState(pending.mClaimed, info)); boolean handled = mTaskViewTransitions.startAnimation(pending.mClaimed, null, dispatchState, mStartTransaction, mFinishTransaction, mFinishCallback); Slog.v(TAG, "DispatchState:\n" + dispatchState.getDebugInfo()); // Has not animated the taskView assertWithMessage("Handler should not play the transition") .that(handled).isFalse(); verify(mFinishCallback, never()).onTransitionFinished(any()); verify(pending.mTaskView, never()).notifyAppeared(anyBoolean()); // Non task-view spotted as intruder verify(dispatchState) .addError(eq(mTaskViewTransitions), eq(showingTV), eq(LOST_RELEVANT_CHANGE)); assertThat(dispatchState.hasErrors(mTaskViewTransitions)).isTrue(); } /** * Refactor tests on taskViews */ Loading