summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java85
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java33
2 files changed, 109 insertions, 9 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java
index c74e4f5cd8d8..23c5cc4111f6 100644
--- a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java
+++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java
@@ -46,6 +46,11 @@ public class AutoclickTypePanel {
public static final int AUTOCLICK_TYPE_DRAG = 3;
public static final int AUTOCLICK_TYPE_SCROLL = 4;
+ public static final int CORNER_BOTTOM_RIGHT = 0;
+ public static final int CORNER_BOTTOM_LEFT = 1;
+ public static final int CORNER_TOP_LEFT = 2;
+ public static final int CORNER_TOP_RIGHT = 3;
+
// Types of click the AutoclickTypePanel supports.
@IntDef({
AUTOCLICK_TYPE_LEFT_CLICK,
@@ -56,6 +61,21 @@ public class AutoclickTypePanel {
})
public @interface AutoclickType {}
+ @IntDef({
+ CORNER_BOTTOM_RIGHT,
+ CORNER_BOTTOM_LEFT,
+ CORNER_TOP_LEFT,
+ CORNER_TOP_RIGHT
+ })
+ public @interface Corner {}
+
+ private static final @Corner int[] CORNER_ROTATION_ORDER = {
+ CORNER_BOTTOM_RIGHT,
+ CORNER_BOTTOM_LEFT,
+ CORNER_TOP_LEFT,
+ CORNER_TOP_RIGHT
+ };
+
// An interface exposed to {@link AutoclickController) to handle different actions on the panel,
// including changing autoclick type, pausing/resuming autoclick.
public interface ClickPanelControllerInterface {
@@ -79,6 +99,10 @@ public class AutoclickTypePanel {
// Whether autoclick is paused.
private boolean mPaused = false;
+ // Tracks the current corner position of the panel using an index into CORNER_ROTATION_ORDER
+ // array. This allows the panel to cycle through screen corners in a defined sequence when
+ // repositioned.
+ private int mCurrentCornerIndex = 0;
private final LinearLayout mLeftClickButton;
private final LinearLayout mRightClickButton;
@@ -86,6 +110,7 @@ public class AutoclickTypePanel {
private final LinearLayout mDragButton;
private final LinearLayout mScrollButton;
private final LinearLayout mPauseButton;
+ private final LinearLayout mPositionButton;
private LinearLayout mSelectedButton;
@@ -117,6 +142,7 @@ public class AutoclickTypePanel {
mScrollButton = mContentView.findViewById(R.id.accessibility_autoclick_scroll_layout);
mDragButton = mContentView.findViewById(R.id.accessibility_autoclick_drag_layout);
mPauseButton = mContentView.findViewById(R.id.accessibility_autoclick_pause_layout);
+ mPositionButton = mContentView.findViewById(R.id.accessibility_autoclick_position_layout);
initializeButtonState();
}
@@ -128,10 +154,8 @@ public class AutoclickTypePanel {
v -> togglePanelExpansion(AUTOCLICK_TYPE_DOUBLE_CLICK));
mScrollButton.setOnClickListener(v -> togglePanelExpansion(AUTOCLICK_TYPE_SCROLL));
mDragButton.setOnClickListener(v -> togglePanelExpansion(AUTOCLICK_TYPE_DRAG));
-
+ mPositionButton.setOnClickListener(v -> moveToNextCorner());
mPauseButton.setOnClickListener(v -> togglePause());
- // TODO(b/388847771): registers listener for position button and allows users to move the
- // panel to a different position.
// Initializes panel as collapsed state and only displays the left click button.
hideAllClickTypeButtons();
@@ -248,6 +272,46 @@ public class AutoclickTypePanel {
};
}
+ /** Moves the panel to the next corner in clockwise direction. */
+ private void moveToNextCorner() {
+ @Corner int nextCornerIndex = (mCurrentCornerIndex + 1) % CORNER_ROTATION_ORDER.length;
+ mCurrentCornerIndex = nextCornerIndex;
+
+ // getLayoutParams() will update the panel position based on current corner.
+ WindowManager.LayoutParams params = getLayoutParams();
+ mWindowManager.updateViewLayout(mContentView, params);
+ }
+
+ private void setPanelPositionForCorner(WindowManager.LayoutParams params, @Corner int corner) {
+ // TODO(b/396402941): Replace hardcoded pixel values with proper dimension calculations,
+ // Current values are experimental and may not work correctly across different device
+ // resolutions and configurations.
+ switch (corner) {
+ case CORNER_BOTTOM_RIGHT:
+ params.gravity = Gravity.END | Gravity.BOTTOM;
+ params.x = 15;
+ params.y = 90;
+ break;
+ case CORNER_BOTTOM_LEFT:
+ params.gravity = Gravity.START | Gravity.BOTTOM;
+ params.x = 15;
+ params.y = 90;
+ break;
+ case CORNER_TOP_LEFT:
+ params.gravity = Gravity.START | Gravity.TOP;
+ params.x = 15;
+ params.y = 30;
+ break;
+ case CORNER_TOP_RIGHT:
+ params.gravity = Gravity.END | Gravity.TOP;
+ params.x = 15;
+ params.y = 30;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid corner: " + corner);
+ }
+ }
+
@VisibleForTesting
boolean getExpansionStateForTesting() {
return mExpanded;
@@ -259,12 +323,19 @@ public class AutoclickTypePanel {
return mContentView;
}
+ @VisibleForTesting
+ @Corner
+ int getCurrentCornerIndexForTesting() {
+ return mCurrentCornerIndex;
+ }
+
/**
* Retrieves the layout params for AutoclickIndicatorView, used when it's added to the Window
* Manager.
*/
+ @VisibleForTesting
@NonNull
- private WindowManager.LayoutParams getLayoutParams() {
+ WindowManager.LayoutParams getLayoutParams() {
final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -277,11 +348,7 @@ public class AutoclickTypePanel {
mContext.getString(R.string.accessibility_autoclick_type_settings_panel_title);
layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
- // TODO(b/388847771): Compute position based on user interaction.
- layoutParams.x = 15;
- layoutParams.y = 90;
- layoutParams.gravity = Gravity.END | Gravity.BOTTOM;
-
+ setPanelPositionForCorner(layoutParams, mCurrentCornerIndex);
return layoutParams;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java
index b6d8e87d0780..f3016f4b17f9 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java
@@ -30,6 +30,7 @@ import android.graphics.drawable.GradientDrawable;
import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
import android.testing.TestableLooper;
+import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
@@ -64,6 +65,7 @@ public class AutoclickTypePanelTest {
private LinearLayout mDragButton;
private LinearLayout mScrollButton;
private LinearLayout mPauseButton;
+ private LinearLayout mPositionButton;
private @AutoclickType int mActiveClickType = AUTOCLICK_TYPE_LEFT_CLICK;
@@ -93,6 +95,7 @@ public class AutoclickTypePanelTest {
mScrollButton = contentView.findViewById(R.id.accessibility_autoclick_scroll_layout);
mDragButton = contentView.findViewById(R.id.accessibility_autoclick_drag_layout);
mPauseButton = contentView.findViewById(R.id.accessibility_autoclick_pause_layout);
+ mPositionButton = contentView.findViewById(R.id.accessibility_autoclick_position_layout);
}
@Test
@@ -175,9 +178,39 @@ public class AutoclickTypePanelTest {
assertThat(mActiveClickType).isEqualTo(AUTOCLICK_TYPE_SCROLL);
}
+ @Test
+ public void moveToNextCorner_positionButton_rotatesThroughAllPositions() {
+ // Define all positions in sequence
+ int[][] expectedPositions = {
+ {0, Gravity.END | Gravity.BOTTOM, /*x=*/ 15, /*y=*/ 90},
+ {1, Gravity.START | Gravity.BOTTOM, /*x=*/ 15, /*y=*/ 90},
+ {2, Gravity.START | Gravity.TOP, /*x=*/ 15, /*y=*/ 30},
+ {3, Gravity.END | Gravity.TOP, /*x=*/ 15, /*y=*/ 30},
+ {0, Gravity.END | Gravity.BOTTOM, /*x=*/ 15, /*y=*/ 90}
+ };
+
+ // Check initial position
+ verifyPanelPosition(expectedPositions[0]);
+
+ // Move through all corners.
+ for (int i = 1; i < expectedPositions.length; i++) {
+ mPositionButton.callOnClick();
+ verifyPanelPosition(expectedPositions[i]);
+ }
+ }
+
private void verifyButtonHasSelectedStyle(@NonNull LinearLayout button) {
GradientDrawable gradientDrawable = (GradientDrawable) button.getBackground();
assertThat(gradientDrawable.getColor().getDefaultColor())
.isEqualTo(mTestableContext.getColor(R.color.materialColorPrimary));
}
+
+ private void verifyPanelPosition(int[] expectedPosition) {
+ WindowManager.LayoutParams params = mAutoclickTypePanel.getLayoutParams();
+ assertThat(mAutoclickTypePanel.getCurrentCornerIndexForTesting()).isEqualTo(
+ expectedPosition[0]);
+ assertThat(params.gravity).isEqualTo(expectedPosition[1]);
+ assertThat(params.x).isEqualTo(expectedPosition[2]);
+ assertThat(params.y).isEqualTo(expectedPosition[3]);
+ }
}