Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f6493516 authored by Jackal Guo's avatar Jackal Guo Committed by Android (Google) Code Review
Browse files

Merge "Accessibility actions should trigger ACTION_OUTSIDE"

parents 80058fd2 ac2b62e9
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.os.Message;
import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.text.style.AccessibilityClickableSpan;
import android.text.style.ClickableSpan;
import android.util.LongSparseArray;
@@ -702,6 +703,14 @@ final class AccessibilityInteractionController {
                    // Handle this hidden action separately
                    succeeded = handleClickableSpanActionUiThread(
                            target, virtualDescendantId, arguments);
                } else if (action == R.id.accessibilityActionOutsideTouch) {
                    // trigger ACTION_OUTSIDE to notify windows
                    final long now = SystemClock.uptimeMillis();
                    MotionEvent event = MotionEvent.obtain(now, now, MotionEvent.ACTION_OUTSIDE,
                            0, 0, 0);
                    event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
                    mViewRootImpl.dispatchInputEvent(event);
                    succeeded = true;
                } else {
                    AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
                    if (provider != null) {
+7 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ public class WindowInfo implements Parcelable {
    public CharSequence title;
    public long accessibilityIdOfAnchor = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
    public boolean inPictureInPicture;
    public boolean hasFlagWatchOutsideTouch;

    private WindowInfo() {
        /* do nothing - hide constructor */
@@ -74,6 +75,7 @@ public class WindowInfo implements Parcelable {
        window.title = other.title;
        window.accessibilityIdOfAnchor = other.accessibilityIdOfAnchor;
        window.inPictureInPicture = other.inPictureInPicture;
        window.hasFlagWatchOutsideTouch = other.hasFlagWatchOutsideTouch;

        if (other.childTokens != null && !other.childTokens.isEmpty()) {
            if (window.childTokens == null) {
@@ -108,6 +110,7 @@ public class WindowInfo implements Parcelable {
        parcel.writeCharSequence(title);
        parcel.writeLong(accessibilityIdOfAnchor);
        parcel.writeInt(inPictureInPicture ? 1 : 0);
        parcel.writeInt(hasFlagWatchOutsideTouch ? 1 : 0);

        if (childTokens != null && !childTokens.isEmpty()) {
            parcel.writeInt(1);
@@ -130,6 +133,8 @@ public class WindowInfo implements Parcelable {
        builder.append(", focused=").append(focused);
        builder.append(", children=").append(childTokens);
        builder.append(", accessibility anchor=").append(accessibilityIdOfAnchor);
        builder.append(", pictureInPicture=").append(inPictureInPicture);
        builder.append(", watchOutsideTouch=").append(hasFlagWatchOutsideTouch);
        builder.append(']');
        return builder.toString();
    }
@@ -145,6 +150,7 @@ public class WindowInfo implements Parcelable {
        title = parcel.readCharSequence();
        accessibilityIdOfAnchor = parcel.readLong();
        inPictureInPicture = (parcel.readInt() == 1);
        hasFlagWatchOutsideTouch = (parcel.readInt() == 1);

        final boolean hasChildren = (parcel.readInt() == 1);
        if (hasChildren) {
@@ -167,6 +173,7 @@ public class WindowInfo implements Parcelable {
            childTokens.clear();
        }
        inPictureInPicture = false;
        hasFlagWatchOutsideTouch = false;
    }

    public static final Parcelable.Creator<WindowInfo> CREATOR =
+3 −0
Original line number Diff line number Diff line
@@ -172,4 +172,7 @@

    <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_HIDE_TOOLTIP}. -->
    <item type="id" name="accessibilityActionHideTooltip" />

  <!-- Accessibility action to notify a window there is an outside touch. -->
  <item type="id" name="accessibilityActionOutsideTouch" />
</resources>
+1 −0
Original line number Diff line number Diff line
@@ -218,6 +218,7 @@
  <java-symbol type="id" name="selection_end_handle" />
  <java-symbol type="id" name="insertion_handle" />
  <java-symbol type="id" name="accessibilityActionClickOnClickableSpan" />
  <java-symbol type="id" name="accessibilityActionOutsideTouch" />
  <java-symbol type="id" name="camera" />
  <java-symbol type="id" name="mic" />
  <java-symbol type="id" name="overlay" />
+57 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY
import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
import static com.android.internal.util.FunctionalUtils.ignoreRemoteException;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import static android.accessibilityservice.AccessibilityService.SHOW_MODE_AUTO;
@@ -2621,6 +2623,38 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        return -1;
    }

    private void notifyOutsideTouchIfNeeded(int targetWindowId, int action, Bundle arguments,
            int interactionId, IAccessibilityInteractionConnectionCallback callback, int fetchFlags,
            int interrogatingPid, long interrogatingTid) {
        if (action != ACTION_CLICK && action != ACTION_LONG_CLICK) {
            return;
        }

        final List<Integer> outsideWindowsIds;
        final List<RemoteAccessibilityConnection> connectionList = new ArrayList<>();
        synchronized (mLock) {
            outsideWindowsIds = mSecurityPolicy.getWatchOutsideTouchWindowId(targetWindowId);
            for (int i = 0; i < outsideWindowsIds.size(); i++) {
                connectionList.add(getConnectionLocked(outsideWindowsIds.get(i)));
            }
        }
        for (int i = 0; i < connectionList.size(); i++) {
            final RemoteAccessibilityConnection connection = connectionList.get(i);
            if (connection != null) {
                try {
                    connection.mConnection.performAccessibilityAction(
                            AccessibilityNodeInfo.ROOT_ITEM_ID,
                            R.id.accessibilityActionOutsideTouch, arguments, interactionId,
                            callback, fetchFlags, interrogatingPid, interrogatingTid);
                } catch (RemoteException re) {
                    if (DEBUG) {
                        Slog.e(LOG_TAG, "Error calling performAccessibilityAction: " + re);
                    }
                }
            }
        }
    }

    @Override
    public void ensureWindowsAvailableTimed() {
        synchronized (mLock) {
@@ -2700,6 +2734,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
            mPowerManager.userActivity(SystemClock.uptimeMillis(),
                    PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);

            notifyOutsideTouchIfNeeded(resolvedWindowId, action, arguments, interactionId, callback,
                    fetchFlags, interrogatingPid, interrogatingTid);
            if (activityToken != null) {
                LocalServices.getService(ActivityTaskManagerInternal.class)
                        .setFocusedActivity(activityToken);
@@ -3027,6 +3063,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        public long mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;

        private boolean mTouchInteractionInProgress;
        private boolean mHasWatchOutsideTouchWindow;

        private boolean canDispatchAccessibilityEventLocked(AccessibilityEvent event) {
            final int eventType = event.getEventType();
@@ -3184,6 +3221,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
                mWindowInfoById.valueAt(i).recycle();
            }
            mWindowInfoById.clear();
            mHasWatchOutsideTouchWindow = false;

            mFocusedWindowId = INVALID_WINDOW_ID;
            if (!mTouchInteractionInProgress) {
@@ -3228,6 +3266,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
                                activeWindowGone = false;
                            }
                        }
                        if (!mHasWatchOutsideTouchWindow && windowInfo.hasFlagWatchOutsideTouch) {
                            mHasWatchOutsideTouchWindow = true;
                        }
                        mWindows.add(window);
                        mA11yWindowInfoById.put(windowId, window);
                        mWindowInfoById.put(windowId, WindowInfo.obtain(windowInfo));
@@ -3646,6 +3687,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
            return mWindowInfoById.get(windowId);
        }

        private List<Integer> getWatchOutsideTouchWindowId(int targetWindowId) {
            if (mWindowInfoById != null && mHasWatchOutsideTouchWindow) {
                final List<Integer> outsideWindowsId = new ArrayList<>();
                final WindowInfo targetWindow = mWindowInfoById.get(targetWindowId);
                for (int i = 0; i < mWindowInfoById.size(); i++) {
                    WindowInfo window = mWindowInfoById.valueAt(i);
                    if (window.layer < targetWindow.layer
                            && window.hasFlagWatchOutsideTouch) {
                        outsideWindowsId.add(mWindowInfoById.keyAt(i));
                    }
                }
                return outsideWindowsId;
            }
            return Collections.emptyList();
        }

        private AccessibilityWindowInfo getPictureInPictureWindow() {
            if (mWindows != null) {
                final int windowCount = mWindows.size();
Loading