diff options
author | Justin Klaassen <justinklaassen@google.com> | 2017-11-30 18:18:21 -0500 |
---|---|---|
committer | Justin Klaassen <justinklaassen@google.com> | 2017-11-30 18:18:21 -0500 |
commit | 4217cf85c20565a3446a662a7f07f26137b26b7f (patch) | |
tree | a0417b47a8cc802f6642f369fd2371165bec7b5c /android/view/accessibility | |
parent | 6a65f2da209bff03cb0eb6da309710ac6ee5026d (diff) | |
download | android-28-4217cf85c20565a3446a662a7f07f26137b26b7f.tar.gz |
Import Android SDK Platform P [4477446]
/google/data/ro/projects/android/fetch_artifact \
--bid 4477446 \
--target sdk_phone_armv7-win_sdk \
sdk-repo-linux-sources-4477446.zip
AndroidVersion.ApiLevel has been modified to appear as 28
Change-Id: If0559643d7c328e36aafca98f0c114641d33642c
Diffstat (limited to 'android/view/accessibility')
5 files changed, 157 insertions, 57 deletions
diff --git a/android/view/accessibility/AccessibilityCache.java b/android/view/accessibility/AccessibilityCache.java index d7851171..da5a1cd6 100644 --- a/android/view/accessibility/AccessibilityCache.java +++ b/android/view/accessibility/AccessibilityCache.java @@ -23,8 +23,6 @@ import android.util.LongArray; import android.util.LongSparseArray; import android.util.SparseArray; -import com.android.internal.annotations.VisibleForTesting; - import java.util.ArrayList; import java.util.List; @@ -33,8 +31,7 @@ import java.util.List; * It is updated when windows change or nodes change. * @hide */ -@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) -public final class AccessibilityCache { +public class AccessibilityCache { private static final String LOG_TAG = "AccessibilityCache"; @@ -329,6 +326,8 @@ public final class AccessibilityCache { final long oldParentId = oldInfo.getParentNodeId(); if (info.getParentNodeId() != oldParentId) { clearSubTreeLocked(windowId, oldParentId); + } else { + oldInfo.recycle(); } } diff --git a/android/view/accessibility/AccessibilityEvent.java b/android/view/accessibility/AccessibilityEvent.java index 5adea669..1d19a9f5 100644 --- a/android/view/accessibility/AccessibilityEvent.java +++ b/android/view/accessibility/AccessibilityEvent.java @@ -16,6 +16,7 @@ package android.view.accessibility; +import android.annotation.IntDef; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -23,6 +24,8 @@ import android.util.Pools.SynchronizedPool; import com.android.internal.util.BitUtils; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; @@ -709,6 +712,38 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par */ public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 0x00000004; + + /** @hide */ + @IntDef(flag = true, prefix = { "TYPE_" }, value = { + TYPE_VIEW_CLICKED, + TYPE_VIEW_LONG_CLICKED, + TYPE_VIEW_SELECTED, + TYPE_VIEW_FOCUSED, + TYPE_VIEW_TEXT_CHANGED, + TYPE_WINDOW_STATE_CHANGED, + TYPE_NOTIFICATION_STATE_CHANGED, + TYPE_VIEW_HOVER_ENTER, + TYPE_VIEW_HOVER_EXIT, + TYPE_TOUCH_EXPLORATION_GESTURE_START, + TYPE_TOUCH_EXPLORATION_GESTURE_END, + TYPE_WINDOW_CONTENT_CHANGED, + TYPE_VIEW_SCROLLED, + TYPE_VIEW_TEXT_SELECTION_CHANGED, + TYPE_ANNOUNCEMENT, + TYPE_VIEW_ACCESSIBILITY_FOCUSED, + TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED, + TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY, + TYPE_GESTURE_DETECTION_START, + TYPE_GESTURE_DETECTION_END, + TYPE_TOUCH_INTERACTION_START, + TYPE_TOUCH_INTERACTION_END, + TYPE_WINDOWS_CHANGED, + TYPE_VIEW_CONTEXT_CLICKED, + TYPE_ASSIST_READING_CONTEXT + }) + @Retention(RetentionPolicy.SOURCE) + public @interface EventType {} + /** * Mask for {@link AccessibilityEvent} all types. * @@ -741,7 +776,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par private static final SynchronizedPool<AccessibilityEvent> sPool = new SynchronizedPool<AccessibilityEvent>(MAX_POOL_SIZE); - private int mEventType; + private @EventType int mEventType; private CharSequence mPackageName; private long mEventTime; int mMovementGranularity; @@ -833,7 +868,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par * * @return The event type. */ - public int getEventType() { + public @EventType int getEventType() { return mEventType; } @@ -890,7 +925,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par * * @throws IllegalStateException If called from an AccessibilityService. */ - public void setEventType(int eventType) { + public void setEventType(@EventType int eventType) { enforceNotSealed(); mEventType = eventType; } diff --git a/android/view/accessibility/AccessibilityInteractionClient.java b/android/view/accessibility/AccessibilityInteractionClient.java index c3d6c695..d890f329 100644 --- a/android/view/accessibility/AccessibilityInteractionClient.java +++ b/android/view/accessibility/AccessibilityInteractionClient.java @@ -28,6 +28,8 @@ import android.util.Log; import android.util.LongSparseArray; import android.util.SparseArray; +import com.android.internal.annotations.VisibleForTesting; + import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -86,6 +88,12 @@ public final class AccessibilityInteractionClient private static final LongSparseArray<AccessibilityInteractionClient> sClients = new LongSparseArray<>(); + private static final SparseArray<IAccessibilityServiceConnection> sConnectionCache = + new SparseArray<>(); + + private static AccessibilityCache sAccessibilityCache = + new AccessibilityCache(new AccessibilityCache.AccessibilityNodeRefresher()); + private final AtomicInteger mInteractionIdCounter = new AtomicInteger(); private final Object mInstanceLock = new Object(); @@ -100,12 +108,6 @@ public final class AccessibilityInteractionClient private Message mSameThreadMessage; - private static final SparseArray<IAccessibilityServiceConnection> sConnectionCache = - new SparseArray<>(); - - private static final AccessibilityCache sAccessibilityCache = - new AccessibilityCache(new AccessibilityCache.AccessibilityNodeRefresher()); - /** * @return The client for the current thread. */ @@ -133,6 +135,50 @@ public final class AccessibilityInteractionClient } } + /** + * Gets a cached accessibility service connection. + * + * @param connectionId The connection id. + * @return The cached connection if such. + */ + public static IAccessibilityServiceConnection getConnection(int connectionId) { + synchronized (sConnectionCache) { + return sConnectionCache.get(connectionId); + } + } + + /** + * Adds a cached accessibility service connection. + * + * @param connectionId The connection id. + * @param connection The connection. + */ + public static void addConnection(int connectionId, IAccessibilityServiceConnection connection) { + synchronized (sConnectionCache) { + sConnectionCache.put(connectionId, connection); + } + } + + /** + * Removes a cached accessibility service connection. + * + * @param connectionId The connection id. + */ + public static void removeConnection(int connectionId) { + synchronized (sConnectionCache) { + sConnectionCache.remove(connectionId); + } + } + + /** + * This method is only for testing. Replacing the cache is a generally terrible idea, but + * tests need to be able to verify this class's interactions with the cache + */ + @VisibleForTesting + public static void setCache(AccessibilityCache cache) { + sAccessibilityCache = cache; + } + private AccessibilityInteractionClient() { /* reducing constructor visibility */ } @@ -300,7 +346,7 @@ public final class AccessibilityInteractionClient if (success) { List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear( interactionId); - finalizeAndCacheAccessibilityNodeInfos(infos, connectionId); + finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, bypassCache); if (infos != null && !infos.isEmpty()) { for (int i = 1; i < infos.size(); i++) { infos.get(i).recycle(); @@ -356,7 +402,7 @@ public final class AccessibilityInteractionClient List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear( interactionId); if (infos != null) { - finalizeAndCacheAccessibilityNodeInfos(infos, connectionId); + finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, false); return infos; } } @@ -409,7 +455,7 @@ public final class AccessibilityInteractionClient List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear( interactionId); if (infos != null) { - finalizeAndCacheAccessibilityNodeInfos(infos, connectionId); + finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, false); return infos; } } @@ -460,7 +506,7 @@ public final class AccessibilityInteractionClient if (success) { AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear( interactionId); - finalizeAndCacheAccessibilityNodeInfo(info, connectionId); + finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false); return info; } } else { @@ -509,7 +555,7 @@ public final class AccessibilityInteractionClient if (success) { AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear( interactionId); - finalizeAndCacheAccessibilityNodeInfo(info, connectionId); + finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false); return info; } } else { @@ -731,13 +777,17 @@ public final class AccessibilityInteractionClient * * @param info The info. * @param connectionId The id of the connection to the system. + * @param bypassCache Whether or not to bypass the cache. The node is added to the cache if + * this value is {@code false} */ private void finalizeAndCacheAccessibilityNodeInfo(AccessibilityNodeInfo info, - int connectionId) { + int connectionId, boolean bypassCache) { if (info != null) { info.setConnectionId(connectionId); info.setSealed(true); - sAccessibilityCache.add(info); + if (!bypassCache) { + sAccessibilityCache.add(info); + } } } @@ -746,14 +796,16 @@ public final class AccessibilityInteractionClient * * @param infos The {@link AccessibilityNodeInfo}s. * @param connectionId The id of the connection to the system. + * @param bypassCache Whether or not to bypass the cache. The nodes are added to the cache if + * this value is {@code false} */ private void finalizeAndCacheAccessibilityNodeInfos(List<AccessibilityNodeInfo> infos, - int connectionId) { + int connectionId, boolean bypassCache) { if (infos != null) { final int infosCount = infos.size(); for (int i = 0; i < infosCount; i++) { AccessibilityNodeInfo info = infos.get(i); - finalizeAndCacheAccessibilityNodeInfo(info, connectionId); + finalizeAndCacheAccessibilityNodeInfo(info, connectionId, bypassCache); } } } @@ -773,41 +825,6 @@ public final class AccessibilityInteractionClient } /** - * Gets a cached accessibility service connection. - * - * @param connectionId The connection id. - * @return The cached connection if such. - */ - public IAccessibilityServiceConnection getConnection(int connectionId) { - synchronized (sConnectionCache) { - return sConnectionCache.get(connectionId); - } - } - - /** - * Adds a cached accessibility service connection. - * - * @param connectionId The connection id. - * @param connection The connection. - */ - public void addConnection(int connectionId, IAccessibilityServiceConnection connection) { - synchronized (sConnectionCache) { - sConnectionCache.put(connectionId, connection); - } - } - - /** - * Removes a cached accessibility service connection. - * - * @param connectionId The connection id. - */ - public void removeConnection(int connectionId) { - synchronized (sConnectionCache) { - sConnectionCache.remove(connectionId); - } - } - - /** * Checks whether the infos are a fully connected tree with no duplicates. * * @param infos The result list to check. diff --git a/android/view/accessibility/AccessibilityManager.java b/android/view/accessibility/AccessibilityManager.java index 35f6acba..0375635f 100644 --- a/android/view/accessibility/AccessibilityManager.java +++ b/android/view/accessibility/AccessibilityManager.java @@ -24,6 +24,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SystemService; +import android.annotation.TestApi; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; @@ -187,6 +188,7 @@ public final class AccessibilityManager { * * @hide */ + @TestApi public interface AccessibilityServicesStateChangeListener { /** @@ -452,6 +454,18 @@ public final class AccessibilityManager { } /** + * Returns whether there are observers registered for this event type. If + * this method returns false you shuold not generate events of this type + * to conserve resources. + * + * @param type The event type. + * @return Whether the event is being observed. + */ + public boolean isObservedEventType(@AccessibilityEvent.EventType int type) { + return mIsEnabled && (mRelevantEventTypes & type) != 0; + } + + /** * Requests feedback interruption from all accessibility services. */ public void interrupt() { @@ -683,6 +697,7 @@ public final class AccessibilityManager { * for a callback on the process's main handler. * @hide */ + @TestApi public void addAccessibilityServicesStateChangeListener( @NonNull AccessibilityServicesStateChangeListener listener, @Nullable Handler handler) { synchronized (mLock) { @@ -698,6 +713,7 @@ public final class AccessibilityManager { * * @hide */ + @TestApi public void removeAccessibilityServicesStateChangeListener( @NonNull AccessibilityServicesStateChangeListener listener) { // Final CopyOnWriteArrayList - no lock needed. diff --git a/android/view/accessibility/AccessibilityNodeInfo.java b/android/view/accessibility/AccessibilityNodeInfo.java index 9bdd3ffc..faea9200 100644 --- a/android/view/accessibility/AccessibilityNodeInfo.java +++ b/android/view/accessibility/AccessibilityNodeInfo.java @@ -635,6 +635,8 @@ public class AccessibilityNodeInfo implements Parcelable { private static final int BOOLEAN_PROPERTY_IMPORTANCE = 0x0040000; + private static final int BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE = 0x0080000; + private static final int BOOLEAN_PROPERTY_IS_SHOWING_HINT = 0x0100000; /** @@ -2321,6 +2323,37 @@ public class AccessibilityNodeInfo implements Parcelable { } /** + * Returns whether the node is explicitly marked as a focusable unit by a screen reader. Note + * that {@code false} indicates that it is not explicitly marked, not that the node is not + * a focusable unit. Screen readers should generally used other signals, such as + * {@link #isFocusable()}, or the presence of text in a node, to determine what should receive + * focus. + * + * @return {@code true} if the node is specifically marked as a focusable unit for screen + * readers, {@code false} otherwise. + * + * @see View#isScreenReaderFocusable() + */ + public boolean isScreenReaderFocusable() { + return getBooleanProperty(BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE); + } + + /** + * Sets whether the node should be considered a focusable unit by a screen reader. + * <p> + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + * </p> + * + * @param screenReaderFocusable {@code true} if the node is a focusable unit for screen readers, + * {@code false} otherwise. + */ + public void setScreenReaderFocusable(boolean screenReaderFocusable) { + setBooleanProperty(BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE, screenReaderFocusable); + } + + /** * Returns whether the node's text represents a hint for the user to enter text. It should only * be {@code true} if the node has editable text. * |