Loading packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java +32 −14 Original line number Diff line number Diff line Loading @@ -46,9 +46,15 @@ import com.android.systemui.R; */ class MagnificationModeSwitch { private static final int DURATION_MS = 5000; private static final int START_DELAY_MS = 3000; private final Runnable mAnimationTask; @VisibleForTesting static final long FADING_ANIMATION_DURATION_MS = 300; private static final int DEFAULT_FADE_OUT_ANIMATION_DELAY_MS = 3000; // The button visible duration starting from the last showButton() called. private int mVisibleDuration = DEFAULT_FADE_OUT_ANIMATION_DELAY_MS; private final Runnable mFadeInAnimationTask; private final Runnable mFadeOutAnimationTask; @VisibleForTesting boolean mIsFadeOutAnimating = false; private final Context mContext; private final WindowManager mWindowManager; Loading Loading @@ -100,12 +106,19 @@ class MagnificationModeSwitch { } }); mAnimationTask = () -> { mFadeInAnimationTask = () -> { mImageView.animate() .alpha(1f) .setDuration(FADING_ANIMATION_DURATION_MS) .start(); }; mFadeOutAnimationTask = () -> { mImageView.animate() .alpha(0f) .setDuration(DURATION_MS) .setDuration(FADING_ANIMATION_DURATION_MS) .withEndAction(() -> removeButton()) .start(); mIsFadeOutAnimating = true; }; } Loading @@ -128,7 +141,6 @@ class MagnificationModeSwitch { } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mImageView.setAlpha(1.0f); mImageView.animate().cancel(); mLastDown.set(event.getRawX(), event.getRawY()); mLastDrag.set(event.getRawX(), event.getRawY()); Loading Loading @@ -169,9 +181,13 @@ class MagnificationModeSwitch { if (!mIsVisible) { return; } // Reset button status. mImageView.removeCallbacks(mFadeInAnimationTask); mImageView.removeCallbacks(mFadeOutAnimationTask); mImageView.animate().cancel(); mIsFadeOutAnimating = false; mImageView.setAlpha(0f); mWindowManager.removeView(mImageView); // Reset button status. mIsVisible = false; mParams.x = 0; mParams.y = 0; Loading @@ -185,14 +201,15 @@ class MagnificationModeSwitch { if (!mIsVisible) { mWindowManager.addView(mImageView, mParams); mIsVisible = true; mImageView.postOnAnimation(mFadeInAnimationTask); } mImageView.setAlpha(1.0f); // TODO(b/143852371): use accessibility timeout as a delay. // Dismiss the magnification switch button after the button is displayed for a period of // time. if (mIsFadeOutAnimating) { mImageView.animate().cancel(); mImageView.removeCallbacks(mAnimationTask); mImageView.postDelayed(mAnimationTask, START_DELAY_MS); mImageView.setAlpha(1f); } // Refresh the time slot of the fade-out task whenever this method is called. mImageView.removeCallbacks(mFadeOutAnimationTask); mImageView.postOnAnimationDelayed(mFadeOutAnimationTask, mVisibleDuration); } void onConfigurationChanged(int configDiff) { Loading Loading @@ -222,6 +239,7 @@ class MagnificationModeSwitch { imageView.setClickable(true); imageView.setFocusable(true); imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); imageView.setAlpha(0f); return imageView; } Loading packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java +53 −38 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.view.MotionEvent.ACTION_MOVE; import static android.view.MotionEvent.ACTION_UP; import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK; import static com.android.systemui.accessibility.MagnificationModeSwitch.FADING_ANIMATION_DURATION_MS; import static com.android.systemui.accessibility.MagnificationModeSwitch.getIconResId; import static junit.framework.Assert.assertEquals; Loading @@ -35,7 +36,6 @@ import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading Loading @@ -69,6 +69,9 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) public class MagnificationModeSwitchTest extends SysuiTestCase { private static final float FADE_IN_ALPHA = 1f; private static final float FADE_OUT_ALPHA = 0f; private ImageView mSpyImageView; @Mock private WindowManager mWindowManager; Loading @@ -87,49 +90,47 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { ).when(mWindowManager).getMaximumWindowMetrics(); mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager); mSpyImageView = Mockito.spy(new ImageView(mContext)); doAnswer(invocation -> null).when(mSpyImageView).setOnTouchListener( mTouchListenerCaptor.capture()); initMockImageViewAndAnimator(); resetMockImageViewAndAnimator(); mMagnificationModeSwitch = new MagnificationModeSwitch(mContext, mSpyImageView); } @Test public void removeButton_removeView() { public void removeButton_buttonIsShowing_removeView() { mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); mMagnificationModeSwitch.removeButton(); verify(mWindowManager).removeView(mSpyImageView); // First invocation is in showButton. verify(mViewPropertyAnimator, times(2)).cancel(); verify(mViewPropertyAnimator).cancel(); } @Test public void showWindowModeButton_fullscreenMode_addViewAndSetImageResource() { mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); verify(mSpyImageView).setAlpha(1.0f); verify(mSpyImageView).setImageResource( getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)); assertShowButtonAnimation(); assertShowFadingAnimation(FADE_IN_ALPHA); assertShowFadingAnimation(FADE_OUT_ALPHA); ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class); verify(mViewPropertyAnimator).withEndAction(captor.capture()); verify(mWindowManager).addView(eq(mSpyImageView), any(WindowManager.LayoutParams.class)); captor.getValue().run(); // First invocation is in showButton. verify(mViewPropertyAnimator, times(2)).cancel(); verify(mViewPropertyAnimator).cancel(); verify(mWindowManager).removeView(mSpyImageView); } @Test public void onConfigurationChanged_setImageResource() { public void onConfigurationChanged_buttonIsShowing_setImageResource() { mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); resetMockImageViewAndAnimator(); mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY); verify(mSpyImageView, times(2)).setImageResource( verify(mSpyImageView).setImageResource( getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN)); } Loading Loading @@ -162,7 +163,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0); listener.onTouch(mSpyImageView, MotionEvent.obtain( 0, 0, ACTION_DOWN, 100, 100, 0)); verify(mSpyImageView).setAlpha(1.0f); verify(mViewPropertyAnimator).cancel(); listener.onTouch(mSpyImageView, MotionEvent.obtain( Loading @@ -173,9 +173,8 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { resetMockImageViewAndAnimator(); listener.onTouch(mSpyImageView, MotionEvent.obtain( 0, ViewConfiguration.getTapTimeout() + 10, ACTION_UP, 100 + offset, 100, 0)); verify(mSpyImageView).setAlpha(1.0f); assertModeUnchanged(previousMode); assertShowButtonAnimation(); assertShowFadingAnimation(FADE_OUT_ALPHA); } @Test Loading @@ -193,9 +192,8 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { resetMockImageViewAndAnimator(); listener.onTouch(mSpyImageView, MotionEvent.obtain( 0, ViewConfiguration.getTapTimeout(), ACTION_CANCEL, 100, 100, 0)); verify(mSpyImageView).setAlpha(1.0f); assertModeUnchanged(previousMode); assertShowButtonAnimation(); assertShowFadingAnimation(FADE_OUT_ALPHA); } @Test Loading @@ -216,9 +214,8 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { resetMockImageViewAndAnimator(); listener.onTouch(mSpyImageView, MotionEvent.obtain( 0, ViewConfiguration.getTapTimeout(), ACTION_CANCEL, 100 + offset, 100, 0)); verify(mSpyImageView).setAlpha(1.0f); assertModeUnchanged(previousMode); assertShowButtonAnimation(); assertShowFadingAnimation(FADE_OUT_ALPHA); } @Test Loading Loading @@ -249,37 +246,55 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { verifyTapAction(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); } @Test public void showButton_showFadeOutAnimation_fadeOutAnimationCanceled() { mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); assertShowFadingAnimation(FADE_OUT_ALPHA); resetMockImageViewAndAnimator(); mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); verify(mViewPropertyAnimator).cancel(); assertEquals(1f, mSpyImageView.getAlpha()); assertShowFadingAnimation(FADE_OUT_ALPHA); } private void assertModeUnchanged(int expectedMode) { final int actualMode = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0); assertEquals(expectedMode, actualMode); } private void assertShowButtonAnimation() { verify(mViewPropertyAnimator).cancel(); verify(mViewPropertyAnimator).setDuration(anyLong()); verify(mViewPropertyAnimator).alpha(anyFloat()); private void assertShowFadingAnimation(float alpha) { ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class); if (alpha == FADE_IN_ALPHA) { // Fade-in verify(mSpyImageView).postOnAnimation(runnableCaptor.capture()); } else { // Fade-out verify(mSpyImageView).postOnAnimationDelayed(runnableCaptor.capture(), anyLong()); } resetMockAnimator(); runnableCaptor.getValue().run(); verify(mViewPropertyAnimator).setDuration(eq(FADING_ANIMATION_DURATION_MS)); verify(mViewPropertyAnimator).alpha(alpha); verify(mViewPropertyAnimator).start(); } private void initMockImageViewAndAnimator() { private void resetMockImageViewAndAnimator() { Mockito.reset(mSpyImageView); doAnswer(invocation -> null).when(mSpyImageView).setOnTouchListener( mTouchListenerCaptor.capture()); resetMockAnimator(); } private void resetMockAnimator() { Mockito.reset(mViewPropertyAnimator); when(mViewPropertyAnimator.setDuration(anyLong())).thenReturn(mViewPropertyAnimator); when(mViewPropertyAnimator.alpha(anyFloat())).thenReturn(mViewPropertyAnimator); when(mViewPropertyAnimator.withEndAction(any(Runnable.class))).thenReturn( mViewPropertyAnimator); when(mSpyImageView.animate()).thenReturn(mViewPropertyAnimator); doAnswer(invocation -> { Runnable run = invocation.getArgument(0); run.run(); return null; }).when(mSpyImageView).postDelayed(any(), anyLong()); } private void resetMockImageViewAndAnimator() { Mockito.reset(mViewPropertyAnimator); Mockito.reset(mSpyImageView); initMockImageViewAndAnimator(); } /** Loading Loading
packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java +32 −14 Original line number Diff line number Diff line Loading @@ -46,9 +46,15 @@ import com.android.systemui.R; */ class MagnificationModeSwitch { private static final int DURATION_MS = 5000; private static final int START_DELAY_MS = 3000; private final Runnable mAnimationTask; @VisibleForTesting static final long FADING_ANIMATION_DURATION_MS = 300; private static final int DEFAULT_FADE_OUT_ANIMATION_DELAY_MS = 3000; // The button visible duration starting from the last showButton() called. private int mVisibleDuration = DEFAULT_FADE_OUT_ANIMATION_DELAY_MS; private final Runnable mFadeInAnimationTask; private final Runnable mFadeOutAnimationTask; @VisibleForTesting boolean mIsFadeOutAnimating = false; private final Context mContext; private final WindowManager mWindowManager; Loading Loading @@ -100,12 +106,19 @@ class MagnificationModeSwitch { } }); mAnimationTask = () -> { mFadeInAnimationTask = () -> { mImageView.animate() .alpha(1f) .setDuration(FADING_ANIMATION_DURATION_MS) .start(); }; mFadeOutAnimationTask = () -> { mImageView.animate() .alpha(0f) .setDuration(DURATION_MS) .setDuration(FADING_ANIMATION_DURATION_MS) .withEndAction(() -> removeButton()) .start(); mIsFadeOutAnimating = true; }; } Loading @@ -128,7 +141,6 @@ class MagnificationModeSwitch { } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mImageView.setAlpha(1.0f); mImageView.animate().cancel(); mLastDown.set(event.getRawX(), event.getRawY()); mLastDrag.set(event.getRawX(), event.getRawY()); Loading Loading @@ -169,9 +181,13 @@ class MagnificationModeSwitch { if (!mIsVisible) { return; } // Reset button status. mImageView.removeCallbacks(mFadeInAnimationTask); mImageView.removeCallbacks(mFadeOutAnimationTask); mImageView.animate().cancel(); mIsFadeOutAnimating = false; mImageView.setAlpha(0f); mWindowManager.removeView(mImageView); // Reset button status. mIsVisible = false; mParams.x = 0; mParams.y = 0; Loading @@ -185,14 +201,15 @@ class MagnificationModeSwitch { if (!mIsVisible) { mWindowManager.addView(mImageView, mParams); mIsVisible = true; mImageView.postOnAnimation(mFadeInAnimationTask); } mImageView.setAlpha(1.0f); // TODO(b/143852371): use accessibility timeout as a delay. // Dismiss the magnification switch button after the button is displayed for a period of // time. if (mIsFadeOutAnimating) { mImageView.animate().cancel(); mImageView.removeCallbacks(mAnimationTask); mImageView.postDelayed(mAnimationTask, START_DELAY_MS); mImageView.setAlpha(1f); } // Refresh the time slot of the fade-out task whenever this method is called. mImageView.removeCallbacks(mFadeOutAnimationTask); mImageView.postOnAnimationDelayed(mFadeOutAnimationTask, mVisibleDuration); } void onConfigurationChanged(int configDiff) { Loading Loading @@ -222,6 +239,7 @@ class MagnificationModeSwitch { imageView.setClickable(true); imageView.setFocusable(true); imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); imageView.setAlpha(0f); return imageView; } Loading
packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java +53 −38 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.view.MotionEvent.ACTION_MOVE; import static android.view.MotionEvent.ACTION_UP; import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK; import static com.android.systemui.accessibility.MagnificationModeSwitch.FADING_ANIMATION_DURATION_MS; import static com.android.systemui.accessibility.MagnificationModeSwitch.getIconResId; import static junit.framework.Assert.assertEquals; Loading @@ -35,7 +36,6 @@ import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading Loading @@ -69,6 +69,9 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) public class MagnificationModeSwitchTest extends SysuiTestCase { private static final float FADE_IN_ALPHA = 1f; private static final float FADE_OUT_ALPHA = 0f; private ImageView mSpyImageView; @Mock private WindowManager mWindowManager; Loading @@ -87,49 +90,47 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { ).when(mWindowManager).getMaximumWindowMetrics(); mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager); mSpyImageView = Mockito.spy(new ImageView(mContext)); doAnswer(invocation -> null).when(mSpyImageView).setOnTouchListener( mTouchListenerCaptor.capture()); initMockImageViewAndAnimator(); resetMockImageViewAndAnimator(); mMagnificationModeSwitch = new MagnificationModeSwitch(mContext, mSpyImageView); } @Test public void removeButton_removeView() { public void removeButton_buttonIsShowing_removeView() { mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); mMagnificationModeSwitch.removeButton(); verify(mWindowManager).removeView(mSpyImageView); // First invocation is in showButton. verify(mViewPropertyAnimator, times(2)).cancel(); verify(mViewPropertyAnimator).cancel(); } @Test public void showWindowModeButton_fullscreenMode_addViewAndSetImageResource() { mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); verify(mSpyImageView).setAlpha(1.0f); verify(mSpyImageView).setImageResource( getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)); assertShowButtonAnimation(); assertShowFadingAnimation(FADE_IN_ALPHA); assertShowFadingAnimation(FADE_OUT_ALPHA); ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class); verify(mViewPropertyAnimator).withEndAction(captor.capture()); verify(mWindowManager).addView(eq(mSpyImageView), any(WindowManager.LayoutParams.class)); captor.getValue().run(); // First invocation is in showButton. verify(mViewPropertyAnimator, times(2)).cancel(); verify(mViewPropertyAnimator).cancel(); verify(mWindowManager).removeView(mSpyImageView); } @Test public void onConfigurationChanged_setImageResource() { public void onConfigurationChanged_buttonIsShowing_setImageResource() { mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); resetMockImageViewAndAnimator(); mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY); verify(mSpyImageView, times(2)).setImageResource( verify(mSpyImageView).setImageResource( getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN)); } Loading Loading @@ -162,7 +163,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0); listener.onTouch(mSpyImageView, MotionEvent.obtain( 0, 0, ACTION_DOWN, 100, 100, 0)); verify(mSpyImageView).setAlpha(1.0f); verify(mViewPropertyAnimator).cancel(); listener.onTouch(mSpyImageView, MotionEvent.obtain( Loading @@ -173,9 +173,8 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { resetMockImageViewAndAnimator(); listener.onTouch(mSpyImageView, MotionEvent.obtain( 0, ViewConfiguration.getTapTimeout() + 10, ACTION_UP, 100 + offset, 100, 0)); verify(mSpyImageView).setAlpha(1.0f); assertModeUnchanged(previousMode); assertShowButtonAnimation(); assertShowFadingAnimation(FADE_OUT_ALPHA); } @Test Loading @@ -193,9 +192,8 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { resetMockImageViewAndAnimator(); listener.onTouch(mSpyImageView, MotionEvent.obtain( 0, ViewConfiguration.getTapTimeout(), ACTION_CANCEL, 100, 100, 0)); verify(mSpyImageView).setAlpha(1.0f); assertModeUnchanged(previousMode); assertShowButtonAnimation(); assertShowFadingAnimation(FADE_OUT_ALPHA); } @Test Loading @@ -216,9 +214,8 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { resetMockImageViewAndAnimator(); listener.onTouch(mSpyImageView, MotionEvent.obtain( 0, ViewConfiguration.getTapTimeout(), ACTION_CANCEL, 100 + offset, 100, 0)); verify(mSpyImageView).setAlpha(1.0f); assertModeUnchanged(previousMode); assertShowButtonAnimation(); assertShowFadingAnimation(FADE_OUT_ALPHA); } @Test Loading Loading @@ -249,37 +246,55 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { verifyTapAction(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); } @Test public void showButton_showFadeOutAnimation_fadeOutAnimationCanceled() { mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); assertShowFadingAnimation(FADE_OUT_ALPHA); resetMockImageViewAndAnimator(); mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); verify(mViewPropertyAnimator).cancel(); assertEquals(1f, mSpyImageView.getAlpha()); assertShowFadingAnimation(FADE_OUT_ALPHA); } private void assertModeUnchanged(int expectedMode) { final int actualMode = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0); assertEquals(expectedMode, actualMode); } private void assertShowButtonAnimation() { verify(mViewPropertyAnimator).cancel(); verify(mViewPropertyAnimator).setDuration(anyLong()); verify(mViewPropertyAnimator).alpha(anyFloat()); private void assertShowFadingAnimation(float alpha) { ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class); if (alpha == FADE_IN_ALPHA) { // Fade-in verify(mSpyImageView).postOnAnimation(runnableCaptor.capture()); } else { // Fade-out verify(mSpyImageView).postOnAnimationDelayed(runnableCaptor.capture(), anyLong()); } resetMockAnimator(); runnableCaptor.getValue().run(); verify(mViewPropertyAnimator).setDuration(eq(FADING_ANIMATION_DURATION_MS)); verify(mViewPropertyAnimator).alpha(alpha); verify(mViewPropertyAnimator).start(); } private void initMockImageViewAndAnimator() { private void resetMockImageViewAndAnimator() { Mockito.reset(mSpyImageView); doAnswer(invocation -> null).when(mSpyImageView).setOnTouchListener( mTouchListenerCaptor.capture()); resetMockAnimator(); } private void resetMockAnimator() { Mockito.reset(mViewPropertyAnimator); when(mViewPropertyAnimator.setDuration(anyLong())).thenReturn(mViewPropertyAnimator); when(mViewPropertyAnimator.alpha(anyFloat())).thenReturn(mViewPropertyAnimator); when(mViewPropertyAnimator.withEndAction(any(Runnable.class))).thenReturn( mViewPropertyAnimator); when(mSpyImageView.animate()).thenReturn(mViewPropertyAnimator); doAnswer(invocation -> { Runnable run = invocation.getArgument(0); run.run(); return null; }).when(mSpyImageView).postDelayed(any(), anyLong()); } private void resetMockImageViewAndAnimator() { Mockito.reset(mViewPropertyAnimator); Mockito.reset(mSpyImageView); initMockImageViewAndAnimator(); } /** Loading