Fix that accessibility floating menu did not remember tucked state when lock/unlock the phone.

Actions:
1) Add a new SharedPreference key to record the tucked state.
2) Add a new LiveData for the tucked state.

Bug: 251082969
Test: atest MenuAnimationControllerTest MenuViewLayerTest
Change-Id: I8e8ae6867b6ad72959de3f6bb92c913ae61286c2
This commit is contained in:
Peter Liang
2022-11-06 22:17:03 +08:00
parent e1e1887ece
commit 8dca8a3434
8 changed files with 115 additions and 27 deletions

View File

@@ -72,7 +72,8 @@ public final class Prefs {
Key.HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP,
Key.ACCESSIBILITY_FLOATING_MENU_POSITION,
Key.HAS_CLICKED_NUDGE_TO_SETUP_DREAM,
Key.HAS_DISMISSED_NUDGE_TO_SETUP_DREAM
Key.HAS_DISMISSED_NUDGE_TO_SETUP_DREAM,
Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED
})
// TODO: annotate these with their types so {@link PrefsCommandLine} can know how to set them
public @interface Key {
@@ -117,6 +118,7 @@ public final class Prefs {
String ACCESSIBILITY_FLOATING_MENU_POSITION = "AccessibilityFloatingMenuPosition";
String HAS_CLICKED_NUDGE_TO_SETUP_DREAM = "HasClickedNudgeToSetupDream";
String HAS_DISMISSED_NUDGE_TO_SETUP_DREAM = "HasDismissedNudgeToSetupDream";
String HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED = "HasAccessibilityFloatingMenuTucked";
}
public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {

View File

@@ -16,8 +16,6 @@
package com.android.systemui.accessibility.floatingmenu;
import static android.util.MathUtils.constrain;
import static java.util.Objects.requireNonNull;
import android.animation.ValueAnimator;
@@ -64,7 +62,6 @@ class MenuAnimationController {
private final MenuView mMenuView;
private final ValueAnimator mFadeOutAnimator;
private final Handler mHandler;
private boolean mIsMovedToEdge;
private boolean mIsFadeEffectEnabled;
private DismissAnimationController.DismissCallback mDismissCallback;
@@ -111,25 +108,25 @@ class MenuAnimationController {
}
void moveToTopLeftPosition() {
mIsMovedToEdge = false;
mMenuView.updateMenuMoveToTucked(/* isMoveToTucked= */ false);
final Rect draggableBounds = mMenuView.getMenuDraggableBounds();
moveAndPersistPosition(new PointF(draggableBounds.left, draggableBounds.top));
}
void moveToTopRightPosition() {
mIsMovedToEdge = false;
mMenuView.updateMenuMoveToTucked(/* isMoveToTucked= */ false);
final Rect draggableBounds = mMenuView.getMenuDraggableBounds();
moveAndPersistPosition(new PointF(draggableBounds.right, draggableBounds.top));
}
void moveToBottomLeftPosition() {
mIsMovedToEdge = false;
mMenuView.updateMenuMoveToTucked(/* isMoveToTucked= */ false);
final Rect draggableBounds = mMenuView.getMenuDraggableBounds();
moveAndPersistPosition(new PointF(draggableBounds.left, draggableBounds.bottom));
}
void moveToBottomRightPosition() {
mIsMovedToEdge = false;
mMenuView.updateMenuMoveToTucked(/* isMoveToTucked= */ false);
final Rect draggableBounds = mMenuView.getMenuDraggableBounds();
moveAndPersistPosition(new PointF(draggableBounds.right, draggableBounds.bottom));
}
@@ -254,6 +251,8 @@ class MenuAnimationController {
// If the translation x is zero, it should be at the left of the bound.
if (currentXTranslation < draggableBounds.left
|| currentXTranslation > draggableBounds.right) {
constrainPositionAndUpdate(
new PointF(mMenuView.getTranslationX(), mMenuView.getTranslationY()));
moveToEdgeAndHide();
return true;
}
@@ -262,37 +261,33 @@ class MenuAnimationController {
return false;
}
private boolean isOnLeftSide() {
boolean isOnLeftSide() {
return mMenuView.getTranslationX() < mMenuView.getMenuDraggableBounds().centerX();
}
boolean isMovedToEdge() {
return mIsMovedToEdge;
boolean isMoveToTucked() {
return mMenuView.isMoveToTucked();
}
void moveToEdgeAndHide() {
mIsMovedToEdge = true;
mMenuView.updateMenuMoveToTucked(/* isMoveToTucked= */ true);
final Rect draggableBounds = mMenuView.getMenuDraggableBounds();
final float endY = constrain(mMenuView.getTranslationY(), draggableBounds.top,
draggableBounds.bottom);
final float menuHalfWidth = mMenuView.getWidth() / 2.0f;
final PointF position = mMenuView.getMenuPosition();
final float menuHalfWidth = mMenuView.getMenuWidth() / 2.0f;
final float endX = isOnLeftSide()
? draggableBounds.left - menuHalfWidth
: draggableBounds.right + menuHalfWidth;
moveAndPersistPosition(new PointF(endX, endY));
? position.x - menuHalfWidth
: position.x + menuHalfWidth;
moveToPosition(new PointF(endX, position.y));
// Keep the touch region let users could click extra space to pop up the menu view
// from the screen edge
mMenuView.onBoundsInParentChanged(isOnLeftSide()
? draggableBounds.left
: draggableBounds.right, (int) mMenuView.getTranslationY());
mMenuView.onBoundsInParentChanged((int) position.x, (int) position.y);
fadeOutIfEnabled();
}
void moveOutEdgeAndShow() {
mIsMovedToEdge = false;
mMenuView.updateMenuMoveToTucked(/* isMoveToTucked= */ false);
mMenuView.onPositionChanged();
mMenuView.onEdgeChangedIfNeeded();

View File

@@ -51,6 +51,7 @@ class MenuInfoRepository {
@FloatRange(from = 0.0, to = 1.0)
private static final float DEFAULT_MENU_POSITION_Y_PERCENT = 0.77f;
private static final boolean DEFAULT_MOVE_TO_TUCKED_VALUE = false;
private final Context mContext;
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -92,6 +93,12 @@ class MenuInfoRepository {
mPercentagePosition = getStartPosition();
}
void loadMenuMoveToTucked(OnInfoReady<Boolean> callback) {
callback.onReady(
Prefs.getBoolean(mContext, Prefs.Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED,
DEFAULT_MOVE_TO_TUCKED_VALUE));
}
void loadMenuPosition(OnInfoReady<Position> callback) {
callback.onReady(mPercentagePosition);
}
@@ -113,6 +120,11 @@ class MenuInfoRepository {
getMenuOpacityFromSettings(mContext));
}
void updateMoveToTucked(boolean isMoveToTucked) {
Prefs.putBoolean(mContext, Prefs.Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED,
isMoveToTucked);
}
void updateMenuSavingPosition(Position percentagePosition) {
mPercentagePosition = percentagePosition;
Prefs.putString(mContext, Prefs.Key.ACCESSIBILITY_FLOATING_MENU_POSITION,

View File

@@ -74,10 +74,10 @@ class MenuItemAccessibilityDelegate extends RecyclerViewAccessibilityDelegate.It
R.string.accessibility_floating_button_action_move_bottom_right));
info.addAction(moveBottomRight);
final int moveEdgeId = mAnimationController.isMovedToEdge()
final int moveEdgeId = mAnimationController.isMoveToTucked()
? R.id.action_move_out_edge_and_show
: R.id.action_move_to_edge_and_hide;
final int moveEdgeTextResId = mAnimationController.isMovedToEdge()
final int moveEdgeTextResId = mAnimationController.isMoveToTucked()
? R.string.accessibility_floating_button_action_move_out_edge_and_show
: R.string.accessibility_floating_button_action_move_to_edge_and_hide_to_half;
final AccessibilityNodeInfoCompat.AccessibilityActionCompat moveToOrOutEdge =

View File

@@ -58,12 +58,15 @@ class MenuView extends FrameLayout implements
this::updateSystemGestureExcludeRects;
private final Observer<MenuFadeEffectInfo> mFadeEffectInfoObserver =
this::onMenuFadeEffectInfoChanged;
private final Observer<Boolean> mMoveToTuckedObserver = this::onMoveToTucked;
private final Observer<Position> mPercentagePositionObserver = this::onPercentagePosition;
private final Observer<Integer> mSizeTypeObserver = this::onSizeTypeChanged;
private final Observer<List<AccessibilityTarget>> mTargetFeaturesObserver =
this::onTargetFeaturesChanged;
private final MenuViewAppearance mMenuViewAppearance;
private boolean mIsMoveToTucked;
private OnTargetFeaturesChangeListener mFeaturesChangeListener;
MenuView(Context context, MenuViewModel menuViewModel, MenuViewAppearance menuViewAppearance) {
@@ -161,6 +164,12 @@ class MenuView extends FrameLayout implements
mMenuViewAppearance.getMenuStrokeColor());
}
private void onMoveToTucked(boolean isMoveToTucked) {
mIsMoveToTucked = isMoveToTucked;
onPositionChanged();
}
private void onPercentagePosition(Position percentagePosition) {
mMenuViewAppearance.setPercentagePosition(percentagePosition);
@@ -171,6 +180,10 @@ class MenuView extends FrameLayout implements
final PointF position = mMenuViewAppearance.getMenuPosition();
mMenuAnimationController.moveToPosition(position);
onBoundsInParentChanged((int) position.x, (int) position.y);
if (isMoveToTucked()) {
mMenuAnimationController.moveToEdgeAndHide();
}
}
@SuppressLint("NotifyDataSetChanged")
@@ -227,6 +240,14 @@ class MenuView extends FrameLayout implements
return mMenuViewAppearance.getMenuHeight();
}
int getMenuWidth() {
return mMenuViewAppearance.getMenuWidth();
}
PointF getMenuPosition() {
return mMenuViewAppearance.getMenuPosition();
}
void persistPositionAndUpdateEdge(Position percentagePosition) {
mMenuViewModel.updateMenuSavingPosition(percentagePosition);
mMenuViewAppearance.setPercentagePosition(percentagePosition);
@@ -234,6 +255,16 @@ class MenuView extends FrameLayout implements
onEdgeChangedIfNeeded();
}
boolean isMoveToTucked() {
return mIsMoveToTucked;
}
void updateMenuMoveToTucked(boolean isMoveToTucked) {
mIsMoveToTucked = isMoveToTucked;
mMenuViewModel.updateMenuMoveToTucked(isMoveToTucked);
}
/**
* Uses the touch events from the parent view to identify if users clicked the extra
* space of the menu view. If yes, will use the percentage position and update the
@@ -249,7 +280,7 @@ class MenuView extends FrameLayout implements
boolean maybeMoveOutEdgeAndShow(int x, int y) {
// Utilizes the touch region of the parent view to implement that users could tap extra
// the space region to show the menu from the edge.
if (!mMenuAnimationController.isMovedToEdge() || !mBoundsInParent.contains(x, y)) {
if (!isMoveToTucked() || !mBoundsInParent.contains(x, y)) {
return false;
}
@@ -266,6 +297,7 @@ class MenuView extends FrameLayout implements
mMenuViewModel.getFadeEffectInfoData().observeForever(mFadeEffectInfoObserver);
mMenuViewModel.getTargetFeaturesData().observeForever(mTargetFeaturesObserver);
mMenuViewModel.getSizeTypeData().observeForever(mSizeTypeObserver);
mMenuViewModel.getMoveToTuckedData().observeForever(mMoveToTuckedObserver);
setVisibility(VISIBLE);
mMenuViewModel.registerContentObservers();
getViewTreeObserver().addOnComputeInternalInsetsListener(this);
@@ -279,6 +311,7 @@ class MenuView extends FrameLayout implements
mMenuViewModel.getFadeEffectInfoData().removeObserver(mFadeEffectInfoObserver);
mMenuViewModel.getTargetFeaturesData().removeObserver(mTargetFeaturesObserver);
mMenuViewModel.getSizeTypeData().removeObserver(mSizeTypeObserver);
mMenuViewModel.getMoveToTuckedData().removeObserver(mMoveToTuckedObserver);
mMenuViewModel.unregisterContentObservers();
getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
getViewTreeObserver().removeOnDrawListener(mSystemGestureExcludeUpdater);

View File

@@ -35,6 +35,7 @@ class MenuViewModel implements MenuInfoRepository.OnSettingsContentsChanged {
private final MutableLiveData<Integer> mSizeTypeData = new MutableLiveData<>();
private final MutableLiveData<MenuFadeEffectInfo> mFadeEffectInfoData =
new MutableLiveData<>();
private final MutableLiveData<Boolean> mMoveToTuckedData = new MutableLiveData<>();
private final MutableLiveData<Position> mPercentagePositionData = new MutableLiveData<>();
private final MenuInfoRepository mInfoRepository;
@@ -57,10 +58,19 @@ class MenuViewModel implements MenuInfoRepository.OnSettingsContentsChanged {
mFadeEffectInfoData.setValue(fadeEffectInfo);
}
void updateMenuMoveToTucked(boolean isMoveToTucked) {
mInfoRepository.updateMoveToTucked(isMoveToTucked);
}
void updateMenuSavingPosition(Position percentagePosition) {
mInfoRepository.updateMenuSavingPosition(percentagePosition);
}
LiveData<Boolean> getMoveToTuckedData() {
mInfoRepository.loadMenuMoveToTucked(mMoveToTuckedData::setValue);
return mMoveToTuckedData;
}
LiveData<Position> getPercentagePositionData() {
mInfoRepository.loadMenuPosition(mPercentagePositionData::setValue);
return mPercentagePositionData;

View File

@@ -32,8 +32,10 @@ import android.view.WindowManager;
import androidx.test.filters.SmallTest;
import com.android.systemui.Prefs;
import com.android.systemui.SysuiTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -44,6 +46,7 @@ import org.junit.runner.RunWith;
@SmallTest
public class MenuAnimationControllerTest extends SysuiTestCase {
private boolean mLastIsMoveToTucked;
private ViewPropertyAnimator mViewPropertyAnimator;
private MenuView mMenuView;
private MenuAnimationController mMenuAnimationController;
@@ -60,6 +63,14 @@ public class MenuAnimationControllerTest extends SysuiTestCase {
doReturn(mViewPropertyAnimator).when(mMenuView).animate();
mMenuAnimationController = new MenuAnimationController(mMenuView);
mLastIsMoveToTucked = Prefs.getBoolean(mContext,
Prefs.Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED, /* defaultValue= */ false);
}
@After
public void tearDown() throws Exception {
Prefs.putBoolean(mContext, Prefs.Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED,
mLastIsMoveToTucked);
}
@Test
@@ -81,10 +92,34 @@ public class MenuAnimationControllerTest extends SysuiTestCase {
@Test
public void startGrowAnimation_menuCompletelyOpaque() {
mMenuAnimationController.startShrinkAnimation(null);
mMenuAnimationController.startShrinkAnimation(/* endAction= */ null);
mMenuAnimationController.startGrowAnimation();
assertThat(mMenuView.getAlpha()).isEqualTo(/* completelyOpaque */ 1.0f);
}
@Test
public void moveToEdgeAndHide_untucked_expectedSharedPreferenceValue() {
Prefs.putBoolean(mContext, Prefs.Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED, /* value= */
false);
mMenuAnimationController.moveToEdgeAndHide();
final boolean isMoveToTucked = Prefs.getBoolean(mContext,
Prefs.Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED, /* defaultValue= */ false);
assertThat(isMoveToTucked).isTrue();
}
@Test
public void moveOutEdgeAndShow_tucked_expectedSharedPreferenceValue() {
Prefs.putBoolean(mContext, Prefs.Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED, /* value= */
true);
mMenuAnimationController.moveOutEdgeAndShow();
final boolean isMoveToTucked = Prefs.getBoolean(mContext,
Prefs.Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED, /* defaultValue= */ true);
assertThat(isMoveToTucked).isFalse();
}
}

View File

@@ -141,6 +141,7 @@ public class MenuViewLayerTest extends SysuiTestCase {
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, mLastEnabledAccessibilityServices,
UserHandle.USER_CURRENT);
mMenuView.updateMenuMoveToTucked(/* isMoveToTucked= */ false);
mMenuViewLayer.onDetachedFromWindow();
}