summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tom Natan <tomnatan@google.com> 2022-03-16 00:26:02 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-03-16 00:26:02 +0000
commit5059dbde7b07cb405c6dedf8e734d09ada6cd90f (patch)
treecd5b8f98bdf099ad93564ae9e76d9e02cdf0dd81
parent840f39893e825f92df4fd1aee3acdcc459a52d7e (diff)
parentdc3dac34bdf38cda039e1b28f0707f31e599a569 (diff)
Merge "[18/n] Letterbox Education: start dialog enter animation after all shell transitions have finished" into tm-dev
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduAnimationController.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java27
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java23
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java7
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManagerTest.java31
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java82
9 files changed, 176 insertions, 14 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index b2bbafeb7bf5..99b32a677abe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -42,6 +42,7 @@ import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.compatui.CompatUIWindowManager.CompatUIHintsState;
import com.android.wm.shell.compatui.letterboxedu.LetterboxEduWindowManager;
+import com.android.wm.shell.transition.Transitions;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -50,6 +51,8 @@ import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
+import dagger.Lazy;
+
/**
* Controller to show/update compat UI components on Tasks based on whether the foreground
* activities are in compatibility mode.
@@ -102,6 +105,7 @@ public class CompatUIController implements OnDisplaysChangedListener,
private final DisplayImeController mImeController;
private final SyncTransactionQueue mSyncQueue;
private final ShellExecutor mMainExecutor;
+ private final Lazy<Transitions> mTransitionsLazy;
private final CompatUIImpl mImpl = new CompatUIImpl();
private CompatUICallback mCallback;
@@ -118,13 +122,15 @@ public class CompatUIController implements OnDisplaysChangedListener,
DisplayInsetsController displayInsetsController,
DisplayImeController imeController,
SyncTransactionQueue syncQueue,
- ShellExecutor mainExecutor) {
+ ShellExecutor mainExecutor,
+ Lazy<Transitions> transitionsLazy) {
mContext = context;
mDisplayController = displayController;
mDisplayInsetsController = displayInsetsController;
mImeController = imeController;
mSyncQueue = syncQueue;
mMainExecutor = mainExecutor;
+ mTransitionsLazy = transitionsLazy;
mDisplayController.addDisplayWindowListener(this);
mImeController.addPositionProcessor(this);
mCompatUIHintsState = new CompatUIHintsState();
@@ -302,6 +308,7 @@ public class CompatUIController implements OnDisplaysChangedListener,
ShellTaskOrganizer.TaskListener taskListener) {
return new LetterboxEduWindowManager(context, taskInfo,
mSyncQueue, taskListener, mDisplayController.getDisplayLayout(taskInfo.displayId),
+ mTransitionsLazy.get(),
this::onLetterboxEduDismissed);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduAnimationController.java
index 03986ee3b6d2..3061eab17d24 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduAnimationController.java
@@ -18,6 +18,7 @@ package com.android.wm.shell.compatui.letterboxedu;
import static com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
import static com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
+import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -42,7 +43,9 @@ import com.android.internal.policy.TransitionAnimation;
class LetterboxEduAnimationController {
private static final String TAG = "LetterboxEduAnimation";
- private static final int ENTER_ANIM_START_DELAY_MILLIS = 500;
+ // If shell transitions are enabled, startEnterAnimation will be called after all transitions
+ // have finished, and therefore the start delay should be shorter.
+ private static final int ENTER_ANIM_START_DELAY_MILLIS = ENABLE_SHELL_TRANSITIONS ? 300 : 500;
private final TransitionAnimation mTransitionAnimation;
private final String mPackageName;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java
index 8aa4d0ee99ab..2e0b09e9d230 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduDialogLayout.java
@@ -38,6 +38,7 @@ class LetterboxEduDialogLayout extends ConstraintLayout {
// The alpha of a background is a number between 0 (fully transparent) to 255 (fully opaque).
// 204 is simply 255 * 0.8.
static final int BACKGROUND_DIM_ALPHA = 204;
+
private View mDialogContainer;
private TextView mDialogTitle;
private Drawable mBackgroundDim;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java
index dda72ffb432f..cc3a3b2206f3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManager.java
@@ -36,6 +36,7 @@ import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.compatui.CompatUIWindowManagerAbstract;
+import com.android.wm.shell.transition.Transitions;
/**
* Window manager for the Letterbox Education.
@@ -63,6 +64,8 @@ public class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
private final LetterboxEduAnimationController mAnimationController;
+ private final Transitions mTransitions;
+
// Remember the last reported state in case visibility changes due to keyguard or IME updates.
private boolean mEligibleForLetterboxEducation;
@@ -80,17 +83,19 @@ public class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
public LetterboxEduWindowManager(Context context, TaskInfo taskInfo,
SyncTransactionQueue syncQueue, ShellTaskOrganizer.TaskListener taskListener,
- DisplayLayout displayLayout, Runnable onDismissCallback) {
- this(context, taskInfo, syncQueue, taskListener, displayLayout, onDismissCallback,
- new LetterboxEduAnimationController(context));
+ DisplayLayout displayLayout, Transitions transitions,
+ Runnable onDismissCallback) {
+ this(context, taskInfo, syncQueue, taskListener, displayLayout, transitions,
+ onDismissCallback, new LetterboxEduAnimationController(context));
}
@VisibleForTesting
LetterboxEduWindowManager(Context context, TaskInfo taskInfo,
SyncTransactionQueue syncQueue, ShellTaskOrganizer.TaskListener taskListener,
- DisplayLayout displayLayout, Runnable onDismissCallback,
+ DisplayLayout displayLayout, Transitions transitions, Runnable onDismissCallback,
LetterboxEduAnimationController animationController) {
super(context, taskInfo, syncQueue, taskListener, displayLayout);
+ mTransitions = transitions;
mOnDismissCallback = onDismissCallback;
mAnimationController = animationController;
mEligibleForLetterboxEducation = taskInfo.topActivityEligibleForLetterboxEducation;
@@ -132,8 +137,8 @@ public class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
mLayout = inflateLayout();
updateDialogMargins();
- mAnimationController.startEnterAnimation(mLayout, /* endCallback= */
- this::onDialogEnterAnimationEnded);
+ // startEnterAnimation will be called immediately if shell-transitions are disabled.
+ mTransitions.runOnIdle(this::startEnterAnimation);
return mLayout;
}
@@ -158,8 +163,18 @@ public class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
R.layout.letterbox_education_dialog_layout, null);
}
+ private void startEnterAnimation() {
+ if (mLayout == null) {
+ // Dialog has already been released.
+ return;
+ }
+ mAnimationController.startEnterAnimation(mLayout, /* endCallback= */
+ this::onDialogEnterAnimationEnded);
+ }
+
private void onDialogEnterAnimationEnded() {
if (mLayout == null) {
+ // Dialog has already been released.
return;
}
mLayout.setDismissOnClickListener(this::onDismiss);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index bf0337dbd11a..1ee9407d385d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -96,6 +96,7 @@ import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
import java.util.Optional;
import dagger.BindsOptionalOf;
+import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
@@ -210,9 +211,9 @@ public abstract class WMShellBaseModule {
static CompatUIController provideCompatUIController(Context context,
DisplayController displayController, DisplayInsetsController displayInsetsController,
DisplayImeController imeController, SyncTransactionQueue syncQueue,
- @ShellMainThread ShellExecutor mainExecutor) {
+ @ShellMainThread ShellExecutor mainExecutor, Lazy<Transitions> transitionsLazy) {
return new CompatUIController(context, displayController, displayInsetsController,
- imeController, syncQueue, mainExecutor);
+ imeController, syncQueue, mainExecutor, transitionsLazy);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index fb3cd87448d1..435d67087f34 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -109,6 +109,9 @@ public class Transitions implements RemoteCallable<Transitions> {
/** List of possible handlers. Ordered by specificity (eg. tapped back to front). */
private final ArrayList<TransitionHandler> mHandlers = new ArrayList<>();
+ /** List of {@link Runnable} instances to run when the last active transition has finished. */
+ private final ArrayList<Runnable> mRunWhenIdleQueue = new ArrayList<>();
+
private float mTransitionAnimationScaleSetting = 1.0f;
private static final class ActiveTransition {
@@ -224,6 +227,21 @@ public class Transitions implements RemoteCallable<Transitions> {
mRemoteTransitionHandler.removeFiltered(remoteTransition);
}
+ /**
+ * Runs the given {@code runnable} when the last active transition has finished, or immediately
+ * if there are currently no active transitions.
+ *
+ * <p>This method should be called on the Shell main-thread, where the given {@code runnable}
+ * will be executed when the last active transition is finished.
+ */
+ public void runOnIdle(Runnable runnable) {
+ if (mActiveTransitions.isEmpty()) {
+ runnable.run();
+ } else {
+ mRunWhenIdleQueue.add(runnable);
+ }
+ }
+
/** @return true if the transition was triggered by opening something vs closing something */
public static boolean isOpeningType(@WindowManager.TransitionType int type) {
return type == TRANSIT_OPEN
@@ -520,6 +538,11 @@ public class Transitions implements RemoteCallable<Transitions> {
if (mActiveTransitions.size() <= activeIdx) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "All active transition animations "
+ "finished");
+ // Run all runnables from the run-when-idle queue.
+ for (int i = 0; i < mRunWhenIdleQueue.size(); i++) {
+ mRunWhenIdleQueue.get(i).run();
+ }
+ mRunWhenIdleQueue.clear();
return;
}
// Start animating the next active transition
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
index a31b28737552..4607d8acc63e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
@@ -53,6 +53,7 @@ import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.compatui.letterboxedu.LetterboxEduWindowManager;
+import com.android.wm.shell.transition.Transitions;
import org.junit.Before;
import org.junit.Test;
@@ -62,6 +63,8 @@ import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import dagger.Lazy;
+
/**
* Tests for {@link CompatUIController}.
*
@@ -82,6 +85,7 @@ public class CompatUIControllerTest extends ShellTestCase {
private @Mock ShellTaskOrganizer.TaskListener mMockTaskListener;
private @Mock SyncTransactionQueue mMockSyncQueue;
private @Mock ShellExecutor mMockExecutor;
+ private @Mock Lazy<Transitions> mMockTransitionsLazy;
private @Mock CompatUIWindowManager mMockCompatLayout;
private @Mock LetterboxEduWindowManager mMockLetterboxEduLayout;
@@ -102,7 +106,8 @@ public class CompatUIControllerTest extends ShellTestCase {
doReturn(true).when(mMockLetterboxEduLayout).createLayout(anyBoolean());
doReturn(true).when(mMockLetterboxEduLayout).updateCompatInfo(any(), any(), anyBoolean());
mController = new CompatUIController(mContext, mMockDisplayController,
- mMockDisplayInsetsController, mMockImeController, mMockSyncQueue, mMockExecutor) {
+ mMockDisplayInsetsController, mMockImeController, mMockSyncQueue, mMockExecutor,
+ mMockTransitionsLazy) {
@Override
CompatUIWindowManager createCompatUiWindowManager(Context context, TaskInfo taskInfo,
ShellTaskOrganizer.TaskListener taskListener) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManagerTest.java
index 337b7385faec..7d51b521a9fb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManagerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterboxedu/LetterboxEduWindowManagerTest.java
@@ -54,6 +54,7 @@ import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.transition.Transitions;
import org.junit.After;
import org.junit.Before;
@@ -86,11 +87,14 @@ public class LetterboxEduWindowManagerTest extends ShellTestCase {
private ArgumentCaptor<WindowManager.LayoutParams> mWindowAttrsCaptor;
@Captor
private ArgumentCaptor<Runnable> mEndCallbackCaptor;
+ @Captor
+ private ArgumentCaptor<Runnable> mRunOnIdleCaptor;
@Mock private LetterboxEduAnimationController mAnimationController;
@Mock private SyncTransactionQueue mSyncTransactionQueue;
@Mock private ShellTaskOrganizer.TaskListener mTaskListener;
@Mock private SurfaceControlViewHost mViewHost;
+ @Mock private Transitions mTransitions;
@Mock private Runnable mOnDismissCallback;
private SharedPreferences mSharedPreferences;
@@ -204,6 +208,23 @@ public class LetterboxEduWindowManagerTest extends ShellTestCase {
}
@Test
+ public void testCreateLayout_windowManagerReleasedBeforeTransitionsIsIdle_doesNotStartAnim() {
+ LetterboxEduWindowManager windowManager = createWindowManager(/* eligible= */ true);
+
+ assertTrue(windowManager.createLayout(/* canShow= */ true));
+
+ assertTrue(mSharedPreferences.getBoolean(mPrefKey, /* default= */ false));
+
+ verify(mTransitions).runOnIdle(mRunOnIdleCaptor.capture());
+
+ windowManager.release();
+
+ mRunOnIdleCaptor.getValue().run();
+
+ verify(mAnimationController, never()).startEnterAnimation(any(), any());
+ }
+
+ @Test
public void testUpdateCompatInfo_updatesLayoutCorrectly() {
LetterboxEduWindowManager windowManager = createWindowManager(/* eligible= */ true);
@@ -303,6 +324,13 @@ public class LetterboxEduWindowManagerTest extends ShellTestCase {
}
private void verifyAndFinishEnterAnimation(LetterboxEduDialogLayout layout) {
+ verify(mTransitions).runOnIdle(mRunOnIdleCaptor.capture());
+
+ // startEnterAnimation isn't called until run-on-idle runnable is called.
+ verify(mAnimationController, never()).startEnterAnimation(any(), any());
+
+ mRunOnIdleCaptor.getValue().run();
+
verify(mAnimationController).startEnterAnimation(eq(layout), mEndCallbackCaptor.capture());
mEndCallbackCaptor.getValue().run();
}
@@ -320,7 +348,8 @@ public class LetterboxEduWindowManagerTest extends ShellTestCase {
boolean isTaskbarEduShowing) {
LetterboxEduWindowManager windowManager = new LetterboxEduWindowManager(mContext,
createTaskInfo(eligible), mSyncTransactionQueue, mTaskListener,
- createDisplayLayout(), mOnDismissCallback, mAnimationController);
+ createDisplayLayout(), mTransitions, mOnDismissCallback,
+ mAnimationController);
spyOn(windowManager);
doReturn(mViewHost).when(windowManager).createSurfaceViewHost();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index dbf93b4d7e0a..a0b12976b467 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -46,6 +46,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -93,7 +94,7 @@ import java.util.ArrayList;
* Tests for the shell transitions.
*
* Build/Install/Run:
- * atest WMShellUnitTests:ShellTransitionTests
+ * atest WMShellUnitTests:ShellTransitionTests
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -600,6 +601,83 @@ public class ShellTransitionTests {
assertTrue(DefaultTransitionHandler.isRotationSeamless(seamlessDisplay, displays));
}
+ @Test
+ public void testRunWhenIdle() {
+ Transitions transitions = createTestTransitions();
+ transitions.replaceDefaultHandlerForTest(mDefaultHandler);
+
+ Runnable runnable1 = mock(Runnable.class);
+ Runnable runnable2 = mock(Runnable.class);
+ Runnable runnable3 = mock(Runnable.class);
+ Runnable runnable4 = mock(Runnable.class);
+
+ transitions.runOnIdle(runnable1);
+
+ // runnable1 is executed immediately because there are no active transitions.
+ verify(runnable1, times(1)).run();
+
+ clearInvocations(runnable1);
+
+ IBinder transitToken1 = new Binder();
+ transitions.requestStartTransition(transitToken1,
+ new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
+ TransitionInfo info1 = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+ transitions.onTransitionReady(transitToken1, info1, mock(SurfaceControl.Transaction.class),
+ mock(SurfaceControl.Transaction.class));
+ assertEquals(1, mDefaultHandler.activeCount());
+
+ transitions.runOnIdle(runnable2);
+ transitions.runOnIdle(runnable3);
+
+ // runnable2 and runnable3 aren't executed immediately because there is an active
+ // transaction.
+
+ IBinder transitToken2 = new Binder();
+ transitions.requestStartTransition(transitToken2,
+ new TransitionRequestInfo(TRANSIT_CLOSE, null /* trigger */, null /* remote */));
+ TransitionInfo info2 = new TransitionInfoBuilder(TRANSIT_CLOSE)
+ .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+ transitions.onTransitionReady(transitToken2, info2, mock(SurfaceControl.Transaction.class),
+ mock(SurfaceControl.Transaction.class));
+ assertEquals(1, mDefaultHandler.activeCount());
+
+ mDefaultHandler.finishAll();
+ mMainExecutor.flushAll();
+ // first transition finished
+ verify(mOrganizer, times(1)).finishTransition(eq(transitToken1), any(), any());
+ verify(mOrganizer, times(0)).finishTransition(eq(transitToken2), any(), any());
+ // But now the "queued" transition is running
+ assertEquals(1, mDefaultHandler.activeCount());
+
+ // runnable2 and runnable3 are still not executed because the second transition is still
+ // active.
+ verify(runnable2, times(0)).run();
+ verify(runnable3, times(0)).run();
+
+ mDefaultHandler.finishAll();
+ mMainExecutor.flushAll();
+ verify(mOrganizer, times(1)).finishTransition(eq(transitToken2), any(), any());
+
+ // runnable2 and runnable3 are executed after the second transition finishes because there
+ // are no other active transitions, runnable1 isn't executed again.
+ verify(runnable1, times(0)).run();
+ verify(runnable2, times(1)).run();
+ verify(runnable3, times(1)).run();
+
+ clearInvocations(runnable2);
+ clearInvocations(runnable3);
+
+ transitions.runOnIdle(runnable4);
+
+ // runnable4 is executed immediately because there are no active transitions, all other
+ // runnables aren't executed again.
+ verify(runnable1, times(0)).run();
+ verify(runnable2, times(0)).run();
+ verify(runnable3, times(0)).run();
+ verify(runnable4, times(1)).run();
+ }
+
class TransitionInfoBuilder {
final TransitionInfo mInfo;
@@ -749,7 +827,7 @@ public class ShellTransitionTests {
IWindowManager mockWM = mock(IWindowManager.class);
final IDisplayWindowListener[] displayListener = new IDisplayWindowListener[1];
try {
- doReturn(new int[] {DEFAULT_DISPLAY}).when(mockWM).registerDisplayWindowListener(any());
+ doReturn(new int[]{DEFAULT_DISPLAY}).when(mockWM).registerDisplayWindowListener(any());
} catch (RemoteException e) {
// No remote stuff happening, so this can't be hit
}