Loading core/java/android/text/TextUtils.java +15 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ import android.os.Parcelable; import android.os.SystemProperties; import android.provider.Settings; import android.text.style.AbsoluteSizeSpan; import android.text.style.AccessibilityClickableSpan; import android.text.style.AccessibilityURLSpan; import android.text.style.AlignmentSpan; import android.text.style.BackgroundColorSpan; import android.text.style.BulletSpan; Loading Loading @@ -621,7 +623,11 @@ public class TextUtils { /** @hide */ public static final int TTS_SPAN = 24; /** @hide */ public static final int LAST_SPAN = TTS_SPAN; public static final int ACCESSIBILITY_CLICKABLE_SPAN = 25; /** @hide */ public static final int ACCESSIBILITY_URL_SPAN = 26; /** @hide */ public static final int LAST_SPAN = ACCESSIBILITY_URL_SPAN; /** * Flatten a CharSequence and whatever styles can be copied across processes Loading Loading @@ -803,6 +809,14 @@ public class TextUtils { readSpan(p, sp, new TtsSpan(p)); break; case ACCESSIBILITY_CLICKABLE_SPAN: readSpan(p, sp, new AccessibilityClickableSpan(p)); break; case ACCESSIBILITY_URL_SPAN: readSpan(p, sp, new AccessibilityURLSpan(p)); break; default: throw new RuntimeException("bogus span encoding " + kind); } Loading core/java/android/text/style/AccessibilityClickableSpan.java 0 → 100644 +156 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.text.style; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.text.ParcelableSpan; import android.text.Spanned; import android.text.TextUtils; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import com.android.internal.R; import java.lang.ref.WeakReference; /** * {@link ClickableSpan} cannot be parceled, but accessibility services need to be able to cause * their callback handlers to be called. This class serves as a parcelable placeholder for the * real spans. * * This span is also passed back to an app's process when an accessibility service tries to click * it. It contains enough information to track down the original clickable span so it can be * called. * * @hide */ public class AccessibilityClickableSpan extends ClickableSpan implements ParcelableSpan { // The id of the span this one replaces private final int mOriginalClickableSpanId; // Only retain a weak reference to the node to avoid referencing cycles that could create memory // leaks. private WeakReference<AccessibilityNodeInfo> mAccessibilityNodeInfoRef; /** * @param originalClickableSpanId The id of the span this one replaces */ public AccessibilityClickableSpan(int originalClickableSpanId) { mOriginalClickableSpanId = originalClickableSpanId; } public AccessibilityClickableSpan(Parcel p) { mOriginalClickableSpanId = p.readInt(); } @Override public int getSpanTypeId() { return getSpanTypeIdInternal(); } @Override public int getSpanTypeIdInternal() { return TextUtils.ACCESSIBILITY_CLICKABLE_SPAN; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { writeToParcelInternal(dest, flags); } @Override public void writeToParcelInternal(Parcel dest, int flags) { dest.writeInt(mOriginalClickableSpanId); } /** * Find the ClickableSpan that matches the one used to create this object. * * @param text The text that contains the original ClickableSpan. * @return The ClickableSpan that matches this object, or {@code null} if no such object * can be found. */ public ClickableSpan findClickableSpan(CharSequence text) { if (!(text instanceof Spanned)) { return null; } Spanned sp = (Spanned) text; ClickableSpan[] os = sp.getSpans(0, text.length(), ClickableSpan.class); for (int i = 0; i < os.length; i++) { if (os[i].getId() == mOriginalClickableSpanId) { return os[i]; } } return null; } /** * Set the accessibilityNodeInfo that this placeholder belongs to. This node is not * included in the parceling logic, and must be set to allow the onClick handler to function. * * @param accessibilityNodeInfo The info this span is part of */ public void setAccessibilityNodeInfo(AccessibilityNodeInfo accessibilityNodeInfo) { mAccessibilityNodeInfoRef = new WeakReference<>(accessibilityNodeInfo); } /** * Perform the click from an accessibility service. Will not work unless * setAccessibilityNodeInfo is called with a properly initialized node. * * @param unused This argument is required by the superclass but is unused. The real view will * be determined by the AccessibilityNodeInfo. */ @Override public void onClick(View unused) { if (mAccessibilityNodeInfoRef == null) { return; } AccessibilityNodeInfo info = mAccessibilityNodeInfoRef.get(); if (info == null) { return; } Bundle arguments = new Bundle(); arguments.putParcelable(ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN, this); info.performAction(R.id.accessibilityActionClickOnClickableSpan, arguments); } public static final Parcelable.Creator<AccessibilityClickableSpan> CREATOR = new Parcelable.Creator<AccessibilityClickableSpan>() { @Override public AccessibilityClickableSpan createFromParcel(Parcel parcel) { return new AccessibilityClickableSpan(parcel); } @Override public AccessibilityClickableSpan[] newArray(int size) { return new AccessibilityClickableSpan[size]; } }; } core/java/android/text/style/AccessibilityURLSpan.java 0 → 100644 +79 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.text.style; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; /** * URLSpan's onClick method does not work from an accessibility service. This version of it does. * It is used to replace URLSpans in {@link AccessibilityNodeInfo#setText(CharSequence)} * @hide */ public class AccessibilityURLSpan extends URLSpan implements Parcelable { final AccessibilityClickableSpan mAccessibilityClickableSpan; /** * @param spanToReplace The original span */ public AccessibilityURLSpan(URLSpan spanToReplace) { super(spanToReplace.getURL()); mAccessibilityClickableSpan = new AccessibilityClickableSpan(spanToReplace.getId()); } public AccessibilityURLSpan(Parcel p) { super(p); mAccessibilityClickableSpan = new AccessibilityClickableSpan(p); } @Override public int getSpanTypeId() { return getSpanTypeIdInternal(); } @Override public int getSpanTypeIdInternal() { return TextUtils.ACCESSIBILITY_URL_SPAN; } @Override public void writeToParcel(Parcel dest, int flags) { writeToParcelInternal(dest, flags); } @Override public void writeToParcelInternal(Parcel dest, int flags) { super.writeToParcelInternal(dest, flags); mAccessibilityClickableSpan.writeToParcel(dest, flags); } @Override public void onClick(View unused) { mAccessibilityClickableSpan.onClick(unused); } /** * Delegated to AccessibilityClickableSpan * @param accessibilityNodeInfo */ public void setAccessibilityNodeInfo(AccessibilityNodeInfo accessibilityNodeInfo) { mAccessibilityClickableSpan.setAccessibilityNodeInfo(accessibilityNodeInfo); } } core/java/android/text/style/ClickableSpan.java +14 −1 Original line number Diff line number Diff line Loading @@ -26,6 +26,9 @@ import android.view.View; * be called. */ public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance { private static int sIdCounter = 0; private int mId = sIdCounter++; /** * Performs the click action associated with this span. Loading @@ -40,4 +43,14 @@ public abstract class ClickableSpan extends CharacterStyle implements UpdateAppe ds.setColor(ds.linkColor); ds.setUnderlineText(true); } /** * Get the unique ID for this span. * * @return The unique ID. * @hide */ public int getId() { return mId; } } core/java/android/view/AccessibilityInteractionController.java +54 −10 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.view; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; Loading @@ -24,8 +26,12 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; import android.text.TextUtils; import android.text.style.AccessibilityClickableSpan; import android.text.style.ClickableSpan; import android.util.LongSparseArray; import android.view.View.AttachInfo; import android.view.accessibility.AccessibilityInteractionClient; Loading @@ -33,6 +39,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeProvider; import android.view.accessibility.IAccessibilityInteractionConnectionCallback; import com.android.internal.R; import com.android.internal.os.SomeArgs; import com.android.internal.util.Predicate; Loading Loading @@ -655,19 +662,25 @@ final class AccessibilityInteractionController { target = mViewRootImpl.mView; } if (target != null && isShown(target)) { if (action == R.id.accessibilityActionClickOnClickableSpan) { // Handle this hidden action separately succeeded = handleClickableSpanActionUiThread( target, virtualDescendantId, arguments); } else { AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider(); if (provider != null) { if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { succeeded = provider.performAction(virtualDescendantId, action, arguments); } else { succeeded = provider.performAction(AccessibilityNodeProvider.HOST_VIEW_ID, action, arguments); succeeded = provider.performAction( AccessibilityNodeProvider.HOST_VIEW_ID, action, arguments); } } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { succeeded = target.performAccessibilityAction(action, arguments); } } } } finally { try { mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; Loading Loading @@ -816,6 +829,37 @@ final class AccessibilityInteractionController { return (appScale != 1.0f || (spec != null && !spec.isNop())); } private boolean handleClickableSpanActionUiThread( View view, int virtualDescendantId, Bundle arguments) { Parcelable span = arguments.getParcelable(ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN); if (!(span instanceof AccessibilityClickableSpan)) { return false; } // Find the original ClickableSpan if it's still on the screen AccessibilityNodeInfo infoWithSpan = null; AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider(); if (provider != null) { int idForNode = (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) ? AccessibilityNodeProvider.HOST_VIEW_ID : virtualDescendantId; infoWithSpan = provider.createAccessibilityNodeInfo(idForNode); } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { infoWithSpan = view.createAccessibilityNodeInfo(); } if (infoWithSpan == null) { return false; } // Click on the corresponding span ClickableSpan clickableSpan = ((AccessibilityClickableSpan) span).findClickableSpan( infoWithSpan.getOriginalText()); if (clickableSpan != null) { clickableSpan.onClick(view); return true; } return false; } /** * This class encapsulates a prefetching strategy for the accessibility APIs for * querying window content. It is responsible to prefetch a batch of Loading Loading
core/java/android/text/TextUtils.java +15 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ import android.os.Parcelable; import android.os.SystemProperties; import android.provider.Settings; import android.text.style.AbsoluteSizeSpan; import android.text.style.AccessibilityClickableSpan; import android.text.style.AccessibilityURLSpan; import android.text.style.AlignmentSpan; import android.text.style.BackgroundColorSpan; import android.text.style.BulletSpan; Loading Loading @@ -621,7 +623,11 @@ public class TextUtils { /** @hide */ public static final int TTS_SPAN = 24; /** @hide */ public static final int LAST_SPAN = TTS_SPAN; public static final int ACCESSIBILITY_CLICKABLE_SPAN = 25; /** @hide */ public static final int ACCESSIBILITY_URL_SPAN = 26; /** @hide */ public static final int LAST_SPAN = ACCESSIBILITY_URL_SPAN; /** * Flatten a CharSequence and whatever styles can be copied across processes Loading Loading @@ -803,6 +809,14 @@ public class TextUtils { readSpan(p, sp, new TtsSpan(p)); break; case ACCESSIBILITY_CLICKABLE_SPAN: readSpan(p, sp, new AccessibilityClickableSpan(p)); break; case ACCESSIBILITY_URL_SPAN: readSpan(p, sp, new AccessibilityURLSpan(p)); break; default: throw new RuntimeException("bogus span encoding " + kind); } Loading
core/java/android/text/style/AccessibilityClickableSpan.java 0 → 100644 +156 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.text.style; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.text.ParcelableSpan; import android.text.Spanned; import android.text.TextUtils; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import com.android.internal.R; import java.lang.ref.WeakReference; /** * {@link ClickableSpan} cannot be parceled, but accessibility services need to be able to cause * their callback handlers to be called. This class serves as a parcelable placeholder for the * real spans. * * This span is also passed back to an app's process when an accessibility service tries to click * it. It contains enough information to track down the original clickable span so it can be * called. * * @hide */ public class AccessibilityClickableSpan extends ClickableSpan implements ParcelableSpan { // The id of the span this one replaces private final int mOriginalClickableSpanId; // Only retain a weak reference to the node to avoid referencing cycles that could create memory // leaks. private WeakReference<AccessibilityNodeInfo> mAccessibilityNodeInfoRef; /** * @param originalClickableSpanId The id of the span this one replaces */ public AccessibilityClickableSpan(int originalClickableSpanId) { mOriginalClickableSpanId = originalClickableSpanId; } public AccessibilityClickableSpan(Parcel p) { mOriginalClickableSpanId = p.readInt(); } @Override public int getSpanTypeId() { return getSpanTypeIdInternal(); } @Override public int getSpanTypeIdInternal() { return TextUtils.ACCESSIBILITY_CLICKABLE_SPAN; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { writeToParcelInternal(dest, flags); } @Override public void writeToParcelInternal(Parcel dest, int flags) { dest.writeInt(mOriginalClickableSpanId); } /** * Find the ClickableSpan that matches the one used to create this object. * * @param text The text that contains the original ClickableSpan. * @return The ClickableSpan that matches this object, or {@code null} if no such object * can be found. */ public ClickableSpan findClickableSpan(CharSequence text) { if (!(text instanceof Spanned)) { return null; } Spanned sp = (Spanned) text; ClickableSpan[] os = sp.getSpans(0, text.length(), ClickableSpan.class); for (int i = 0; i < os.length; i++) { if (os[i].getId() == mOriginalClickableSpanId) { return os[i]; } } return null; } /** * Set the accessibilityNodeInfo that this placeholder belongs to. This node is not * included in the parceling logic, and must be set to allow the onClick handler to function. * * @param accessibilityNodeInfo The info this span is part of */ public void setAccessibilityNodeInfo(AccessibilityNodeInfo accessibilityNodeInfo) { mAccessibilityNodeInfoRef = new WeakReference<>(accessibilityNodeInfo); } /** * Perform the click from an accessibility service. Will not work unless * setAccessibilityNodeInfo is called with a properly initialized node. * * @param unused This argument is required by the superclass but is unused. The real view will * be determined by the AccessibilityNodeInfo. */ @Override public void onClick(View unused) { if (mAccessibilityNodeInfoRef == null) { return; } AccessibilityNodeInfo info = mAccessibilityNodeInfoRef.get(); if (info == null) { return; } Bundle arguments = new Bundle(); arguments.putParcelable(ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN, this); info.performAction(R.id.accessibilityActionClickOnClickableSpan, arguments); } public static final Parcelable.Creator<AccessibilityClickableSpan> CREATOR = new Parcelable.Creator<AccessibilityClickableSpan>() { @Override public AccessibilityClickableSpan createFromParcel(Parcel parcel) { return new AccessibilityClickableSpan(parcel); } @Override public AccessibilityClickableSpan[] newArray(int size) { return new AccessibilityClickableSpan[size]; } }; }
core/java/android/text/style/AccessibilityURLSpan.java 0 → 100644 +79 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.text.style; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; /** * URLSpan's onClick method does not work from an accessibility service. This version of it does. * It is used to replace URLSpans in {@link AccessibilityNodeInfo#setText(CharSequence)} * @hide */ public class AccessibilityURLSpan extends URLSpan implements Parcelable { final AccessibilityClickableSpan mAccessibilityClickableSpan; /** * @param spanToReplace The original span */ public AccessibilityURLSpan(URLSpan spanToReplace) { super(spanToReplace.getURL()); mAccessibilityClickableSpan = new AccessibilityClickableSpan(spanToReplace.getId()); } public AccessibilityURLSpan(Parcel p) { super(p); mAccessibilityClickableSpan = new AccessibilityClickableSpan(p); } @Override public int getSpanTypeId() { return getSpanTypeIdInternal(); } @Override public int getSpanTypeIdInternal() { return TextUtils.ACCESSIBILITY_URL_SPAN; } @Override public void writeToParcel(Parcel dest, int flags) { writeToParcelInternal(dest, flags); } @Override public void writeToParcelInternal(Parcel dest, int flags) { super.writeToParcelInternal(dest, flags); mAccessibilityClickableSpan.writeToParcel(dest, flags); } @Override public void onClick(View unused) { mAccessibilityClickableSpan.onClick(unused); } /** * Delegated to AccessibilityClickableSpan * @param accessibilityNodeInfo */ public void setAccessibilityNodeInfo(AccessibilityNodeInfo accessibilityNodeInfo) { mAccessibilityClickableSpan.setAccessibilityNodeInfo(accessibilityNodeInfo); } }
core/java/android/text/style/ClickableSpan.java +14 −1 Original line number Diff line number Diff line Loading @@ -26,6 +26,9 @@ import android.view.View; * be called. */ public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance { private static int sIdCounter = 0; private int mId = sIdCounter++; /** * Performs the click action associated with this span. Loading @@ -40,4 +43,14 @@ public abstract class ClickableSpan extends CharacterStyle implements UpdateAppe ds.setColor(ds.linkColor); ds.setUnderlineText(true); } /** * Get the unique ID for this span. * * @return The unique ID. * @hide */ public int getId() { return mId; } }
core/java/android/view/AccessibilityInteractionController.java +54 −10 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.view; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; Loading @@ -24,8 +26,12 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; import android.text.TextUtils; import android.text.style.AccessibilityClickableSpan; import android.text.style.ClickableSpan; import android.util.LongSparseArray; import android.view.View.AttachInfo; import android.view.accessibility.AccessibilityInteractionClient; Loading @@ -33,6 +39,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeProvider; import android.view.accessibility.IAccessibilityInteractionConnectionCallback; import com.android.internal.R; import com.android.internal.os.SomeArgs; import com.android.internal.util.Predicate; Loading Loading @@ -655,19 +662,25 @@ final class AccessibilityInteractionController { target = mViewRootImpl.mView; } if (target != null && isShown(target)) { if (action == R.id.accessibilityActionClickOnClickableSpan) { // Handle this hidden action separately succeeded = handleClickableSpanActionUiThread( target, virtualDescendantId, arguments); } else { AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider(); if (provider != null) { if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { succeeded = provider.performAction(virtualDescendantId, action, arguments); } else { succeeded = provider.performAction(AccessibilityNodeProvider.HOST_VIEW_ID, action, arguments); succeeded = provider.performAction( AccessibilityNodeProvider.HOST_VIEW_ID, action, arguments); } } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { succeeded = target.performAccessibilityAction(action, arguments); } } } } finally { try { mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0; Loading Loading @@ -816,6 +829,37 @@ final class AccessibilityInteractionController { return (appScale != 1.0f || (spec != null && !spec.isNop())); } private boolean handleClickableSpanActionUiThread( View view, int virtualDescendantId, Bundle arguments) { Parcelable span = arguments.getParcelable(ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN); if (!(span instanceof AccessibilityClickableSpan)) { return false; } // Find the original ClickableSpan if it's still on the screen AccessibilityNodeInfo infoWithSpan = null; AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider(); if (provider != null) { int idForNode = (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) ? AccessibilityNodeProvider.HOST_VIEW_ID : virtualDescendantId; infoWithSpan = provider.createAccessibilityNodeInfo(idForNode); } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { infoWithSpan = view.createAccessibilityNodeInfo(); } if (infoWithSpan == null) { return false; } // Click on the corresponding span ClickableSpan clickableSpan = ((AccessibilityClickableSpan) span).findClickableSpan( infoWithSpan.getOriginalText()); if (clickableSpan != null) { clickableSpan.onClick(view); return true; } return false; } /** * This class encapsulates a prefetching strategy for the accessibility APIs for * querying window content. It is responsible to prefetch a batch of Loading