diff options
10 files changed, 443 insertions, 219 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java index bf09975bb034..782cd29b0179 100644 --- a/packages/SystemUI/src/com/android/systemui/Prefs.java +++ b/packages/SystemUI/src/com/android/systemui/Prefs.java @@ -74,7 +74,8 @@ public final class Prefs { Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, Key.HAS_SEEN_REVERSE_BOTTOM_SHEET, Key.CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT, - Key.HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP + Key.HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP, + Key.ACCESSIBILITY_FLOATING_MENU_POSITION }) // TODO: annotate these with their types so {@link PrefsCommandLine} can know how to set them public @interface Key { @@ -125,6 +126,7 @@ public final class Prefs { String CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT = "ControlsStructureSwipeTooltipCount"; String HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP = "HasSeenAccessibilityFloatingMenuDockTooltip"; + String ACCESSIBILITY_FLOATING_MENU_POSITION = "AccessibilityFloatingMenuPosition"; } public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java index ee6276813512..47f373920b90 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenu.java @@ -28,12 +28,16 @@ import static com.android.systemui.Prefs.Key.HAS_SEEN_ACCESSIBILITY_FLOATING_MEN import static com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuView.ShapeType; import static com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuView.SizeType; +import android.annotation.FloatRange; import android.content.Context; import android.database.ContentObserver; import android.os.Handler; import android.os.Looper; import android.os.UserHandle; import android.provider.Settings; +import android.text.TextUtils; + +import androidx.annotation.NonNull; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Prefs; @@ -44,7 +48,13 @@ import com.android.systemui.Prefs; public class AccessibilityFloatingMenu implements IAccessibilityFloatingMenu { private static final int DEFAULT_FADE_EFFECT_IS_ENABLED = 1; private static final int DEFAULT_MIGRATION_TOOLTIP_PROMPT_IS_DISABLED = 0; + @FloatRange(from = 0.0, to = 1.0) private static final float DEFAULT_OPACITY_VALUE = 0.55f; + @FloatRange(from = 0.0, to = 1.0) + private static final float DEFAULT_POSITION_X_PERCENT = 1.0f; + @FloatRange(from = 0.0, to = 1.0) + private static final float DEFAULT_POSITION_Y_PERCENT = 0.8f; + private final Context mContext; private final AccessibilityFloatingMenuView mMenuView; private final MigrationTooltipView mMigrationTooltipView; @@ -85,7 +95,10 @@ public class AccessibilityFloatingMenu implements IAccessibilityFloatingMenu { }; public AccessibilityFloatingMenu(Context context) { - this(context, new AccessibilityFloatingMenuView(context)); + mContext = context; + mMenuView = new AccessibilityFloatingMenuView(context, getPosition(context)); + mMigrationTooltipView = new MigrationTooltipView(mContext, mMenuView); + mDockTooltipView = new DockTooltipView(mContext, mMenuView); } @VisibleForTesting @@ -113,7 +126,7 @@ public class AccessibilityFloatingMenu implements IAccessibilityFloatingMenu { getOpacityValue(mContext)); mMenuView.setSizeType(getSizeType(mContext)); mMenuView.setShapeType(getShapeType(mContext)); - mMenuView.setOnDragEndListener(this::showDockTooltipIfNecessary); + mMenuView.setOnDragEndListener(this::onDragEnd); showMigrationTooltipIfNecessary(); @@ -127,12 +140,25 @@ public class AccessibilityFloatingMenu implements IAccessibilityFloatingMenu { } mMenuView.hide(); + mMenuView.setOnDragEndListener(null); mMigrationTooltipView.hide(); mDockTooltipView.hide(); unregisterContentObservers(); } + @NonNull + private Position getPosition(Context context) { + final String absolutePositionString = Prefs.getString(context, + Prefs.Key.ACCESSIBILITY_FLOATING_MENU_POSITION, /* defaultValue= */ null); + + if (TextUtils.isEmpty(absolutePositionString)) { + return new Position(DEFAULT_POSITION_X_PERCENT, DEFAULT_POSITION_Y_PERCENT); + } else { + return Position.fromString(absolutePositionString); + } + } + // Migration tooltip was the android S feature. It's just used on the Android version from R // to S. In addition, it only shows once. private void showMigrationTooltipIfNecessary() { @@ -150,18 +176,28 @@ public class AccessibilityFloatingMenu implements IAccessibilityFloatingMenu { DEFAULT_MIGRATION_TOOLTIP_PROMPT_IS_DISABLED) == /* enabled */ 1; } + private void onDragEnd(Position position) { + savePosition(mContext, position); + showDockTooltipIfNecessary(mContext); + } + + private void savePosition(Context context, Position position) { + Prefs.putString(context, Prefs.Key.ACCESSIBILITY_FLOATING_MENU_POSITION, + position.toString()); + } + /** * Shows tooltip when user drags accessibility floating menu for the first time. */ - private void showDockTooltipIfNecessary() { - if (!Prefs.get(mContext).getBoolean( + private void showDockTooltipIfNecessary(Context context) { + if (!Prefs.get(context).getBoolean( HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP, false)) { // if the menu is an oval, the user has already dragged it out, so show the tooltip. if (mMenuView.isOvalShape()) { mDockTooltipView.show(); } - Prefs.putBoolean(mContext, HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP, true); + Prefs.putBoolean(context, HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP, true); } } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java index 259a9f7c6f3b..5bb55222e09b 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuView.java @@ -26,6 +26,7 @@ import static java.util.Objects.requireNonNull; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; +import android.annotation.FloatRange; import android.annotation.IntDef; import android.content.Context; import android.content.pm.ActivityInfo; @@ -85,7 +86,6 @@ public class AccessibilityFloatingMenuView extends FrameLayout private static final int FADE_EFFECT_DURATION_MS = 3000; private static final int SNAP_TO_LOCATION_DURATION_MS = 150; private static final int MIN_WINDOW_Y = 0; - private static final float LOCATION_Y_PERCENTAGE = 0.8f; private static final int ANIMATION_START_OFFSET = 600; private static final int ANIMATION_DURATION_MS = 600; @@ -97,7 +97,7 @@ public class AccessibilityFloatingMenuView extends FrameLayout private boolean mIsDragging = false; private boolean mImeVisibility; @Alignment - private int mAlignment = Alignment.RIGHT; + private int mAlignment; @SizeType private int mSizeType = SizeType.SMALL; @VisibleForTesting @@ -105,7 +105,7 @@ public class AccessibilityFloatingMenuView extends FrameLayout int mShapeType = ShapeType.OVAL; private int mTemporaryShapeType; @RadiusType - private int mRadiusType = RadiusType.LEFT_HALF_OVAL; + private int mRadiusType; private int mMargin; private int mPadding; private int mScreenHeight; @@ -118,7 +118,7 @@ public class AccessibilityFloatingMenuView extends FrameLayout private int mRelativeToPointerDownX; private int mRelativeToPointerDownY; private float mRadius; - private float mPercentageY = LOCATION_Y_PERCENTAGE; + private final Position mPosition; private float mSquareScaledTouchSlop; private final Configuration mLastConfiguration; private Optional<OnDragEndListener> mOnDragEndListener = Optional.empty(); @@ -182,25 +182,35 @@ public class AccessibilityFloatingMenuView extends FrameLayout interface OnDragEndListener { /** - * Invoked when the floating menu has dragged end. + * Called when a drag is completed. + * + * @param position Stores information about the position */ - void onDragEnd(); + void onDragEnd(Position position); } - public AccessibilityFloatingMenuView(Context context) { - this(context, new RecyclerView(context)); + public AccessibilityFloatingMenuView(Context context, @NonNull Position position) { + this(context, position, new RecyclerView(context)); } @VisibleForTesting - AccessibilityFloatingMenuView(Context context, + AccessibilityFloatingMenuView(Context context, @NonNull Position position, RecyclerView listView) { super(context); mListView = listView; mWindowManager = context.getSystemService(WindowManager.class); - mCurrentLayoutParams = createDefaultLayoutParams(); mAdapter = new AccessibilityTargetAdapter(mTargets); mUiHandler = createUiHandler(); + mPosition = position; + mAlignment = transformToAlignment(mPosition.getPercentageX()); + mRadiusType = (mAlignment == Alignment.RIGHT) + ? RadiusType.LEFT_HALF_OVAL + : RadiusType.RIGHT_HALF_OVAL; + + updateDimensions(); + + mCurrentLayoutParams = createDefaultLayoutParams(); mFadeOutAnimator = ValueAnimator.ofFloat(1.0f, mFadeOutValue); mFadeOutAnimator.setDuration(FADE_OUT_DURATION_MS); @@ -213,10 +223,11 @@ public class AccessibilityFloatingMenuView extends FrameLayout mDragAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - mAlignment = calculateCurrentAlignment(); - mPercentageY = calculateCurrentPercentageY(); + mPosition.update(transformCurrentPercentageXToEdge(), + calculateCurrentPercentageY()); + mAlignment = transformToAlignment(mPosition.getPercentageX()); - updateLocationWith(mAlignment, mPercentageY); + updateLocationWith(mPosition); updateInsetWith(getResources().getConfiguration().uiMode, mAlignment); @@ -227,13 +238,13 @@ public class AccessibilityFloatingMenuView extends FrameLayout fadeOut(); - mOnDragEndListener.ifPresent(OnDragEndListener::onDragEnd); + mOnDragEndListener.ifPresent( + onDragEndListener -> onDragEndListener.onDragEnd(mPosition)); } }); mLastConfiguration = new Configuration(getResources().getConfiguration()); - updateDimensions(); initListView(); updateStrokeWith(getResources().getConfiguration().uiMode, mAlignment); } @@ -423,7 +434,7 @@ public class AccessibilityFloatingMenuView extends FrameLayout updateRadiusWith(newSizeType, mRadiusType, mTargets.size()); // When the icon sized changed, the menu size and location will be impacted. - updateLocationWith(mAlignment, mPercentageY); + updateLocationWith(mPosition); updateScrollModeWith(hasExceededMaxLayoutHeight()); updateOffsetWith(mShapeType, mAlignment); setSystemGestureExclusion(); @@ -446,14 +457,14 @@ public class AccessibilityFloatingMenuView extends FrameLayout fadeOut(); } - public void setOnDragEndListener(OnDragEndListener onDragListener) { - mOnDragEndListener = Optional.ofNullable(onDragListener); + public void setOnDragEndListener(OnDragEndListener onDragEndListener) { + mOnDragEndListener = Optional.ofNullable(onDragEndListener); } void startTranslateXAnimation() { fadeIn(); - final float toXValue = mAlignment == Alignment.RIGHT + final float toXValue = (mAlignment == Alignment.RIGHT) ? ANIMATION_TO_X_VALUE : -ANIMATION_TO_X_VALUE; final TranslateAnimation animation = @@ -581,7 +592,7 @@ public class AccessibilityFloatingMenuView extends FrameLayout final boolean currentImeVisibility = insets.isVisible(ime()); if (currentImeVisibility != mImeVisibility) { mImeVisibility = currentImeVisibility; - updateLocationWith(mAlignment, mPercentageY); + updateLocationWith(mPosition); } return insets; @@ -697,8 +708,10 @@ public class AccessibilityFloatingMenuView extends FrameLayout params.receiveInsetsIgnoringZOrder = true; params.windowAnimations = android.R.style.Animation_Translucent; params.gravity = Gravity.START | Gravity.TOP; - params.x = getMaxWindowX(); - params.y = (int) (getMaxWindowY() * mPercentageY); + params.x = (mAlignment == Alignment.RIGHT) ? getMaxWindowX() : getMinWindowX(); +// params.y = (int) (mPosition.getPercentageY() * getMaxWindowY()); + final int currentLayoutY = (int) (mPosition.getPercentageY() * getMaxWindowY()); + params.y = Math.max(MIN_WINDOW_Y, currentLayoutY - getInterval()); updateAccessibilityTitle(params); return params; } @@ -716,7 +729,7 @@ public class AccessibilityFloatingMenuView extends FrameLayout updateItemViewWith(mSizeType); updateColor(); updateStrokeWith(newConfig.uiMode, mAlignment); - updateLocationWith(mAlignment, mPercentageY); + updateLocationWith(mPosition); updateRadiusWith(mSizeType, mRadiusType, mTargets.size()); updateScrollModeWith(hasExceededMaxLayoutHeight()); setSystemGestureExclusion(); @@ -765,9 +778,10 @@ public class AccessibilityFloatingMenuView extends FrameLayout /** * Updates the floating menu to be fixed at the side of the screen. */ - private void updateLocationWith(@Alignment int side, float percentageCurrentY) { - mCurrentLayoutParams.x = (side == Alignment.RIGHT) ? getMaxWindowX() : getMinWindowX(); - final int currentLayoutY = (int) (percentageCurrentY * getMaxWindowY()); + private void updateLocationWith(Position position) { + final @Alignment int alignment = transformToAlignment(position.getPercentageX()); + mCurrentLayoutParams.x = (alignment == Alignment.RIGHT) ? getMaxWindowX() : getMinWindowX(); + final int currentLayoutY = (int) (position.getPercentageY() * getMaxWindowY()); mCurrentLayoutParams.y = Math.max(MIN_WINDOW_Y, currentLayoutY - getInterval()); mWindowManager.updateViewLayout(this, mCurrentLayoutParams); } @@ -861,10 +875,17 @@ public class AccessibilityFloatingMenuView extends FrameLayout } @Alignment - private int calculateCurrentAlignment() { - return mCurrentLayoutParams.x >= ((getMinWindowX() + getMaxWindowX()) / 2) - ? Alignment.RIGHT - : Alignment.LEFT; + private int transformToAlignment(@FloatRange(from = 0.0, to = 1.0) float percentageX) { + return (percentageX < 0.5f) ? Alignment.LEFT : Alignment.RIGHT; + } + + private float transformCurrentPercentageXToEdge() { + final float percentageX = calculateCurrentPercentageX(); + return (percentageX < 0.5) ? 0.0f : 1.0f; + } + + private float calculateCurrentPercentageX() { + return mCurrentLayoutParams.x / (float) getMaxWindowX(); } private float calculateCurrentPercentageY() { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/Position.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/Position.java new file mode 100644 index 000000000000..7b7eda84df4c --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/Position.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2021 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.floatingmenu; + +import android.annotation.FloatRange; +import android.text.TextUtils; + +/** + * Stores information about the position, which includes percentage of X-axis of the screen, + * percentage of Y-axis of the screen. + */ +public class Position { + + private static final char STRING_SEPARATOR = ','; + private static final TextUtils.SimpleStringSplitter sStringCommaSplitter = + new TextUtils.SimpleStringSplitter(STRING_SEPARATOR); + + private float mPercentageX; + private float mPercentageY; + + /** + * Creates a {@link Position} from a encoded string described in {@link #toString()}. + * + * @param positionString A string conform to the format described in {@link #toString()} + * @return A {@link Position} with the given value retrieved from {@code absolutePositionString} + * @throws IllegalArgumentException If {@code positionString} does not conform to the format + * described in {@link #toString()} + */ + public static Position fromString(String positionString) { + sStringCommaSplitter.setString(positionString); + if (sStringCommaSplitter.hasNext()) { + final float percentageX = Float.parseFloat(sStringCommaSplitter.next()); + final float percentageY = Float.parseFloat(sStringCommaSplitter.next()); + return new Position(percentageX, percentageY); + } + + throw new IllegalArgumentException( + "Invalid Position string: " + positionString); + } + + Position(float percentageX, float percentageY) { + update(percentageX, percentageY); + } + + @Override + public String toString() { + return mPercentageX + ", " + mPercentageY; + } + + /** + * Updates the position with {@code percentageX} and {@code percentageY}. + * + * @param percentageX the new percentage of X-axis of the screen, from 0.0 to 1.0. + * @param percentageY the new percentage of Y-axis of the screen, from 0.0 to 1.0. + */ + public void update(@FloatRange(from = 0.0, to = 1.0) float percentageX, + @FloatRange(from = 0.0, to = 1.0) float percentageY) { + mPercentageX = percentageX; + mPercentageY = percentageY; + } + + public float getPercentageX() { + return mPercentageX; + } + + public float getPercentageY() { + return mPercentageY; + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuTest.java index 337d97e1dc0b..e027a2b7bcaf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuTest.java @@ -22,7 +22,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; import android.content.Context; import android.testing.AndroidTestingRunner; @@ -31,15 +30,16 @@ import android.view.accessibility.AccessibilityManager; import androidx.test.filters.SmallTest; -import com.android.internal.accessibility.dialog.AccessibilityTarget; import com.android.systemui.SysuiTestCase; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; @@ -50,6 +50,9 @@ import java.util.List; @TestableLooper.RunWithLooper public class AccessibilityFloatingMenuTest extends SysuiTestCase { + @Rule + public MockitoRule mockito = MockitoJUnit.rule(); + @Mock private AccessibilityManager mAccessibilityManager; @@ -58,18 +61,14 @@ public class AccessibilityFloatingMenuTest extends SysuiTestCase { @Before public void initMenu() { - MockitoAnnotations.initMocks(this); - - final List<AccessibilityTarget> mTargets = new ArrayList<>(); - mTargets.add(mock(AccessibilityTarget.class)); - final List<String> assignedTargets = new ArrayList<>(); mContext.addMockSystemService(Context.ACCESSIBILITY_SERVICE, mAccessibilityManager); assignedTargets.add(MAGNIFICATION_CONTROLLER_NAME); doReturn(assignedTargets).when(mAccessibilityManager).getAccessibilityShortcutTargets( anyInt()); - mMenuView = new AccessibilityFloatingMenuView(mContext); + final Position position = new Position(0, 0); + mMenuView = new AccessibilityFloatingMenuView(mContext, position); mMenu = new AccessibilityFloatingMenu(mContext, mMenuView); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuViewTest.java index 448211ed5274..09e6940acd43 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuViewTest.java @@ -39,7 +39,6 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Insets; import android.graphics.Rect; -import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.LayerDrawable; import android.testing.AndroidTestingRunner; @@ -63,13 +62,16 @@ import com.android.systemui.accessibility.MotionEventHelper; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InOrder; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** Tests for {@link AccessibilityFloatingMenuView}. */ @@ -77,22 +79,26 @@ import java.util.List; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper public class AccessibilityFloatingMenuViewTest extends SysuiTestCase { - private AccessibilityFloatingMenuView mMenuView; + + @Rule + public MockitoRule mockito = MockitoJUnit.rule(); + + private final MotionEventHelper mMotionEventHelper = new MotionEventHelper(); + private final List<AccessibilityTarget> mTargets = new ArrayList<>( + Collections.singletonList(mock(AccessibilityTarget.class))); + + private final Rect mAvailableBounds = new Rect(100, 200, 300, 400); + private final Position mPlaceholderPosition = new Position(0.0f, 0.0f); @Mock private WindowManager mWindowManager; - @Mock private ViewPropertyAnimator mAnimator; - @Mock private WindowMetrics mWindowMetrics; - private MotionEvent mInterceptMotionEvent; - - private RecyclerView mListView; - - private Rect mAvailableBounds = new Rect(100, 200, 300, 400); + private AccessibilityFloatingMenuView mMenuView; + private RecyclerView mListView = new RecyclerView(mContext); private int mScreenHeight; private int mMenuWindowHeight; @@ -101,23 +107,21 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase { private int mScreenHalfWidth; private int mScreenHalfHeight; private int mMaxWindowX; - - private final MotionEventHelper mMotionEventHelper = new MotionEventHelper(); - private final List<AccessibilityTarget> mTargets = new ArrayList<>(); + private int mMaxWindowY; @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - + public void initMenuView() { final WindowManager wm = mContext.getSystemService(WindowManager.class); doAnswer(invocation -> wm.getMaximumWindowMetrics()).when( mWindowManager).getMaximumWindowMetrics(); mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager); - mTargets.add(mock(AccessibilityTarget.class)); - mListView = new RecyclerView(mContext); - mMenuView = new AccessibilityFloatingMenuView(mContext, mListView); + mMenuView = spy( + new AccessibilityFloatingMenuView(mContext, mPlaceholderPosition, mListView)); + } + @Before + public void setUpMatrices() { final Resources res = mContext.getResources(); final int margin = res.getDimensionPixelSize(R.dimen.accessibility_floating_menu_margin); @@ -135,6 +139,7 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase { mScreenHalfHeight = mScreenHeight / 2; mMaxWindowX = screenWidth - margin - menuWidth; mMenuWindowHeight = menuHeight + margin * 2; + mMaxWindowY = mScreenHeight - mMenuWindowHeight; } @Test @@ -180,42 +185,46 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase { } @Test - public void updateListViewRadius_singleTarget_matchResult() { - final float radius = - getContext().getResources().getDimensionPixelSize( - R.dimen.accessibility_floating_menu_small_single_radius); - final float[] expectedRadii = - new float[]{radius, radius, 0.0f, 0.0f, 0.0f, 0.0f, radius, radius}; + public void onTargetsChanged_singleTarget_expectedRadii() { + final Position alignRightPosition = new Position(1.0f, 0.0f); + final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext, + alignRightPosition); + setupBasicMenuView(menuView); - mMenuView.onTargetsChanged(mTargets); - final View view = mMenuView.getChildAt(0); + menuView.onTargetsChanged(mTargets); + + final View view = menuView.getChildAt(0); final LayerDrawable layerDrawable = (LayerDrawable) view.getBackground(); final GradientDrawable gradientDrawable = (GradientDrawable) layerDrawable.getDrawable(0); - final float[] actualRadii = gradientDrawable.getCornerRadii(); - - assertThat(actualRadii).isEqualTo(expectedRadii); + final float smallRadius = + getContext().getResources().getDimensionPixelSize( + R.dimen.accessibility_floating_menu_small_single_radius); + final float[] expectedRadii = + new float[]{smallRadius, smallRadius, 0.0f, 0.0f, 0.0f, 0.0f, smallRadius, + smallRadius}; + assertThat(gradientDrawable.getCornerRadii()).isEqualTo(expectedRadii); } @Test - public void setSizeType_largeSize_matchResult() { - final int shapeType = 2; - final float radius = getContext().getResources().getDimensionPixelSize( - R.dimen.accessibility_floating_menu_large_single_radius); - final float[] expectedRadii = - new float[]{radius, radius, 0.0f, 0.0f, 0.0f, 0.0f, radius, radius}; - final Drawable listViewBackground = - mContext.getDrawable(R.drawable.accessibility_floating_menu_background); - mListView = spy(new RecyclerView(mContext)); - mListView.setBackground(listViewBackground); - - mMenuView = new AccessibilityFloatingMenuView(mContext, mListView); - mMenuView.setSizeType(shapeType); + public void setSizeType_alignRightAndLargeSize_expectedRadii() { + final RecyclerView listView = spy(new RecyclerView(mContext)); + final Position alignRightPosition = new Position(1.0f, 0.0f); + final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext, + alignRightPosition, listView); + setupBasicMenuView(menuView); + + menuView.setSizeType(/* largeSize */ 1); + final LayerDrawable layerDrawable = - (LayerDrawable) mListView.getBackground(); + (LayerDrawable) listView.getBackground(); final GradientDrawable gradientDrawable = (GradientDrawable) layerDrawable.getDrawable(0); - + final float largeRadius = getContext().getResources().getDimensionPixelSize( + R.dimen.accessibility_floating_menu_large_single_radius); + final float[] expectedRadii = + new float[] {largeRadius, largeRadius, 0.0f, 0.0f, 0.0f, 0.0f, largeRadius, + largeRadius}; assertThat(gradientDrawable.getCornerRadii()).isEqualTo(expectedRadii); } @@ -223,49 +232,43 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase { public void setShapeType_halfCircle_translationX() { final RecyclerView listView = spy(new RecyclerView(mContext)); final AccessibilityFloatingMenuView menuView = - new AccessibilityFloatingMenuView(mContext, listView); - final int shapeType = 2; + new AccessibilityFloatingMenuView(mContext, mPlaceholderPosition, listView); + setupBasicMenuView(menuView); doReturn(mAnimator).when(listView).animate(); - menuView.setShapeType(shapeType); + menuView.setShapeType(/* halfOvalShape */ 1); verify(mAnimator).translationX(anyFloat()); } @Test public void onTargetsChanged_fadeInOut() { - final AccessibilityFloatingMenuView menuView = spy(mMenuView); - final InOrder inOrderMenuView = inOrder(menuView); + final InOrder inOrderMenuView = inOrder(mMenuView); - menuView.onTargetsChanged(mTargets); + mMenuView.onTargetsChanged(mTargets); - inOrderMenuView.verify(menuView).fadeIn(); - inOrderMenuView.verify(menuView).fadeOut(); + inOrderMenuView.verify(mMenuView).fadeIn(); + inOrderMenuView.verify(mMenuView).fadeOut(); } @Test public void setSizeType_fadeInOut() { - final AccessibilityFloatingMenuView menuView = spy(mMenuView); - final InOrder inOrderMenuView = inOrder(menuView); - final int smallSize = 0; - menuView.setSizeType(smallSize); + final InOrder inOrderMenuView = inOrder(mMenuView); + + mMenuView.setSizeType(/* smallSize */ 0); - inOrderMenuView.verify(menuView).fadeIn(); - inOrderMenuView.verify(menuView).fadeOut(); + inOrderMenuView.verify(mMenuView).fadeIn(); + inOrderMenuView.verify(mMenuView).fadeOut(); } @Test public void tapOnAndDragMenu_interceptUpEvent() { final RecyclerView listView = new RecyclerView(mContext); final TestAccessibilityFloatingMenu menuView = - new TestAccessibilityFloatingMenu(mContext, listView); - - menuView.show(); - menuView.onTargetsChanged(mTargets); - menuView.setSizeType(0); - menuView.setShapeType(0); - final int currentWindowX = mMenuView.mCurrentLayoutParams.x; - final int currentWindowY = mMenuView.mCurrentLayoutParams.y; + new TestAccessibilityFloatingMenu(mContext, mPlaceholderPosition, listView); + setupBasicMenuView(menuView); + final int currentWindowX = menuView.mCurrentLayoutParams.x; + final int currentWindowY = menuView.mCurrentLayoutParams.y; final MotionEvent downEvent = mMotionEventHelper.obtainMotionEvent(0, 1, MotionEvent.ACTION_DOWN, @@ -283,6 +286,7 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase { /* screenCenterX */ mScreenHalfWidth - /* offsetXToScreenLeftHalfRegion */ 10, /* screenCenterY */ mScreenHalfHeight); + listView.dispatchTouchEvent(downEvent); listView.dispatchTouchEvent(moveEvent); listView.dispatchTouchEvent(upEvent); @@ -292,12 +296,15 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase { @Test public void tapOnAndDragMenu_matchLocation() { - mMenuView.show(); - mMenuView.onTargetsChanged(mTargets); - mMenuView.setSizeType(0); - mMenuView.setShapeType(0); - final int currentWindowX = mMenuView.mCurrentLayoutParams.x; - final int currentWindowY = mMenuView.mCurrentLayoutParams.y; + final float expectedX = 1.0f; + final float expectedY = 0.7f; + final Position position = new Position(expectedX, expectedY); + final RecyclerView listView = new RecyclerView(mContext); + final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext, + position, listView); + setupBasicMenuView(menuView); + final int currentWindowX = menuView.mCurrentLayoutParams.x; + final int currentWindowY = menuView.mCurrentLayoutParams.y; final MotionEvent downEvent = mMotionEventHelper.obtainMotionEvent(0, 1, MotionEvent.ACTION_DOWN, @@ -315,25 +322,28 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase { /* screenCenterX */ mScreenHalfWidth + /* offsetXToScreenRightHalfRegion */ 10, /* screenCenterY */ mScreenHalfHeight); - mListView.dispatchTouchEvent(downEvent); - mListView.dispatchTouchEvent(moveEvent); - mListView.dispatchTouchEvent(upEvent); - mMenuView.mDragAnimator.end(); - assertThat(mMenuView.mCurrentLayoutParams.x).isEqualTo(mMaxWindowX); - assertThat(mMenuView.mCurrentLayoutParams.y).isEqualTo( + listView.dispatchTouchEvent(downEvent); + listView.dispatchTouchEvent(moveEvent); + listView.dispatchTouchEvent(upEvent); + menuView.mDragAnimator.end(); + + assertThat((float) menuView.mCurrentLayoutParams.x).isWithin(1.0f).of(mMaxWindowX); + assertThat((float) menuView.mCurrentLayoutParams.y).isWithin(1.0f).of( /* newWindowY = screenCenterY - offsetY */ mScreenHalfHeight - mMenuHalfHeight); } @Test public void tapOnAndDragMenuToScreenSide_transformShapeHalfOval() { - mMenuView.show(); - mMenuView.onTargetsChanged(mTargets); - mMenuView.setSizeType(0); - mMenuView.setShapeType(/* oval */ 0); - final int currentWindowX = mMenuView.mCurrentLayoutParams.x; - final int currentWindowY = mMenuView.mCurrentLayoutParams.y; + final Position alignRightPosition = new Position(1.0f, 0.8f); + final RecyclerView listView = new RecyclerView(mContext); + final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext, + alignRightPosition, listView); + setupBasicMenuView(menuView); + + final int currentWindowX = menuView.mCurrentLayoutParams.x; + final int currentWindowY = menuView.mCurrentLayoutParams.y; final MotionEvent downEvent = mMotionEventHelper.obtainMotionEvent(0, 1, MotionEvent.ACTION_DOWN, @@ -351,125 +361,110 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase { /* downX */(currentWindowX + mMenuHalfWidth) + /* offsetXToScreenRightSide */ mMenuHalfWidth, /* downY */ (currentWindowY + mMenuHalfHeight)); - mListView.dispatchTouchEvent(downEvent); - mListView.dispatchTouchEvent(moveEvent); - mListView.dispatchTouchEvent(upEvent); - assertThat(mMenuView.mShapeType).isEqualTo(/* halfOval */ 1); + listView.dispatchTouchEvent(downEvent); + listView.dispatchTouchEvent(moveEvent); + listView.dispatchTouchEvent(upEvent); + + assertThat(menuView.mShapeType).isEqualTo(/* halfOval */ 1); } @Test public void getAccessibilityActionList_matchResult() { - final AccessibilityNodeInfo infos = new AccessibilityNodeInfo(); - mMenuView.onInitializeAccessibilityNodeInfo(infos); + final AccessibilityNodeInfo info = new AccessibilityNodeInfo(); + + mMenuView.onInitializeAccessibilityNodeInfo(info); - assertThat(infos.getActionList().size()).isEqualTo(5); + assertThat(info.getActionList().size()).isEqualTo(5); } @Test public void accessibilityActionMove_halfOval_moveTopLeft_success() { - final AccessibilityFloatingMenuView menuView = - spy(new AccessibilityFloatingMenuView(mContext)); - doReturn(mAvailableBounds).when(menuView).getAvailableBounds(); - menuView.setShapeType(/* halfOvalShape */ 1); + doReturn(mAvailableBounds).when(mMenuView).getAvailableBounds(); + mMenuView.setShapeType(/* halfOvalShape */ 1); - final boolean isActionPerformed = - menuView.performAccessibilityAction(R.id.action_move_top_left, null); + final boolean moveTopLeftAction = + mMenuView.performAccessibilityAction(R.id.action_move_top_left, null); - assertThat(isActionPerformed).isTrue(); - assertThat(menuView.mShapeType).isEqualTo(/* ovalShape */ 0); - verify(menuView).snapToLocation(mAvailableBounds.left, mAvailableBounds.top); + assertThat(moveTopLeftAction).isTrue(); + assertThat(mMenuView.mShapeType).isEqualTo(/* ovalShape */ 0); + verify(mMenuView).snapToLocation(mAvailableBounds.left, mAvailableBounds.top); } @Test public void accessibilityActionMove_halfOval_moveTopRight_success() { - final AccessibilityFloatingMenuView menuView = - spy(new AccessibilityFloatingMenuView(mContext)); - doReturn(mAvailableBounds).when(menuView).getAvailableBounds(); - menuView.setShapeType(/* halfOvalShape */ 1); + doReturn(mAvailableBounds).when(mMenuView).getAvailableBounds(); + mMenuView.setShapeType(/* halfOvalShape */ 1); - final boolean isActionPerformed = - menuView.performAccessibilityAction(R.id.action_move_top_right, null); + final boolean moveTopRightAction = + mMenuView.performAccessibilityAction(R.id.action_move_top_right, null); - assertThat(isActionPerformed).isTrue(); - assertThat(menuView.mShapeType).isEqualTo(/* ovalShape */ 0); - verify(menuView).snapToLocation(mAvailableBounds.right, mAvailableBounds.top); + assertThat(moveTopRightAction).isTrue(); + assertThat(mMenuView.mShapeType).isEqualTo(/* ovalShape */ 0); + verify(mMenuView).snapToLocation(mAvailableBounds.right, mAvailableBounds.top); } @Test public void accessibilityActionMove_halfOval_moveBottomLeft_success() { - final AccessibilityFloatingMenuView menuView = - spy(new AccessibilityFloatingMenuView(mContext)); - doReturn(mAvailableBounds).when(menuView).getAvailableBounds(); - menuView.setShapeType(/* halfOvalShape */ 1); + doReturn(mAvailableBounds).when(mMenuView).getAvailableBounds(); + mMenuView.setShapeType(/* halfOvalShape */ 1); - final boolean isActionPerformed = - menuView.performAccessibilityAction(R.id.action_move_bottom_left, null); + final boolean moveBottomLeftAction = + mMenuView.performAccessibilityAction(R.id.action_move_bottom_left, null); - assertThat(isActionPerformed).isTrue(); - assertThat(menuView.mShapeType).isEqualTo(/* ovalShape */ 0); - verify(menuView).snapToLocation(mAvailableBounds.left, mAvailableBounds.bottom); + assertThat(moveBottomLeftAction).isTrue(); + assertThat(mMenuView.mShapeType).isEqualTo(/* ovalShape */ 0); + verify(mMenuView).snapToLocation(mAvailableBounds.left, mAvailableBounds.bottom); } @Test public void accessibilityActionMove_halfOval_moveBottomRight_success() { - final AccessibilityFloatingMenuView menuView = - spy(new AccessibilityFloatingMenuView(mContext)); - doReturn(mAvailableBounds).when(menuView).getAvailableBounds(); - menuView.setShapeType(/* halfOvalShape */ 1); + doReturn(mAvailableBounds).when(mMenuView).getAvailableBounds(); + mMenuView.setShapeType(/* halfOvalShape */ 1); - final boolean isActionPerformed = - menuView.performAccessibilityAction(R.id.action_move_bottom_right, null); + final boolean moveBottomRightAction = + mMenuView.performAccessibilityAction(R.id.action_move_bottom_right, null); - assertThat(isActionPerformed).isTrue(); - assertThat(menuView.mShapeType).isEqualTo(/* ovalShape */ 0); - verify(menuView).snapToLocation(mAvailableBounds.right, mAvailableBounds.bottom); + assertThat(moveBottomRightAction).isTrue(); + assertThat(mMenuView.mShapeType).isEqualTo(/* ovalShape */ 0); + verify(mMenuView).snapToLocation(mAvailableBounds.right, mAvailableBounds.bottom); } @Test public void accessibilityActionMove_halfOval_moveOutEdgeAndShow_success() { - final AccessibilityFloatingMenuView menuView = - spy(new AccessibilityFloatingMenuView(mContext)); - doReturn(mAvailableBounds).when(menuView).getAvailableBounds(); - menuView.setShapeType(/* halfOvalShape */ 1); + doReturn(mAvailableBounds).when(mMenuView).getAvailableBounds(); + mMenuView.setShapeType(/* halfOvalShape */ 1); - final boolean isActionPerformed = - menuView.performAccessibilityAction(R.id.action_move_out_edge_and_show, null); + final boolean moveOutEdgeAndShowAction = + mMenuView.performAccessibilityAction(R.id.action_move_out_edge_and_show, null); - assertThat(isActionPerformed).isTrue(); - assertThat(menuView.mShapeType).isEqualTo(/* ovalShape */ 0); + assertThat(moveOutEdgeAndShowAction).isTrue(); + assertThat(mMenuView.mShapeType).isEqualTo(/* ovalShape */ 0); } @Test public void setupAccessibilityActions_oval_hasActionMoveToEdgeAndHide() { - final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext); - menuView.setShapeType(/* ovalShape */ 0); + final AccessibilityNodeInfo info = new AccessibilityNodeInfo(); + mMenuView.setShapeType(/* ovalShape */ 0); - final AccessibilityNodeInfo infos = new AccessibilityNodeInfo(); - menuView.onInitializeAccessibilityNodeInfo(infos); + mMenuView.onInitializeAccessibilityNodeInfo(info); - assertThat(infos.getActionList().stream().anyMatch( + assertThat(info.getActionList().stream().anyMatch( action -> action.getId() == R.id.action_move_to_edge_and_hide)).isTrue(); } @Test public void onTargetsChanged_exceedAvailableHeight_overScrollAlways() { - final RecyclerView listView = new RecyclerView(mContext); - final AccessibilityFloatingMenuView menuView = - spy(new AccessibilityFloatingMenuView(mContext, listView)); - doReturn(true).when(menuView).hasExceededMaxLayoutHeight(); + doReturn(true).when(mMenuView).hasExceededMaxLayoutHeight(); - menuView.onTargetsChanged(mTargets); + mMenuView.onTargetsChanged(mTargets); - assertThat(listView.getOverScrollMode()).isEqualTo(OVER_SCROLL_ALWAYS); + assertThat(mListView.getOverScrollMode()).isEqualTo(OVER_SCROLL_ALWAYS); } @Test public void onTargetsChanged_notExceedAvailableHeight_overScrollNever() { - final RecyclerView listView = new RecyclerView(mContext); - final AccessibilityFloatingMenuView menuView = - spy(new AccessibilityFloatingMenuView(mContext, listView)); - doReturn(false).when(menuView).hasExceededMaxLayoutHeight(); + doReturn(false).when(mMenuView).hasExceededMaxLayoutHeight(); mMenuView.onTargetsChanged(mTargets); @@ -480,21 +475,24 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase { public void showMenuView_insetsListener_overlapWithIme_menuViewShifted() { final int offset = 200; - showMenuWithLatestStatus(); - final WindowInsets imeInset = fakeImeInsetWith(offset); + final Position alignRightPosition = new Position(1.0f, 0.8f); + final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext, + alignRightPosition); + setupBasicMenuView(menuView); + final WindowInsets imeInset = fakeImeInsetWith(menuView, offset); when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics); when(mWindowMetrics.getWindowInsets()).thenReturn(imeInset); - final int expectedLayoutY = mMenuView.mCurrentLayoutParams.y - offset; - mMenuView.dispatchApplyWindowInsets(imeInset); + final int expectedLayoutY = menuView.mCurrentLayoutParams.y - offset; + menuView.dispatchApplyWindowInsets(imeInset); - assertThat(mMenuView.mCurrentLayoutParams.y).isEqualTo(expectedLayoutY); + assertThat(menuView.mCurrentLayoutParams.y).isEqualTo(expectedLayoutY); } @Test public void hideIme_onMenuViewShifted_menuViewMovedBack() { final int offset = 200; - showMenuWithLatestStatus(); - final WindowInsets imeInset = fakeImeInsetWith(offset); + setupBasicMenuView(mMenuView); + final WindowInsets imeInset = fakeImeInsetWith(mMenuView, offset); when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics); when(mWindowMetrics.getWindowInsets()).thenReturn(imeInset); final int expectedLayoutY = mMenuView.mCurrentLayoutParams.y; @@ -510,8 +508,8 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase { public void showMenuAndIme_withHigherIme_alignScreenTopEdge() { final int offset = 99999; - showMenuWithLatestStatus(); - final WindowInsets imeInset = fakeImeInsetWith(offset); + setupBasicMenuView(mMenuView); + final WindowInsets imeInset = fakeImeInsetWith(mMenuView, offset); when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics); when(mWindowMetrics.getWindowInsets()).thenReturn(imeInset); mMenuView.dispatchApplyWindowInsets(imeInset); @@ -519,31 +517,47 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase { assertThat(mMenuView.mCurrentLayoutParams.y).isEqualTo(0); } + @Test + public void testConstructor_withPosition_expectedPosition() { + final float expectedX = 1.0f; + final float expectedY = 0.7f; + final Position position = new Position(expectedX, expectedY); + + final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext, + position); + setupBasicMenuView(menuView); + + assertThat((float) menuView.mCurrentLayoutParams.x).isWithin(1.0f).of(mMaxWindowX); + assertThat((float) menuView.mCurrentLayoutParams.y).isWithin(1.0f).of( + expectedY * mMaxWindowY); + } + @After public void tearDown() { mInterceptMotionEvent = null; mMotionEventHelper.recycleEvents(); + mListView = null; } - private void showMenuWithLatestStatus() { - mMenuView.show(); - mMenuView.onTargetsChanged(mTargets); - mMenuView.setSizeType(0); - mMenuView.setShapeType(0); + private void setupBasicMenuView(AccessibilityFloatingMenuView menuView) { + menuView.show(); + menuView.onTargetsChanged(mTargets); + menuView.setSizeType(0); + menuView.setShapeType(0); } /** * Based on the current menu status, fake the ime inset component {@link WindowInsets} used * for testing. * - * @param offset is used for the y-axis position of ime higher than the y-axis position of menu. + * @param menuView {@link AccessibilityFloatingMenuView} that needs to be changed + * @param offset is used for the y-axis position of ime higher than the y-axis position of menu * @return the ime inset */ - private WindowInsets fakeImeInsetWith(int offset) { + private WindowInsets fakeImeInsetWith(AccessibilityFloatingMenuView menuView, int offset) { // Ensure the keyboard has overlapped on the menu view. final int fakeImeHeight = - mScreenHeight - (mMenuView.mCurrentLayoutParams.y + mMenuWindowHeight) + offset; - + mScreenHeight - (menuView.mCurrentLayoutParams.y + mMenuWindowHeight) + offset; return new WindowInsets.Builder() .setVisible(ime() | navigationBars(), true) .setInsets(ime() | navigationBars(), Insets.of(0, 0, 0, fakeImeHeight)) @@ -551,8 +565,8 @@ public class AccessibilityFloatingMenuViewTest extends SysuiTestCase { } private class TestAccessibilityFloatingMenu extends AccessibilityFloatingMenuView { - TestAccessibilityFloatingMenu(Context context, RecyclerView listView) { - super(context, listView); + TestAccessibilityFloatingMenu(Context context, Position position, RecyclerView listView) { + super(context, position, listView); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/BaseTooltipViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/BaseTooltipViewTest.java index 6db5761a5054..eb1f15b30d6f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/BaseTooltipViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/BaseTooltipViewTest.java @@ -55,6 +55,7 @@ public class BaseTooltipViewTest extends SysuiTestCase { private AccessibilityFloatingMenuView mMenuView; private BaseTooltipView mToolTipView; + private final Position mPlaceholderPosition = new Position(0.0f, 0.0f); private final MotionEventHelper mMotionEventHelper = new MotionEventHelper(); @Before @@ -66,7 +67,7 @@ public class BaseTooltipViewTest extends SysuiTestCase { mWindowManager).getMaximumWindowMetrics(); mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager); - mMenuView = new AccessibilityFloatingMenuView(mContext); + mMenuView = new AccessibilityFloatingMenuView(mContext, mPlaceholderPosition); mToolTipView = new BaseTooltipView(mContext, mMenuView); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DockTooltipViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DockTooltipViewTest.java index 41b948fb80b0..ca4e3e914a8c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DockTooltipViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/DockTooltipViewTest.java @@ -51,6 +51,7 @@ public class DockTooltipViewTest extends SysuiTestCase { private AccessibilityFloatingMenuView mMenuView; private DockTooltipView mDockTooltipView; + private final Position mPlaceholderPosition = new Position(0.0f, 0.0f); private final MotionEventHelper mMotionEventHelper = new MotionEventHelper(); @Before @@ -62,7 +63,7 @@ public class DockTooltipViewTest extends SysuiTestCase { mWindowManager).getMaximumWindowMetrics(); mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager); - mMenuView = spy(new AccessibilityFloatingMenuView(mContext)); + mMenuView = spy(new AccessibilityFloatingMenuView(mContext, mPlaceholderPosition)); mDockTooltipView = new DockTooltipView(mContext, mMenuView); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MigrationTooltipViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MigrationTooltipViewTest.java index c5bd2fefae16..2fb0a90e7fc2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MigrationTooltipViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/MigrationTooltipViewTest.java @@ -40,10 +40,12 @@ import org.junit.runner.RunWith; public class MigrationTooltipViewTest extends SysuiTestCase { private TextView mTextView; + private final Position mPlaceholderPosition = new Position(0.0f, 0.0f); @Before public void setUp() { - final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext); + final AccessibilityFloatingMenuView menuView = new AccessibilityFloatingMenuView(mContext, + mPlaceholderPosition); final MigrationTooltipView toolTipView = new MigrationTooltipView(mContext, menuView); mTextView = toolTipView.findViewById(R.id.text); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/PositionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/PositionTest.java new file mode 100644 index 000000000000..05f306b1e8b3 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/PositionTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021 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.floatingmenu; + +import static com.google.common.truth.Truth.assertThat; + +import android.testing.AndroidTestingRunner; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Tests for {@link Position}. */ +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class PositionTest extends SysuiTestCase { + + @Test + public void fromString_correctFormat_expectedValues() { + final float expectedX = 0.0f; + final float expectedY = 0.7f; + final String correctStringFormat = expectedX + ", " + expectedY; + + final Position position = Position.fromString(correctStringFormat); + + assertThat(position.getPercentageX()).isEqualTo(expectedX); + assertThat(position.getPercentageY()).isEqualTo(expectedY); + } + + @Test(expected = IllegalArgumentException.class) + public void fromString_incorrectFormat_throwsException() { + final String incorrectStringFormat = "0.0: 1.0"; + + // expect to throw IllegalArgumentException for the incorrect separator ":" + Position.fromString(incorrectStringFormat); + } + + @Test + public void constructor() { + final float expectedX = 0.5f; + final float expectedY = 0.9f; + + final Position position = new Position(expectedX, expectedY); + + assertThat(position.getPercentageX()).isEqualTo(expectedX); + assertThat(position.getPercentageY()).isEqualTo(expectedY); + } +} |