release-request-951b3a8b-6c0c-4d2e-8af4-1c3f7e209f66-for-git_oc-release-4006899 snap-temp-L39600000063784275

Change-Id: I9f7b7d3665476fe242d569c132ade944e14e827d
diff --git a/library/eclair-mr1/src/com/android/setupwizardlib/util/LinkAccessibilityHelper.java b/library/eclair-mr1/src/com/android/setupwizardlib/util/LinkAccessibilityHelper.java
index e6fa497..3866551 100644
--- a/library/eclair-mr1/src/com/android/setupwizardlib/util/LinkAccessibilityHelper.java
+++ b/library/eclair-mr1/src/com/android/setupwizardlib/util/LinkAccessibilityHelper.java
@@ -16,14 +16,21 @@
 
 package com.android.setupwizardlib.util;
 
+import static android.support.v4.os.BuildCompat.isAtLeastO;
+
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.support.v4.view.AccessibilityDelegateCompat;
 import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat;
 import android.support.v4.widget.ExploreByTouchHelper;
 import android.text.Layout;
 import android.text.Spanned;
 import android.text.style.ClickableSpan;
 import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.TextView;
 
@@ -32,6 +39,10 @@
 /**
  * An accessibility delegate that allows {@link android.text.style.ClickableSpan} to be focused and
  * clicked by accessibility services.
+ * <p>
+ * <strong>Note: </strong> From Android O on, there is native support for ClickableSpan
+ * accessibility, so this class is not needed (and indeed has no effect.)
+ * </p>
  *
  * <p />Sample usage:
  * <pre>
@@ -54,19 +65,135 @@
  * @see com.android.setupwizardlib.view.RichTextView
  * @see android.support.v4.widget.ExploreByTouchHelper
  */
-public class LinkAccessibilityHelper extends ExploreByTouchHelper {
+public class LinkAccessibilityHelper extends AccessibilityDelegateCompat {
 
     private static final String TAG = "LinkAccessibilityHelper";
 
     private final TextView mView;
     private final Rect mTempRect = new Rect();
+    private final ExploreByTouchHelper mExploreByTouchHelper;
 
     public LinkAccessibilityHelper(TextView view) {
-        super(view);
+        if (!isAtLeastO()) {
+            // Pre-O, we essentially extend ExploreByTouchHelper to expose a virtual view hierarchy
+            mExploreByTouchHelper = new ExploreByTouchHelper(view) {
+                @Override
+                protected int getVirtualViewAt(float x, float y) {
+                    return this.getVirtualViewAt(x, y);
+                }
+
+                @Override
+                protected void getVisibleVirtualViews(List<Integer> virtualViewIds) {
+                    this.getVisibleVirtualViews(virtualViewIds);
+                }
+
+                @Override
+                protected void onPopulateEventForVirtualView(int virtualViewId,
+                        AccessibilityEvent event) {
+                    this.onPopulateEventForVirtualView(virtualViewId, event);
+                }
+
+                @Override
+                protected void onPopulateNodeForVirtualView(int virtualViewId,
+                        AccessibilityNodeInfoCompat infoCompat) {
+                    this.onPopulateNodeForVirtualView(virtualViewId, infoCompat);
+
+                }
+
+                @Override
+                protected boolean onPerformActionForVirtualView(int virtualViewId, int action,
+                        Bundle arguments) {
+                    return this.onPerformActionForVirtualView(virtualViewId, action, arguments);
+                }
+            };
+        } else {
+            mExploreByTouchHelper = null;
+        }
         mView = view;
     }
 
     @Override
+    public void sendAccessibilityEvent(View host, int eventType) {
+        if (mExploreByTouchHelper != null) {
+            mExploreByTouchHelper.sendAccessibilityEvent(host, eventType);
+        } else {
+            super.sendAccessibilityEvent(host, eventType);
+        }
+    }
+
+    @Override
+    public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
+        if (mExploreByTouchHelper != null) {
+            mExploreByTouchHelper.sendAccessibilityEventUnchecked(host, event);
+        } else {
+            super.sendAccessibilityEventUnchecked(host, event);
+        }
+    }
+
+    @Override
+    public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
+        return (mExploreByTouchHelper != null)
+                ? mExploreByTouchHelper.dispatchPopulateAccessibilityEvent(host, event)
+                : super.dispatchPopulateAccessibilityEvent(host, event);
+    }
+
+    @Override
+    public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
+        if (mExploreByTouchHelper != null) {
+            mExploreByTouchHelper.onPopulateAccessibilityEvent(host, event);
+        } else {
+            super.onPopulateAccessibilityEvent(host, event);
+        }
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
+        if (mExploreByTouchHelper != null) {
+            mExploreByTouchHelper.onInitializeAccessibilityEvent(host, event);
+        } else {
+            super.onInitializeAccessibilityEvent(host, event);
+        }
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
+        if (mExploreByTouchHelper != null) {
+            mExploreByTouchHelper.onInitializeAccessibilityNodeInfo(host, info);
+        } else {
+            super.onInitializeAccessibilityNodeInfo(host, info);
+        }
+    }
+
+    @Override
+    public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
+            AccessibilityEvent event) {
+        return (mExploreByTouchHelper != null)
+                ? mExploreByTouchHelper.onRequestSendAccessibilityEvent(host, child, event)
+                : super.onRequestSendAccessibilityEvent(host, child, event);
+    }
+
+    @Override
+    public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View host) {
+        return (mExploreByTouchHelper != null)
+                ? mExploreByTouchHelper.getAccessibilityNodeProvider(host)
+                : super.getAccessibilityNodeProvider(host);
+    }
+
+    @Override
+    public boolean performAccessibilityAction(View host, int action, Bundle args) {
+        return (mExploreByTouchHelper != null)
+                ? mExploreByTouchHelper.performAccessibilityAction(host, action, args)
+                : super.performAccessibilityAction(host, action, args);
+    }
+
+    /**
+     * Delegated to {@link ExploreByTouchHelper}
+     */
+    public final boolean dispatchHoverEvent(MotionEvent event) {
+        return (mExploreByTouchHelper != null) ? mExploreByTouchHelper.dispatchHoverEvent(event)
+                : false;
+    }
+
     protected int getVirtualViewAt(float x, float y) {
         final CharSequence text = mView.getText();
         if (text instanceof Spanned) {
@@ -78,10 +205,9 @@
                 return spannedText.getSpanStart(linkSpan);
             }
         }
-        return INVALID_ID;
+        return ExploreByTouchHelper.INVALID_ID;
     }
 
-    @Override
     protected void getVisibleVirtualViews(List<Integer> virtualViewIds) {
         final CharSequence text = mView.getText();
         if (text instanceof Spanned) {
@@ -94,7 +220,6 @@
         }
     }
 
-    @Override
     protected void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) {
         final ClickableSpan span = getSpanForOffset(virtualViewId);
         if (span != null) {
@@ -105,7 +230,6 @@
         }
     }
 
-    @Override
     protected void onPopulateNodeForVirtualView(int virtualViewId,
             AccessibilityNodeInfoCompat info) {
         final ClickableSpan span = getSpanForOffset(virtualViewId);
@@ -126,7 +250,6 @@
         info.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
     }
 
-    @Override
     protected boolean onPerformActionForVirtualView(int virtualViewId, int action,
             Bundle arguments) {
         if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) {
diff --git a/library/eclair-mr1/test/instrumentation/src/com/android/setupwizardlib/test/LinkAccessibilityHelperTest.java b/library/eclair-mr1/test/instrumentation/src/com/android/setupwizardlib/test/LinkAccessibilityHelperTest.java
index a1d01fd..e2c492a 100644
--- a/library/eclair-mr1/test/instrumentation/src/com/android/setupwizardlib/test/LinkAccessibilityHelperTest.java
+++ b/library/eclair-mr1/test/instrumentation/src/com/android/setupwizardlib/test/LinkAccessibilityHelperTest.java
@@ -16,6 +16,8 @@
 
 package com.android.setupwizardlib.test;
 
+import static android.support.v4.os.BuildCompat.isAtLeastO;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -57,6 +59,7 @@
 
     @Test
     public void testGetVirtualViewAt() {
+        if (isAtLeastO()) return;
         initTextView();
         final int virtualViewId = mHelper.getVirtualViewAt(dp2Px(15), dp2Px(10));
         assertEquals("Virtual view ID should be 1", 1, virtualViewId);
@@ -64,6 +67,7 @@
 
     @Test
     public void testGetVirtualViewAtHost() {
+        if (isAtLeastO()) return;
         initTextView();
         final int virtualViewId = mHelper.getVirtualViewAt(dp2Px(100), dp2Px(100));
         assertEquals("Virtual view ID should be INVALID_ID",
@@ -72,6 +76,7 @@
 
     @Test
     public void testGetVisibleVirtualViews() {
+        if (isAtLeastO()) return;
         initTextView();
         List<Integer> virtualViewIds = new ArrayList<>();
         mHelper.getVisibleVirtualViews(virtualViewIds);
@@ -82,6 +87,7 @@
 
     @Test
     public void testOnPopulateEventForVirtualView() {
+        if (isAtLeastO()) return;
         initTextView();
         AccessibilityEvent event = AccessibilityEvent.obtain();
         mHelper.onPopulateEventForVirtualView(1, event);
@@ -95,6 +101,7 @@
 
     @Test
     public void testOnPopulateEventForVirtualViewHost() {
+        if (isAtLeastO()) return;
         initTextView();
         AccessibilityEvent event = AccessibilityEvent.obtain();
         mHelper.onPopulateEventForVirtualView(ExploreByTouchHelper.INVALID_ID, event);
@@ -107,6 +114,7 @@
 
     @Test
     public void testOnPopulateNodeForVirtualView() {
+        if (isAtLeastO()) return;
         initTextView();
         AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain();
         mHelper.onPopulateNodeForVirtualView(1, info);
@@ -125,6 +133,7 @@
 
     @Test
     public void testNullLayout() {
+        if (isAtLeastO()) return;
         initTextView();
         // Setting the padding will cause the layout to be null-ed out.
         mTextView.setPadding(1, 1, 1, 1);
@@ -142,6 +151,7 @@
 
     @Test
     public void testRtlLayout() {
+        if (isAtLeastO()) return;
         SpannableStringBuilder ssb = new SpannableStringBuilder("מכונה בתרגום");
         ssb.setSpan(LINK_SPAN, 1, 2, 0 /* flags */);
         initTextView(ssb);
@@ -161,6 +171,7 @@
 
     @Test
     public void testMultilineLink() {
+        if (isAtLeastO()) return;
         SpannableStringBuilder ssb = new SpannableStringBuilder(
                 "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
                 + "Praesent accumsan efficitur eros eu porttitor.");
@@ -182,6 +193,7 @@
 
     @Test
     public void testRtlMultilineLink() {
+        if (isAtLeastO()) return;
         String iwLoremIpsum = "אחר על רביעי אקטואליה. לוח דת אחרות המקובל רומנית, מיזמים מועמדים "
                 + "האנציקלופדיה בה צ'ט. מתן מה שנורו לערוך ייִדיש, בקר או החול אנתרופולוגיה, עוד "
                 + "דפים המחשב מיזמים ב.";
@@ -205,6 +217,7 @@
 
     @Test
     public void testBidiMultilineLink() {
+        if (isAtLeastO()) return;
         String iwLoremIpsum = "אחר על רביעי אקטואליה. לוח דת אחרות המקובל רומנית, מיזמים מועמדים "
                 + "האנציקלופדיה בה צ'ט. מתן מה שנורו לערוך ייִדיש, בקר או החול אנתרופולוגיה, עוד "
                 + "דפים המחשב מיזמים ב.";