blob: 5617f1b6316b155d9e5d04c3909adcdd3c6532cc [file] [log] [blame]
/*
* Copyright (C) 2020 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.systemui.accessibility;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.WindowInsets.Type.displayCutout;
import static android.view.WindowInsets.Type.systemBars;
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK;
import static com.android.systemui.accessibility.MagnificationModeSwitch.DEFAULT_FADE_OUT_ANIMATION_DELAY_MS;
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;
import static junit.framework.Assert.assertNotNull;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Handler;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.Choreographer;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewPropertyAnimator;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.List;
@SmallTest
@FlakyTest(bugId = 188890599)
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
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 AccessibilityManager mAccessibilityManager;
@Mock
private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
private TestableWindowManager mWindowManager;
private ViewPropertyAnimator mViewPropertyAnimator;
private MagnificationModeSwitch mMagnificationModeSwitch;
private View.OnTouchListener mTouchListener;
private Runnable mFadeOutAnimation;
private MotionEventHelper mMotionEventHelper = new MotionEventHelper();
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
final WindowManager wm = mContext.getSystemService(WindowManager.class);
mWindowManager = spy(new TestableWindowManager(wm));
mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
mContext.addMockSystemService(Context.ACCESSIBILITY_SERVICE, mAccessibilityManager);
mSpyImageView = Mockito.spy(new ImageView(mContext));
mViewPropertyAnimator = Mockito.spy(mSpyImageView.animate());
resetAndStubMockImageViewAndAnimator();
doAnswer((invocation) -> {
mTouchListener = invocation.getArgument(0);
return null;
}).when(mSpyImageView).setOnTouchListener(
any(View.OnTouchListener.class));
doAnswer(invocation -> {
Choreographer.FrameCallback callback = invocation.getArgument(0);
callback.doFrame(0);
return null;
}).when(mSfVsyncFrameProvider).postFrameCallback(
any(Choreographer.FrameCallback.class));
mMagnificationModeSwitch = new MagnificationModeSwitch(mContext, mSpyImageView,
mSfVsyncFrameProvider);
assertNotNull(mTouchListener);
}
@After
public void tearDown() {
mFadeOutAnimation = null;
mMotionEventHelper.recycleEvents();
}
@Test
public void removeButton_buttonIsShowing_removeView() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
mMagnificationModeSwitch.removeButton();
verify(mWindowManager).removeView(mSpyImageView);
verify(mViewPropertyAnimator).cancel();
}
@Test
public void showFullscreenModeButton_addViewAndSetImageResource() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
verify(mSpyImageView).setImageResource(
getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN));
assertEquals(mSpyImageView, mWindowManager.getAttachedView());
assertShowFadingAnimation(FADE_IN_ALPHA);
assertShowFadingAnimation(FADE_OUT_ALPHA);
}
@Test
public void showButton_excludeSystemGestureArea() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
verify(mSpyImageView).setSystemGestureExclusionRects(any(List.class));
}
@Test
public void showMagnificationButton_setA11yTimeout_postDelayedAnimationWithA11yTimeout() {
final int a11yTimeout = 12345;
when(mAccessibilityManager.getRecommendedTimeoutMillis(anyInt(), anyInt())).thenReturn(
a11yTimeout);
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
verify(mAccessibilityManager).getRecommendedTimeoutMillis(
DEFAULT_FADE_OUT_ANIMATION_DELAY_MS, AccessibilityManager.FLAG_CONTENT_ICONS
| AccessibilityManager.FLAG_CONTENT_CONTROLS);
verify(mSpyImageView).postOnAnimationDelayed(any(Runnable.class), eq((long) a11yTimeout));
}
@Test
public void showMagnificationButton_windowModeAndFadingOut_verifyAnimationEndAction() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
executeFadeOutAnimation();
// Verify the end action after fade-out.
final ArgumentCaptor<Runnable> endActionCaptor = ArgumentCaptor.forClass(Runnable.class);
verify(mViewPropertyAnimator).withEndAction(endActionCaptor.capture());
endActionCaptor.getValue().run();
verify(mViewPropertyAnimator).cancel();
verify(mWindowManager).removeView(mSpyImageView);
}
@Test
public void onDensityChanged_buttonIsShowing_updateResourcesAndLayout() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
resetAndStubMockImageViewAndAnimator();
mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY);
InOrder inOrder = Mockito.inOrder(mWindowManager);
inOrder.verify(mWindowManager).updateViewLayout(eq(mSpyImageView), any());
inOrder.verify(mWindowManager).removeView(eq(mSpyImageView));
inOrder.verify(mWindowManager).addView(eq(mSpyImageView), any());
verify(mSpyImageView).setSystemGestureExclusionRects(any(List.class));
}
@Test
public void onApplyWindowInsetsWithBoundsChange_buttonIsShowing_updateLayoutPosition() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
mMagnificationModeSwitch.mDraggableWindowBounds.inset(10, 10);
mSpyImageView.onApplyWindowInsets(WindowInsets.CONSUMED);
verify(mWindowManager).updateViewLayout(eq(mSpyImageView),
any(WindowManager.LayoutParams.class));
assertLayoutPosition(/* toLeftScreenEdge= */ false);
}
@Test
public void onSystemBarsInsetsChanged_buttonIsShowing_draggableBoundsChanged() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
final Rect oldDraggableBounds = new Rect(mMagnificationModeSwitch.mDraggableWindowBounds);
mWindowManager.setWindowInsets(new WindowInsets.Builder()
.setInsetsIgnoringVisibility(systemBars(), Insets.of(0, 20, 0, 20))
.build());
mSpyImageView.onApplyWindowInsets(WindowInsets.CONSUMED);
assertNotEquals(oldDraggableBounds, mMagnificationModeSwitch.mDraggableWindowBounds);
}
@Test
public void onDisplayCutoutInsetsChanged_buttonIsShowing_draggableBoundsChanged() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
final Rect oldDraggableBounds = new Rect(mMagnificationModeSwitch.mDraggableWindowBounds);
mWindowManager.setWindowInsets(new WindowInsets.Builder()
.setInsetsIgnoringVisibility(displayCutout(), Insets.of(20, 30, 20, 30))
.build());
mSpyImageView.onApplyWindowInsets(WindowInsets.CONSUMED);
assertNotEquals(oldDraggableBounds, mMagnificationModeSwitch.mDraggableWindowBounds);
}
@Test
public void onWindowBoundsChanged_buttonIsShowing_draggableBoundsChanged() {
mWindowManager.setWindowBounds(new Rect(0, 0, 800, 1000));
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
final Rect oldDraggableBounds = new Rect(mMagnificationModeSwitch.mDraggableWindowBounds);
mWindowManager.setWindowBounds(new Rect(0, 0, 1000, 800));
mSpyImageView.onApplyWindowInsets(WindowInsets.CONSUMED);
assertNotEquals(oldDraggableBounds, mMagnificationModeSwitch.mDraggableWindowBounds);
}
@Test
public void onDraggingGestureFinish_buttonIsShowing_stickToRightEdge() {
final int windowHalfWidth =
mWindowManager.getCurrentWindowMetrics().getBounds().width() / 2;
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
// Drag button to right side on screen
final int offset = ViewConfiguration.get(mContext).getScaledTouchSlop() + 10;
final long downTime = SystemClock.uptimeMillis();
mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
downTime, 0, ACTION_DOWN, 100, 100));
mTouchListener.onTouch(mSpyImageView,
obtainMotionEvent(downTime, downTime, ACTION_MOVE, windowHalfWidth - offset, 100));
mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
downTime, downTime, ACTION_UP, windowHalfWidth - offset, 100));
assertLayoutPosition(/* toLeftScreenEdge= */false);
}
@Test
public void performSingleTap_fullscreenMode_removeViewAndChangeSettingsValue() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
resetAndStubMockImageViewAndAnimator();
// Perform a single-tap
final long downTime = SystemClock.uptimeMillis();
mTouchListener.onTouch(mSpyImageView,
obtainMotionEvent(downTime, 0, ACTION_DOWN, 100, 100));
resetAndStubMockImageViewAndAnimator();
mTouchListener.onTouch(mSpyImageView,
obtainMotionEvent(downTime, downTime, ACTION_UP, 100, 100));
verifyTapAction(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
}
@Test
public void sendDownEvent_fullscreenMode_fadeOutAnimationIsNull() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
resetAndStubMockImageViewAndAnimator();
final long downTime = SystemClock.uptimeMillis();
mTouchListener.onTouch(mSpyImageView,
obtainMotionEvent(downTime, 0, ACTION_DOWN, 100, 100));
assertNull(mFadeOutAnimation);
}
@Test
public void sendDownEvent_fullscreenModeAndFadingOut_cancelAnimation() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
executeFadeOutAnimation();
resetAndStubMockImageViewAndAnimator();
final long downTime = SystemClock.uptimeMillis();
mTouchListener.onTouch(mSpyImageView,
obtainMotionEvent(downTime, 0, ACTION_DOWN, 100, 100));
verify(mViewPropertyAnimator).cancel();
}
@Test
public void performDragging_showMagnificationButton_updateViewLayout() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
resetAndStubMockImageViewAndAnimator();
final int previousMode = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0, UserHandle.USER_CURRENT);
// Perform dragging
final int offset = ViewConfiguration.get(mContext).getScaledTouchSlop() + 10;
final long downTime = SystemClock.uptimeMillis();
mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
downTime, 0, ACTION_DOWN, 100, 100));
mTouchListener.onTouch(mSpyImageView,
obtainMotionEvent(downTime, downTime, ACTION_MOVE, 100 + offset,
100));
verify(mWindowManager).updateViewLayout(eq(mSpyImageView),
any(WindowManager.LayoutParams.class));
resetAndStubMockImageViewAndAnimator();
mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
downTime, downTime, ACTION_UP, 100 + offset, 100));
assertModeUnchanged(previousMode);
assertShowFadingAnimation(FADE_OUT_ALPHA);
}
@Test
public void performSingleTapActionCanceled_showButtonAnimation() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
resetAndStubMockImageViewAndAnimator();
final int previousMode = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
final long downTime = SystemClock.uptimeMillis();
mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
downTime, downTime, ACTION_DOWN, 100, 100));
resetAndStubMockImageViewAndAnimator();
mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
downTime, downTime, ACTION_CANCEL, 100, 100));
assertModeUnchanged(previousMode);
assertShowFadingAnimation(FADE_OUT_ALPHA);
}
@Test
public void performDraggingActionCanceled_showButtonAnimation() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
resetAndStubMockImageViewAndAnimator();
final int previousMode = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
// Perform dragging
final long downTime = SystemClock.uptimeMillis();
final int offset = ViewConfiguration.get(mContext).getScaledTouchSlop() + 10;
mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
0, 0, ACTION_DOWN, 100, 100));
mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
downTime, downTime, ACTION_MOVE, 100 + offset, 100));
resetAndStubMockImageViewAndAnimator();
mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(
downTime, downTime, ACTION_CANCEL, 100 + offset, 100));
assertModeUnchanged(previousMode);
assertShowFadingAnimation(FADE_OUT_ALPHA);
}
@Test
public void initializeA11yNode_showWindowModeButton_expectedValues() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
final AccessibilityNodeInfo nodeInfo = new AccessibilityNodeInfo();
mSpyImageView.onInitializeAccessibilityNodeInfo(nodeInfo);
assertEquals(mContext.getString(R.string.magnification_mode_switch_description),
nodeInfo.getContentDescription());
assertEquals(mContext.getString(R.string.magnification_mode_switch_state_window),
nodeInfo.getStateDescription());
assertThat(nodeInfo.getActionList(),
hasItems(new AccessibilityNodeInfo.AccessibilityAction(
ACTION_CLICK.getId(), mContext.getResources().getString(
R.string.magnification_mode_switch_click_label))));
assertThat(nodeInfo.getActionList(),
hasItems(new AccessibilityNodeInfo.AccessibilityAction(
R.id.accessibility_action_move_up, mContext.getResources().getString(
R.string.accessibility_control_move_up))));
assertThat(nodeInfo.getActionList(),
hasItems(new AccessibilityNodeInfo.AccessibilityAction(
R.id.accessibility_action_move_down, mContext.getResources().getString(
R.string.accessibility_control_move_down))));
assertThat(nodeInfo.getActionList(),
hasItems(new AccessibilityNodeInfo.AccessibilityAction(
R.id.accessibility_action_move_left, mContext.getResources().getString(
R.string.accessibility_control_move_left))));
assertThat(nodeInfo.getActionList(),
hasItems(new AccessibilityNodeInfo.AccessibilityAction(
R.id.accessibility_action_move_right, mContext.getResources().getString(
R.string.accessibility_control_move_right))));
}
@Test
public void performClickA11yActions_showWindowModeButton_verifyTapAction() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
resetAndStubMockImageViewAndAnimator();
mSpyImageView.performAccessibilityAction(
ACTION_CLICK.getId(), null);
verifyTapAction(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
}
@Test
public void performMoveLeftA11yAction_showButtonAtRightEdge_moveToLeftEdge() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
mSpyImageView.performAccessibilityAction(
R.id.accessibility_action_move_left, null);
assertLayoutPosition(/* toLeftScreenEdge= */true);
}
@Test
public void showButton_showFadeOutAnimation_fadeOutAnimationCanceled() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
assertShowFadingAnimation(FADE_OUT_ALPHA);
resetAndStubMockImageViewAndAnimator();
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
verify(mViewPropertyAnimator).cancel();
assertEquals(1f, mSpyImageView.getAlpha());
assertShowFadingAnimation(FADE_OUT_ALPHA);
}
@Test
public void showButton_hasAccessibilityWindowTitle() {
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
final WindowManager.LayoutParams layoutPrams =
mWindowManager.getLayoutParamsFromAttachedView();
assertNotNull(layoutPrams);
assertEquals(getContext().getResources().getString(
com.android.internal.R.string.android_system_label),
layoutPrams.accessibilityTitle);
}
@Test
public void onLocaleChanged_buttonIsShowing_updateA11yWindowTitle() {
final String newA11yWindowTitle = "new a11y window title";
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
getContext().getOrCreateTestableResources().addOverride(
com.android.internal.R.string.android_system_label, newA11yWindowTitle);
mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_LOCALE);
final WindowManager.LayoutParams layoutParams =
mWindowManager.getLayoutParamsFromAttachedView();
assertNotNull(layoutParams);
assertEquals(newA11yWindowTitle, layoutParams.accessibilityTitle);
}
@Test
public void onRotationChanged_buttonIsShowing_expectedYPosition() {
final Rect windowBounds = mWindowManager.getCurrentWindowMetrics().getBounds();
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
final Rect oldDraggableBounds = new Rect(mMagnificationModeSwitch.mDraggableWindowBounds);
final float windowHeightFraction =
(float) (mWindowManager.getLayoutParamsFromAttachedView().y
- oldDraggableBounds.top) / oldDraggableBounds.height();
// The window bounds and the draggable bounds are changed due to the rotation change.
final Rect newWindowBounds = new Rect(0, 0, windowBounds.height(), windowBounds.width());
mWindowManager.setWindowBounds(newWindowBounds);
mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_ORIENTATION);
int expectedY = (int) (windowHeightFraction
* mMagnificationModeSwitch.mDraggableWindowBounds.height())
+ mMagnificationModeSwitch.mDraggableWindowBounds.top;
assertEquals(
"The Y position does not keep the same height ratio after the rotation changed.",
expectedY, mWindowManager.getLayoutParamsFromAttachedView().y);
}
private void assertModeUnchanged(int expectedMode) {
final int actualMode = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
assertEquals(expectedMode, actualMode);
}
private void assertShowFadingAnimation(float alpha) {
final 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());
}
resetAndStubMockAnimator();
runnableCaptor.getValue().run();
verify(mViewPropertyAnimator).setDuration(eq(FADING_ANIMATION_DURATION_MS));
verify(mViewPropertyAnimator).alpha(alpha);
verify(mViewPropertyAnimator).start();
}
private void resetAndStubMockImageViewAndAnimator() {
resetAndStubMockAnimator();
Mockito.reset(mSpyImageView);
final Handler handler = mock(Handler.class);
when(mSpyImageView.getHandler()).thenReturn(handler);
doAnswer(invocation -> {
final Runnable runnable = invocation.getArgument(0);
runnable.run();
return null;
}).when(handler).post(any(Runnable.class));
doAnswer(invocation -> {
final Runnable runnable = invocation.getArgument(0);
runnable.run();
return null;
}).when(mSpyImageView).post(any(Runnable.class));
doReturn(mViewPropertyAnimator).when(mSpyImageView).animate();
doAnswer((invocation) -> {
mFadeOutAnimation = invocation.getArgument(0);
return null;
}).when(mSpyImageView).postOnAnimationDelayed(any(Runnable.class), anyLong());
doAnswer((invocation) -> {
if (mFadeOutAnimation == invocation.getArgument(0)) {
mFadeOutAnimation = null;
}
return null;
}).when(mSpyImageView).removeCallbacks(any(Runnable.class));
}
private void resetAndStubMockAnimator() {
Mockito.reset(mViewPropertyAnimator);
doNothing().when(mViewPropertyAnimator).start();
}
/**
* Verifies the tap behaviour including the image of the button and the magnification mode.
*
* @param expectedMode the expected mode after tapping
*/
private void verifyTapAction(int expectedMode) {
verify(mViewPropertyAnimator).cancel();
verify(mSpyImageView).setImageResource(
getIconResId(expectedMode));
verify(mWindowManager).removeView(mSpyImageView);
final int actualMode = Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0, UserHandle.USER_CURRENT);
assertEquals(expectedMode, actualMode);
}
private MotionEvent obtainMotionEvent(long downTime, long eventTime, int action, float x,
float y) {
return mMotionEventHelper.obtainMotionEvent(downTime, eventTime, action, x, y);
}
private void executeFadeOutAnimation() {
assertNotNull(mFadeOutAnimation);
mFadeOutAnimation.run();
mFadeOutAnimation = null;
}
private void assertLayoutPosition(boolean toLeftScreenEdge) {
final int expectedX =
toLeftScreenEdge ? mMagnificationModeSwitch.mDraggableWindowBounds.left
: mMagnificationModeSwitch.mDraggableWindowBounds.right;
final int expectedY = mMagnificationModeSwitch.mDraggableWindowBounds.bottom;
final WindowManager.LayoutParams layoutParams =
mWindowManager.getLayoutParamsFromAttachedView();
assertNotNull(layoutParams);
assertEquals(expectedX, layoutParams.x);
assertEquals(expectedY, layoutParams.y);
}
}