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

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

Merge "Support accessibility on embedded hierarchies (2/n)"

parents dc48d448 a459b199
Loading
Loading
Loading
Loading
+81 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.view;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Matrix;
import android.os.IBinder;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IAccessibilityEmbeddedConnection;

import java.lang.ref.WeakReference;

/**
 * This class is an interface this ViewRootImpl provides to the host view to the latter
 * can interact with the view hierarchy in SurfaceControlViewHost.
 *
 * @hide
 */
final class AccessibilityEmbeddedConnection extends IAccessibilityEmbeddedConnection.Stub {
    private final WeakReference<ViewRootImpl> mViewRootImpl;

    AccessibilityEmbeddedConnection(ViewRootImpl viewRootImpl) {
        mViewRootImpl = new WeakReference<>(viewRootImpl);
    }

    @Override
    public @Nullable IBinder associateEmbeddedHierarchy(@NonNull IBinder host, int hostViewId) {
        final ViewRootImpl viewRootImpl = mViewRootImpl.get();
        if (viewRootImpl != null) {
            final AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(
                    viewRootImpl.mContext);
            viewRootImpl.mAttachInfo.mLeashedParentToken = host;
            viewRootImpl.mAttachInfo.mLeashedParentAccessibilityViewId = hostViewId;
            if (accessibilityManager.isEnabled()) {
                accessibilityManager.associateEmbeddedHierarchy(host, viewRootImpl.mLeashToken);
            }
            return viewRootImpl.mLeashToken;
        }
        return null;
    }

    @Override
    public void disassociateEmbeddedHierarchy() {
        final ViewRootImpl viewRootImpl = mViewRootImpl.get();
        if (viewRootImpl != null) {
            final AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(
                    viewRootImpl.mContext);
            viewRootImpl.mAttachInfo.mLeashedParentToken = null;
            viewRootImpl.mAttachInfo.mLeashedParentAccessibilityViewId = View.NO_ID;
            viewRootImpl.mAttachInfo.mLocationInParentDisplay.set(0, 0);
            if (accessibilityManager.isEnabled()) {
                accessibilityManager.disassociateEmbeddedHierarchy(viewRootImpl.mLeashToken);
            }
        }
    }

    @Override
    public void setScreenMatrix(float[] matrixValues) {
        final ViewRootImpl viewRootImpl = mViewRootImpl.get();
        if (viewRootImpl != null) {
            // TODO(b/148821260): Implement the rest of matrix values.
            viewRootImpl.mAttachInfo.mLocationInParentDisplay.set(
                    (int) matrixValues[Matrix.MTRANS_X], (int) matrixValues[Matrix.MTRANS_Y]);
        }
    }
}
+32 −0
Original line number Diff line number Diff line
@@ -855,6 +855,36 @@ public final class AccessibilityInteractionController {
        return mViewRootImpl.mAttachInfo.mLocationInParentDisplay.equals(0, 0);
    }

    private void associateLeashedParentIfNeeded(List<AccessibilityNodeInfo> infos) {
        if (infos == null || shouldBypassAssociateLeashedParent()) {
            return;
        }
        final int infoCount = infos.size();
        for (int i = 0; i < infoCount; i++) {
            final AccessibilityNodeInfo info = infos.get(i);
            associateLeashedParentIfNeeded(info);
        }
    }

    private void associateLeashedParentIfNeeded(AccessibilityNodeInfo info) {
        if (info == null || shouldBypassAssociateLeashedParent()) {
            return;
        }
        // The node id of root node in embedded maybe not be ROOT_NODE_ID so we compare the id
        // with root view.
        if (mViewRootImpl.mView.getAccessibilityViewId()
                != AccessibilityNodeInfo.getAccessibilityViewId(info.getSourceNodeId())) {
            return;
        }
        info.setLeashedParent(mViewRootImpl.mAttachInfo.mLeashedParentToken,
                mViewRootImpl.mAttachInfo.mLeashedParentAccessibilityViewId);
    }

    private boolean shouldBypassAssociateLeashedParent() {
        return (mViewRootImpl.mAttachInfo.mLeashedParentToken == null
                && mViewRootImpl.mAttachInfo.mLeashedParentAccessibilityViewId == View.NO_ID);
    }

    private void applyAppScaleAndMagnificationSpecIfNeeded(AccessibilityNodeInfo info,
            MagnificationSpec spec) {
        if (info == null) {
@@ -914,6 +944,7 @@ public final class AccessibilityInteractionController {
            MagnificationSpec spec, Region interactiveRegion) {
        try {
            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
            associateLeashedParentIfNeeded(infos);
            adjustBoundsInScreenIfNeeded(infos);
            // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
            // then impact the visibility result, we need to adjust visibility before apply scale.
@@ -935,6 +966,7 @@ public final class AccessibilityInteractionController {
            MagnificationSpec spec, Region interactiveRegion) {
        try {
            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
            associateLeashedParentIfNeeded(info);
            adjustBoundsInScreenIfNeeded(info);
            // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
            // then impact the visibility result, we need to adjust visibility before apply scale.
+12 −0
Original line number Diff line number Diff line
@@ -28988,6 +28988,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
         */
        OnContentApplyWindowInsetsListener mContentOnApplyWindowInsetsListener;
        /**
         * The leash token of this view's parent when it's in an embedded hierarchy that is
         * re-parented to another window.
         */
        IBinder mLeashedParentToken;
        /**
         * The accessibility view id of this view's parent when it's in an embedded
         * hierarchy that is re-parented to another window.
         */
        int mLeashedParentAccessibilityViewId;
        /**
         * Creates a new set of attachment information with the specified
         * events handler and thread.
+22 −0
Original line number Diff line number Diff line
@@ -135,6 +135,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.accessibility.AccessibilityNodeProvider;
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityEmbeddedConnection;
import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
import android.view.animation.AccelerateDecelerateInterpolator;
@@ -355,6 +356,8 @@ public final class ViewRootImpl implements ViewParent,

    final W mWindow;

    final IBinder mLeashToken;

    final int mTargetSdkVersion;

    int mSeq;
@@ -652,6 +655,8 @@ public final class ViewRootImpl implements ViewParent,

    private final GestureExclusionTracker mGestureExclusionTracker = new GestureExclusionTracker();

    private IAccessibilityEmbeddedConnection mEmbeddedConnection;

    static final class SystemUiVisibilityInfo {
        int seq;
        int globalVisibility;
@@ -685,6 +690,7 @@ public final class ViewRootImpl implements ViewParent,
        mVisRect = new Rect();
        mWinFrame = new Rect();
        mWindow = new W(this);
        mLeashToken = new Binder();
        mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
        mViewVisibility = View.GONE;
        mTransparentRegion = new Region();
@@ -9157,6 +9163,10 @@ public final class ViewRootImpl implements ViewParent,
                        focusedView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
                    }
                }
                if (mAttachInfo.mLeashedParentToken != null) {
                    mAccessibilityManager.associateEmbeddedHierarchy(
                            mAttachInfo.mLeashedParentToken, mLeashToken);
                }
            } else {
                ensureNoConnection();
                mHandler.obtainMessage(MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST).sendToTarget();
@@ -9169,6 +9179,7 @@ public final class ViewRootImpl implements ViewParent,
            if (!registered) {
                mAttachInfo.mAccessibilityWindowId =
                        mAccessibilityManager.addAccessibilityInteractionConnection(mWindow,
                                mLeashToken,
                                mContext.getPackageName(),
                                new AccessibilityInteractionConnection(ViewRootImpl.this));
            }
@@ -9355,6 +9366,17 @@ public final class ViewRootImpl implements ViewParent,
        }
    }

    /**
     * Gets an accessibility embedded connection interface for this ViewRootImpl.
     * @hide
     */
    public IAccessibilityEmbeddedConnection getEmbeddedConnection() {
        if (mEmbeddedConnection == null) {
            mEmbeddedConnection = new AccessibilityEmbeddedConnection(ViewRootImpl.this);
        }
        return mEmbeddedConnection;
    }

    private class SendWindowContentChangedAccessibilityEvent implements Runnable {
        private int mChangeTypes = 0;

+48 −3
Original line number Diff line number Diff line
@@ -1085,6 +1085,50 @@ public final class AccessibilityManager {
        }
    }

    /**
     * Associate the connection between the host View and the embedded SurfaceControlViewHost.
     *
     * @hide
     */
    public void associateEmbeddedHierarchy(@NonNull IBinder host, @NonNull IBinder embedded) {
        final IAccessibilityManager service;
        synchronized (mLock) {
            service = getServiceLocked();
            if (service == null) {
                return;
            }
        }
        try {
            service.associateEmbeddedHierarchy(host, embedded);
        } catch (RemoteException e) {
            return;
        }
    }

    /**
     * Disassociate the connection between the host View and the embedded SurfaceControlViewHost.
     * The given token could be either from host side or embedded side.
     *
     * @hide
     */
    public void disassociateEmbeddedHierarchy(@NonNull IBinder token) {
        if (token == null) {
            return;
        }
        final IAccessibilityManager service;
        synchronized (mLock) {
            service = getServiceLocked();
            if (service == null) {
                return;
            }
        }
        try {
            service.disassociateEmbeddedHierarchy(token);
        } catch (RemoteException e) {
            return;
        }
    }

    /**
     * Sets the current state and notifies listeners, if necessary.
     *
@@ -1147,11 +1191,12 @@ public final class AccessibilityManager {
    /**
     * Adds an accessibility interaction connection interface for a given window.
     * @param windowToken The window token to which a connection is added.
     * @param leashToken The leash token to which a connection is added.
     * @param connection The connection.
     *
     * @hide
     */
    public int addAccessibilityInteractionConnection(IWindow windowToken,
    public int addAccessibilityInteractionConnection(IWindow windowToken, IBinder leashToken,
            String packageName, IAccessibilityInteractionConnection connection) {
        final IAccessibilityManager service;
        final int userId;
@@ -1163,8 +1208,8 @@ public final class AccessibilityManager {
            userId = mUserId;
        }
        try {
            return service.addAccessibilityInteractionConnection(windowToken, connection,
                    packageName, userId);
            return service.addAccessibilityInteractionConnection(windowToken, leashToken,
                    connection, packageName, userId);
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error while adding an accessibility interaction connection. ", re);
        }
Loading