diff options
8 files changed, 91 insertions, 23 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 0fe18a647f95..1489fb9c051c 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9305,6 +9305,16 @@ public final class Settings { "accessibility_autoclick_delay"; /** + * Integer setting specifying the autoclick cursor area size (the radius of the autoclick + * ring indicator) when {@link #ACCESSIBILITY_AUTOCLICK_ENABLED} is set. + * + * @see #ACCESSIBILITY_AUTOCLICK_ENABLED + * @hide + */ + public static final String ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE = + "accessibility_autoclick_cursor_area_size"; + + /** * Whether or not larger size icons are used for the pointer of mouse/trackpad for * accessibility. * (0 = false, 1 = true) diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index fd57aec4180b..544f42b9acfa 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -148,6 +148,15 @@ public final class AccessibilityManager { /** @hide */ public static final int AUTOCLICK_DELAY_DEFAULT = 600; + /** @hide */ + public static final int AUTOCLICK_CURSOR_AREA_SIZE_DEFAULT = 60; + + /** @hide */ + public static final int AUTOCLICK_CURSOR_AREA_SIZE_MIN = 20; + + /** @hide */ + public static final int AUTOCLICK_CURSOR_AREA_SIZE_MAX = 100; + /** * Activity action: Launch UI to manage which accessibility service or feature is assigned * to the navigation bar Accessibility button. diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index 96d34a0230b3..4f7ba9388a1d 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -107,6 +107,8 @@ message SecureSettingsProto { optional SettingProto accessibility_key_gesture_targets = 59 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto hct_rect_prompt_status = 60 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto em_value = 61 [ (android.privacy).dest = DEST_AUTOMATIC ]; + // Settings for accessibility autoclick + optional SettingProto autoclick_cursor_area_size = 62 [ (android.privacy).dest = DEST_AUTOMATIC ]; } optional Accessibility accessibility = 2; diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index 1fc1f05ae149..dd28402d705f 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -91,6 +91,7 @@ public class SecureSettings { Settings.Secure.KEY_REPEAT_TIMEOUT_MS, Settings.Secure.KEY_REPEAT_DELAY_MS, Settings.Secure.CAMERA_GESTURE_DISABLED, + Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE, Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY, Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index d0e88d5d6a3c..b01f6229af16 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -140,6 +140,8 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.KEY_REPEAT_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.KEY_REPEAT_DELAY_MS, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.CAMERA_GESTURE_DISABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put( + Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.ACCESSIBILITY_AUTOCLICK_DELAY, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.ACCESSIBILITY_LARGE_POINTER_ICON, BOOLEAN_VALIDATOR); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index dedd7ebd1ef7..5ad4b8a6dffe 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -1715,6 +1715,9 @@ class SettingsProtoDumpUtil { Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, SecureSettingsProto.Accessibility.ENABLED_ACCESSIBILITY_SERVICES); dumpSetting(s, p, + Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE, + SecureSettingsProto.Accessibility.AUTOCLICK_CURSOR_AREA_SIZE); + dumpSetting(s, p, Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED, SecureSettingsProto.Accessibility.AUTOCLICK_ENABLED); dumpSetting(s, p, diff --git a/services/accessibility/java/com/android/server/accessibility/AutoclickController.java b/services/accessibility/java/com/android/server/accessibility/AutoclickController.java index e3d7062ddb4e..b94fa2f59162 100644 --- a/services/accessibility/java/com/android/server/accessibility/AutoclickController.java +++ b/services/accessibility/java/com/android/server/accessibility/AutoclickController.java @@ -22,6 +22,7 @@ import static com.android.server.accessibility.AutoclickIndicatorView.SHOW_INDIC import android.accessibilityservice.AccessibilityTrace; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; @@ -69,7 +70,7 @@ public class AutoclickController extends BaseEventStreamTransformation { // Lazily created on the first mouse motion event. private ClickScheduler mClickScheduler; - private ClickDelayObserver mClickDelayObserver; + private AutoclickSettingsObserver mAutoclickSettingsObserver; private AutoclickIndicatorScheduler mAutoclickIndicatorScheduler; private AutoclickIndicatorView mAutoclickIndicatorView; private WindowManager mWindowManager; @@ -89,14 +90,17 @@ public class AutoclickController extends BaseEventStreamTransformation { if (event.isFromSource(InputDevice.SOURCE_MOUSE)) { if (mClickScheduler == null) { Handler handler = new Handler(mContext.getMainLooper()); - mClickScheduler = - new ClickScheduler(handler, AccessibilityManager.AUTOCLICK_DELAY_DEFAULT); - mClickDelayObserver = new ClickDelayObserver(mUserId, handler); - mClickDelayObserver.start(mContext.getContentResolver(), mClickScheduler); - if (Flags.enableAutoclickIndicator()) { initiateAutoclickIndicator(handler); } + + mClickScheduler = + new ClickScheduler(handler, AccessibilityManager.AUTOCLICK_DELAY_DEFAULT); + mAutoclickSettingsObserver = new AutoclickSettingsObserver(mUserId, handler); + mAutoclickSettingsObserver.start( + mContext.getContentResolver(), + mClickScheduler, + mAutoclickIndicatorScheduler); } handleMouseMotion(event, policyFlags); @@ -156,9 +160,9 @@ public class AutoclickController extends BaseEventStreamTransformation { @Override public void onDestroy() { - if (mClickDelayObserver != null) { - mClickDelayObserver.stop(); - mClickDelayObserver = null; + if (mAutoclickSettingsObserver != null) { + mAutoclickSettingsObserver.stop(); + mAutoclickSettingsObserver = null; } if (mClickScheduler != null) { mClickScheduler.cancel(); @@ -191,19 +195,24 @@ public class AutoclickController extends BaseEventStreamTransformation { } /** - * Observes setting value for autoclick delay, and updates ClickScheduler delay whenever the - * setting value changes. + * Observes autoclick setting values, and updates ClickScheduler delay and indicator size + * whenever the setting value changes. */ - final private static class ClickDelayObserver extends ContentObserver { + final private static class AutoclickSettingsObserver extends ContentObserver { /** URI used to identify the autoclick delay setting with content resolver. */ private final Uri mAutoclickDelaySettingUri = Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY); + /** URI used to identify the autoclick cursor area size setting with content resolver. */ + private final Uri mAutoclickCursorAreaSizeSettingUri = + Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE); + private ContentResolver mContentResolver; private ClickScheduler mClickScheduler; + private AutoclickIndicatorScheduler mAutoclickIndicatorScheduler; private final int mUserId; - public ClickDelayObserver(int userId, Handler handler) { + public AutoclickSettingsObserver(int userId, Handler handler) { super(handler); mUserId = userId; } @@ -216,11 +225,13 @@ public class AutoclickController extends BaseEventStreamTransformation { * changes. * @param clickScheduler ClickScheduler that should be updated when click delay changes. * @throws IllegalStateException If internal state is already setup when the method is - * called. + * called. * @throws NullPointerException If any of the arguments is a null pointer. */ - public void start(@NonNull ContentResolver contentResolver, - @NonNull ClickScheduler clickScheduler) { + public void start( + @NonNull ContentResolver contentResolver, + @NonNull ClickScheduler clickScheduler, + @Nullable AutoclickIndicatorScheduler autoclickIndicatorScheduler) { if (mContentResolver != null || mClickScheduler != null) { throw new IllegalStateException("Observer already started."); } @@ -233,11 +244,20 @@ public class AutoclickController extends BaseEventStreamTransformation { mContentResolver = contentResolver; mClickScheduler = clickScheduler; + mAutoclickIndicatorScheduler = autoclickIndicatorScheduler; mContentResolver.registerContentObserver(mAutoclickDelaySettingUri, false, this, mUserId); // Initialize mClickScheduler's initial delay value. onChange(true, mAutoclickDelaySettingUri); + + if (Flags.enableAutoclickIndicator()) { + // Register observer to listen to cursor area size setting change. + mContentResolver.registerContentObserver( + mAutoclickCursorAreaSizeSettingUri, false, this, mUserId); + // Initialize mAutoclickIndicatorView's initial size. + onChange(true, mAutoclickCursorAreaSizeSettingUri); + } } /** @@ -248,7 +268,7 @@ public class AutoclickController extends BaseEventStreamTransformation { */ public void stop() { if (mContentResolver == null || mClickScheduler == null) { - throw new IllegalStateException("ClickDelayObserver not started."); + throw new IllegalStateException("AutoclickSettingsObserver not started."); } mContentResolver.unregisterContentObserver(this); @@ -262,6 +282,18 @@ public class AutoclickController extends BaseEventStreamTransformation { AccessibilityManager.AUTOCLICK_DELAY_DEFAULT, mUserId); mClickScheduler.updateDelay(delay); } + if (Flags.enableAutoclickIndicator() + && mAutoclickCursorAreaSizeSettingUri.equals(uri)) { + int size = + Settings.Secure.getIntForUser( + mContentResolver, + Settings.Secure.ACCESSIBILITY_AUTOCLICK_CURSOR_AREA_SIZE, + AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_DEFAULT, + mUserId); + if (mAutoclickIndicatorScheduler != null) { + mAutoclickIndicatorScheduler.updateCursorAreaSize(size); + } + } } } @@ -317,6 +349,10 @@ public class AutoclickController extends BaseEventStreamTransformation { mScheduledShowIndicatorTime = -1; mHandler.removeCallbacks(this); } + + public void updateCursorAreaSize(int size) { + mAutoclickIndicatorView.setRadius(size); + } } /** diff --git a/services/accessibility/java/com/android/server/accessibility/AutoclickIndicatorView.java b/services/accessibility/java/com/android/server/accessibility/AutoclickIndicatorView.java index 816d8e456a9a..bf5015176f8c 100644 --- a/services/accessibility/java/com/android/server/accessibility/AutoclickIndicatorView.java +++ b/services/accessibility/java/com/android/server/accessibility/AutoclickIndicatorView.java @@ -16,6 +16,8 @@ package com.android.server.accessibility; +import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_DEFAULT; + import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; @@ -35,8 +37,7 @@ public class AutoclickIndicatorView extends View { static final int MINIMAL_ANIMATION_DURATION = 50; - // TODO(b/383901288): allow users to customize the indicator area. - static final float RADIUS = 50; + private float mRadius = AUTOCLICK_CURSOR_AREA_SIZE_DEFAULT; private final Paint mPaint; @@ -84,10 +85,10 @@ public class AutoclickIndicatorView extends View { if (showIndicator) { mRingRect.set( - /* left= */ mX - RADIUS, - /* top= */ mY - RADIUS, - /* right= */ mX + RADIUS, - /* bottom= */ mY + RADIUS); + /* left= */ mX - mRadius, + /* top= */ mY - mRadius, + /* right= */ mX + mRadius, + /* bottom= */ mY + mRadius); canvas.drawArc(mRingRect, /* startAngle= */ -90, mSweepAngle, false, mPaint); } } @@ -107,6 +108,10 @@ public class AutoclickIndicatorView extends View { mY = y; } + public void setRadius(int radius) { + mRadius = radius; + } + public void redrawIndicator() { showIndicator = true; invalidate(); |