diff options
| -rw-r--r-- | core/api/current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/view/accessibility/AccessibilityNodeInfo.java | 36 | ||||
| -rw-r--r-- | core/java/android/widget/TextView.java | 38 |
3 files changed, 67 insertions, 8 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index c31928dc013e..1db44ad2e4da 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -55443,6 +55443,7 @@ package android.view.accessibility { field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH"; field public static final int EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_MAX_LENGTH = 20000; // 0x4e20 field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX"; + field @FlaggedApi("android.view.accessibility.a11y_character_in_window_api") public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_IN_WINDOW_KEY = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_IN_WINDOW_KEY"; field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY"; field public static final int FLAG_PREFETCH_ANCESTORS = 1; // 0x1 field public static final int FLAG_PREFETCH_DESCENDANTS_BREADTH_FIRST = 16; // 0x10 diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index f70f7e6a59c0..7076682292e9 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -857,8 +857,10 @@ public class AccessibilityNodeInfo implements Parcelable { * <p> * The data can be retrieved from the {@code Bundle} returned by {@link #getExtras()} using this * string as a key for {@link Bundle#getParcelableArray(String, Class)}. The - * {@link android.graphics.RectF} will be null for characters that either do not exist or are - * off the screen. + * {@link android.graphics.RectF} will be {@code null} for characters that either do not exist + * or are off the screen. + * <p> + * Note that character locations returned are modified by changes in display magnification. * * {@see #refreshWithExtraData(String, Bundle)} */ @@ -866,6 +868,36 @@ public class AccessibilityNodeInfo implements Parcelable { "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY"; /** + * Key used to request and locate extra data for text character location in + * window coordinates. This key requests that an array of + * {@link android.graphics.RectF}s be added to the extras. This request is made + * with {@link #refreshWithExtraData(String, Bundle)}. The arguments taken by + * this request are two integers: + * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX} and + * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH}. The starting index + * must be valid inside the CharSequence returned by {@link #getText()}, and + * the length must be positive. + * <p> + * Providers may advertise that they support text characters in window coordinates using + * {@link #setAvailableExtraData(List)}. Services may check if an implementation supports text + * characters in window coordinates with {@link #getAvailableExtraData()}. + * <p> + * The data can be retrieved from the {@code Bundle} returned by + * {@link #getExtras()} using this string as a key for + * {@link Bundle#getParcelableArray(String, Class)}. The + * {@link android.graphics.RectF} will be {@code null} for characters that either do + * not exist or are outside of the window bounds. + * <p> + * Note that character locations in window bounds are not modified by + * changes in display magnification. + * + * {@see #refreshWithExtraData(String, Bundle)} + */ + @FlaggedApi(Flags.FLAG_A11Y_CHARACTER_IN_WINDOW_API) + public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_IN_WINDOW_KEY = + "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_IN_WINDOW_KEY"; + + /** * Integer argument specifying the start index of the requested text location data. Must be * valid inside the CharSequence returned by {@link #getText()}. * diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index ef941da0e32d..d7750bd412a3 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -26,6 +26,9 @@ import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_RENDER import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH; import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX; import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY; +import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_IN_WINDOW_KEY; +import static android.view.accessibility.Flags.FLAG_A11Y_CHARACTER_IN_WINDOW_API; +import static android.view.accessibility.Flags.a11yCharacterInWindowApi; import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION; import static android.view.inputmethod.EditorInfo.STYLUS_HANDWRITING_ENABLED_ANDROIDX_EXTRAS_KEY; import static android.view.inputmethod.Flags.initiationWithoutInputConnection; @@ -492,6 +495,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener /** Accessibility action start id for "smart" actions. @hide */ static final int ACCESSIBILITY_ACTION_SMART_START_ID = 0x10001000; + // Stable extra data keys supported by TextView. + private static final List<String> ACCESSIBILITY_EXTRA_DATA_KEYS = List.of( + EXTRA_DATA_RENDERING_INFO_KEY, + EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY + ); + + // Flagged and stable extra data keys supported by TextView. + @FlaggedApi(FLAG_A11Y_CHARACTER_IN_WINDOW_API) + private static final List<String> ACCESSIBILITY_EXTRA_DATA_KEYS_FLAGGED = List.of( + EXTRA_DATA_RENDERING_INFO_KEY, + EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY, + EXTRA_DATA_TEXT_CHARACTER_LOCATION_IN_WINDOW_KEY + ); + /** * @hide */ @@ -14207,10 +14224,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE); info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION); - info.setAvailableExtraData(Arrays.asList( - EXTRA_DATA_RENDERING_INFO_KEY, - EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY - )); + if (a11yCharacterInWindowApi()) { + info.setAvailableExtraData(ACCESSIBILITY_EXTRA_DATA_KEYS_FLAGGED); + } else { + info.setAvailableExtraData(ACCESSIBILITY_EXTRA_DATA_KEYS); + } info.setTextSelectable(isTextSelectable() || isTextEditable()); } else { info.setAvailableExtraData(Arrays.asList( @@ -14275,7 +14293,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public void addExtraDataToAccessibilityNodeInfo( AccessibilityNodeInfo info, String extraDataKey, Bundle arguments) { - if (arguments != null && extraDataKey.equals(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY)) { + boolean isCharacterLocationKey = extraDataKey.equals( + EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY); + boolean isCharacterLocationInWindowKey = (a11yCharacterInWindowApi() && extraDataKey.equals( + EXTRA_DATA_TEXT_CHARACTER_LOCATION_IN_WINDOW_KEY)); + if (arguments != null && (isCharacterLocationKey || isCharacterLocationInWindowKey)) { int positionInfoStartIndex = arguments.getInt( EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX, -1); int positionInfoLength = arguments.getInt( @@ -14297,7 +14319,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener RectF bounds = cursorAnchorInfo .getCharacterBounds(positionInfoStartIndex + i); if (bounds != null) { - mapRectFromViewToScreenCoords(bounds, true); + if (isCharacterLocationKey) { + mapRectFromViewToScreenCoords(bounds, true); + } else if (isCharacterLocationInWindowKey) { + mapRectFromViewToWindowCoords(bounds, true); + } boundingRects[i] = bounds; } } |