Set the a11yNodeInfo unclickable if the TextView has a
LinkMovementMethod and there are no onClickListeners or
onLongClickListeners

A view with links shouldn't be exposing itself as clickable to
an a11yService if only the links are clickable. If a movement method is
set, the view turns both clickable and long-clickable. This has brought
a number of bugs where an a11yService will notify users the element is
clickable but performing the action does nothing.

We can't delete years-old code without breaking a lot of things, so try
to minimize the consequences by adding logic in onInitializeA11yNodeInfo.
Add checks so a view with links and no click listeners will be made un-clickable.

Bug: b/131758159
Test: Tested on several bugs with TalkBack, CtsAccessibilityTests, CtsTextTestCases,
CtsWidgetTestCases:TextViewTest
Change-Id: I53b695139ecea2c34d125e7077fd2077593adbe1
diff --git a/api/current.txt b/api/current.txt
index d3807fa..352638e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -50331,6 +50331,7 @@
     method public boolean hasFocusable();
     method public boolean hasNestedScrollingParent();
     method public boolean hasOnClickListeners();
+    method public boolean hasOnLongClickListeners();
     method @android.view.ViewDebug.ExportedProperty(category="drawing") public boolean hasOverlappingRendering();
     method public boolean hasPointerCapture();
     method @android.view.ViewDebug.ExportedProperty(category="layout") public boolean hasTransientState();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7eb3876..1d8b910 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7067,6 +7067,15 @@
     }
 
     /**
+     * Return whether this view has an attached OnLongClickListener.  Returns
+     * true if there is a listener, false if there is none.
+     */
+    public boolean hasOnLongClickListeners() {
+        ListenerInfo li = mListenerInfo;
+        return (li != null && li.mOnLongClickListener != null);
+    }
+
+    /**
      * Register a callback to be invoked when this view is context clicked. If the view is not
      * context clickable, it becomes context clickable.
      *
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index cdbec29..4da334b 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11735,6 +11735,20 @@
         if (!isSingleLine()) {
             info.setMultiLine(true);
         }
+
+        // A view should not be exposed as clickable/long-clickable to a service because of a
+        // LinkMovementMethod.
+        if ((info.isClickable() || info.isLongClickable())
+                && mMovement instanceof LinkMovementMethod) {
+            if (!hasOnClickListeners()) {
+                info.setClickable(false);
+                info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK);
+            }
+            if (!hasOnLongClickListeners()) {
+                info.setLongClickable(false);
+                info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
+            }
+        }
     }
 
     @Override