Merge "Support accessibility on embedded hierarchies (2/n)"
This commit is contained in:
81
core/java/android/view/AccessibilityEmbeddedConnection.java
Normal file
81
core/java/android/view/AccessibilityEmbeddedConnection.java
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.accessibility;
|
||||
|
||||
/**
|
||||
* Interface used by host View to talk to the view root of the embedded SurfaceControlViewHost
|
||||
* that actually implements the functionality.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
interface IAccessibilityEmbeddedConnection {
|
||||
|
||||
IBinder associateEmbeddedHierarchy(IBinder hostToken, int sourceId);
|
||||
|
||||
void disassociateEmbeddedHierarchy();
|
||||
|
||||
oneway void setScreenMatrix(in float[] matrixValues);
|
||||
}
|
||||
@@ -47,7 +47,7 @@ interface IAccessibilityManager {
|
||||
@UnsupportedAppUsage
|
||||
List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, int userId);
|
||||
|
||||
int addAccessibilityInteractionConnection(IWindow windowToken,
|
||||
int addAccessibilityInteractionConnection(IWindow windowToken, IBinder leashToken,
|
||||
in IAccessibilityInteractionConnection connection,
|
||||
String packageName, int userId);
|
||||
|
||||
@@ -88,4 +88,8 @@ interface IAccessibilityManager {
|
||||
oneway void registerSystemAction(in RemoteAction action, int actionId);
|
||||
oneway void unregisterSystemAction(int actionId);
|
||||
oneway void setWindowMagnificationConnection(in IWindowMagnificationConnection connection);
|
||||
|
||||
void associateEmbeddedHierarchy(IBinder host, IBinder embedded);
|
||||
|
||||
void disassociateEmbeddedHierarchy(IBinder token);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user