diff options
9 files changed, 347 insertions, 123 deletions
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java index bd86a8d..29926ca 100644 --- a/core/java/android/view/AccessibilityInteractionController.java +++ b/core/java/android/view/AccessibilityInteractionController.java @@ -138,18 +138,26 @@ final class AccessibilityInteractionController { } public void findAccessibilityNodeInfoByAccessibilityIdClientThread( - long accessibilityNodeId, int interactionId, + long accessibilityNodeId, int windowLeft, int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, long interrogatingTid) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID; message.arg1 = flags; + SomeArgs args = mPool.acquire(); args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId); args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId); args.argi3 = interactionId; args.arg1 = callback; + + SomeArgs moreArgs = mPool.acquire(); + moreArgs.argi1 = windowLeft; + moreArgs.argi2 = windowTop; + args.arg2 = moreArgs; + message.obj = args; + // If the interrogation is performed by the same thread as the main UI // thread in this process, set the message as a static reference so // after this call completes the same thread but in the interrogating @@ -164,13 +172,21 @@ final class AccessibilityInteractionController { private void findAccessibilityNodeInfoByAccessibilityIdUiThread(Message message) { final int flags = message.arg1; + SomeArgs args = (SomeArgs) message.obj; final int accessibilityViewId = args.argi1; final int virtualDescendantId = args.argi2; final int interactionId = args.argi3; final IAccessibilityInteractionConnectionCallback callback = (IAccessibilityInteractionConnectionCallback) args.arg1; + + SomeArgs moreArgs = (SomeArgs) args.arg2; + mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1; + mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2; + + mPool.release(moreArgs); mPool.release(args); + List<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList; infos.clear(); try { @@ -200,17 +216,26 @@ final class AccessibilityInteractionController { } public void findAccessibilityNodeInfoByViewIdClientThread(long accessibilityNodeId, - int viewId, int interactionId, IAccessibilityInteractionConnectionCallback callback, - int flags, int interrogatingPid, long interrogatingTid) { + int viewId, int windowLeft, int windowTop, int interactionId, + IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, + long interrogatingTid) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID; message.arg1 = flags; message.arg2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId); + SomeArgs args = mPool.acquire(); args.argi1 = viewId; args.argi2 = interactionId; args.arg1 = callback; + + SomeArgs moreArgs = mPool.acquire(); + moreArgs.argi1 = windowLeft; + moreArgs.argi2 = windowTop; + args.arg2 = moreArgs; + message.obj = args; + // If the interrogation is performed by the same thread as the main UI // thread in this process, set the message as a static reference so // after this call completes the same thread but in the interrogating @@ -226,12 +251,20 @@ final class AccessibilityInteractionController { private void findAccessibilityNodeInfoByViewIdUiThread(Message message) { final int flags = message.arg1; final int accessibilityViewId = message.arg2; + SomeArgs args = (SomeArgs) message.obj; final int viewId = args.argi1; final int interactionId = args.argi2; final IAccessibilityInteractionConnectionCallback callback = (IAccessibilityInteractionConnectionCallback) args.arg1; + + SomeArgs moreArgs = (SomeArgs) args.arg2; + mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1; + mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2; + + mPool.release(moreArgs); mPool.release(args); + AccessibilityNodeInfo info = null; try { if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) { @@ -262,18 +295,27 @@ final class AccessibilityInteractionController { } public void findAccessibilityNodeInfosByTextClientThread(long accessibilityNodeId, - String text, int interactionId, IAccessibilityInteractionConnectionCallback callback, - int flags, int interrogatingPid, long interrogatingTid) { + String text, int windowLeft, int windowTop, int interactionId, + IAccessibilityInteractionConnectionCallback callback, int flags, + int interrogatingPid, long interrogatingTid) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT; message.arg1 = flags; + SomeArgs args = mPool.acquire(); args.arg1 = text; args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId); args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId); args.argi3 = interactionId; - args.arg2 = callback; + + SomeArgs moreArgs = mPool.acquire(); + moreArgs.arg1 = callback; + moreArgs.argi1 = windowLeft; + moreArgs.argi2 = windowTop; + args.arg2 = moreArgs; + message.obj = args; + // If the interrogation is performed by the same thread as the main UI // thread in this process, set the message as a static reference so // after this call completes the same thread but in the interrogating @@ -288,14 +330,22 @@ final class AccessibilityInteractionController { private void findAccessibilityNodeInfosByTextUiThread(Message message) { final int flags = message.arg1; + SomeArgs args = (SomeArgs) message.obj; final String text = (String) args.arg1; final int accessibilityViewId = args.argi1; final int virtualDescendantId = args.argi2; final int interactionId = args.argi3; + + SomeArgs moreArgs = (SomeArgs) args.arg2; final IAccessibilityInteractionConnectionCallback callback = - (IAccessibilityInteractionConnectionCallback) args.arg2; + (IAccessibilityInteractionConnectionCallback) moreArgs.arg1; + mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1; + mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2; + + mPool.release(moreArgs); mPool.release(args); + List<AccessibilityNodeInfo> infos = null; try { if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) { @@ -353,19 +403,27 @@ final class AccessibilityInteractionController { } } - public void findFocusClientThread(long accessibilityNodeId, int interactionId, int focusType, - IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid, - long interrogatingTid) { + public void findFocusClientThread(long accessibilityNodeId, int focusType, int windowLeft, + int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback, + int flags, int interogatingPid, long interrogatingTid) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_FIND_FOCUS; message.arg1 = flags; message.arg2 = focusType; + SomeArgs args = mPool.acquire(); args.argi1 = interactionId; args.argi2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId); args.argi3 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId); args.arg1 = callback; + + SomeArgs moreArgs = mPool.acquire(); + moreArgs.argi1 = windowLeft; + moreArgs.argi2 = windowTop; + args.arg2 = moreArgs; + message.obj = args; + // If the interrogation is performed by the same thread as the main UI // thread in this process, set the message as a static reference so // after this call completes the same thread but in the interrogating @@ -381,13 +439,21 @@ final class AccessibilityInteractionController { private void findFocusUiThread(Message message) { final int flags = message.arg1; final int focusType = message.arg2; + SomeArgs args = (SomeArgs) message.obj; final int interactionId = args.argi1; final int accessibilityViewId = args.argi2; final int virtualDescendantId = args.argi3; final IAccessibilityInteractionConnectionCallback callback = (IAccessibilityInteractionConnectionCallback) args.arg1; + + SomeArgs moreArgs = (SomeArgs) args.arg2; + mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1; + mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2; + + mPool.release(moreArgs); mPool.release(args); + AccessibilityNodeInfo focused = null; try { if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) { @@ -440,19 +506,27 @@ final class AccessibilityInteractionController { } } - public void focusSearchClientThread(long accessibilityNodeId, int interactionId, int direction, - IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid, - long interrogatingTid) { + public void focusSearchClientThread(long accessibilityNodeId, int direction, int windowLeft, + int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback, + int flags, int interogatingPid, long interrogatingTid) { Message message = mHandler.obtainMessage(); message.what = PrivateHandler.MSG_FOCUS_SEARCH; message.arg1 = flags; message.arg2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId); + SomeArgs args = mPool.acquire(); args.argi1 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId); args.argi2 = direction; args.argi3 = interactionId; args.arg1 = callback; + + SomeArgs moreArgs = mPool.acquire(); + moreArgs.argi1 = windowLeft; + moreArgs.argi2 = windowTop; + args.arg2 = moreArgs; + message.obj = args; + // If the interrogation is performed by the same thread as the main UI // thread in this process, set the message as a static reference so // after this call completes the same thread but in the interrogating @@ -468,13 +542,21 @@ final class AccessibilityInteractionController { private void focusSearchUiThread(Message message) { final int flags = message.arg1; final int accessibilityViewId = message.arg2; + SomeArgs args = (SomeArgs) message.obj; final int virtualDescendantId = args.argi1; final int direction = args.argi2; final int interactionId = args.argi3; final IAccessibilityInteractionConnectionCallback callback = (IAccessibilityInteractionConnectionCallback) args.arg1; + + SomeArgs moreArgs = (SomeArgs) args.arg2; + mViewRootImpl.mAttachInfo.mActualWindowLeft = moreArgs.argi1; + mViewRootImpl.mAttachInfo.mActualWindowTop = moreArgs.argi2; + + mPool.release(moreArgs); mPool.release(args); + AccessibilityNodeInfo next = null; try { if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) { @@ -541,13 +623,16 @@ final class AccessibilityInteractionController { message.what = PrivateHandler.MSG_PERFORM_ACCESSIBILITY_ACTION; message.arg1 = flags; message.arg2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId); + SomeArgs args = mPool.acquire(); args.argi1 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId); args.argi2 = action; args.argi3 = interactionId; args.arg1 = callback; args.arg2 = arguments; + message.obj = args; + // If the interrogation is performed by the same thread as the main UI // thread in this process, set the message as a static reference so // after this call completes the same thread but in the interrogating @@ -563,6 +648,7 @@ final class AccessibilityInteractionController { private void perfromAccessibilityActionUiThread(Message message) { final int flags = message.arg1; final int accessibilityViewId = message.arg2; + SomeArgs args = (SomeArgs) message.obj; final int virtualDescendantId = args.argi1; final int action = args.argi2; @@ -570,7 +656,9 @@ final class AccessibilityInteractionController { final IAccessibilityInteractionConnectionCallback callback = (IAccessibilityInteractionConnectionCallback) args.arg1; Bundle arguments = (Bundle) args.arg2; + mPool.release(args); + boolean succeeded = false; try { if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 0a2b76c..f005eeb 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3609,6 +3609,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal case R.styleable.View_importantForAccessibility: setImportantForAccessibility(a.getInt(attr, IMPORTANT_FOR_ACCESSIBILITY_DEFAULT)); + break; } } @@ -4902,6 +4903,30 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } /** + * Returns the delta between the actual and last reported window left. + * + * @hide + */ + public int getActualAndReportedWindowLeftDelta() { + if (mAttachInfo != null) { + return mAttachInfo.mActualWindowLeft - mAttachInfo.mWindowLeft; + } + return 0; + } + + /** + * Returns the delta between the actual and last reported window top. + * + * @hide + */ + public int getActualAndReportedWindowTopDelta() { + if (mAttachInfo != null) { + return mAttachInfo.mActualWindowTop - mAttachInfo.mWindowTop; + } + return 0; + } + + /** * Computes whether this view is visible to the user. Such a view is * attached, visible, all its predecessors are visible, it is not clipped * entirely by its predecessors, and has an alpha greater than zero. @@ -17307,6 +17332,20 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal int mWindowTop; /** + * Left actual position of this view's window. + * + * TODO: This is a workaround for 6623031. Remove when fixed. + */ + int mActualWindowLeft; + + /** + * Actual top position of this view's window. + * + * TODO: This is a workaround for 6623031. Remove when fixed. + */ + int mActualWindowTop; + + /** * Indicates whether views need to use 32-bit drawing caches */ boolean mUse32BitDrawingCache; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 3138692..b5fff8a 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -5172,13 +5172,15 @@ public final class ViewRootImpl implements ViewParent, @Override public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, - int interactionId, IAccessibilityInteractionConnectionCallback callback, - int flags, int interrogatingPid, long interrogatingTid) { + int windowLeft, int windowTop, int interactionId, + IAccessibilityInteractionConnectionCallback callback, int flags, + int interrogatingPid, long interrogatingTid) { ViewRootImpl viewRootImpl = mViewRootImpl.get(); if (viewRootImpl != null && viewRootImpl.mView != null) { viewRootImpl.getAccessibilityInteractionController() .findAccessibilityNodeInfoByAccessibilityIdClientThread(accessibilityNodeId, - interactionId, callback, flags, interrogatingPid, interrogatingTid); + windowLeft, windowTop, interactionId, callback, flags, interrogatingPid, + interrogatingTid); } else { // We cannot make the call and notify the caller so it does not wait. try { @@ -5211,13 +5213,15 @@ public final class ViewRootImpl implements ViewParent, @Override public void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int viewId, - int interactionId, IAccessibilityInteractionConnectionCallback callback, - int flags, int interrogatingPid, long interrogatingTid) { + int windowLeft, int windowTop, int interactionId, + IAccessibilityInteractionConnectionCallback callback, int flags, + int interrogatingPid, long interrogatingTid) { ViewRootImpl viewRootImpl = mViewRootImpl.get(); if (viewRootImpl != null && viewRootImpl.mView != null) { viewRootImpl.getAccessibilityInteractionController() .findAccessibilityNodeInfoByViewIdClientThread(accessibilityNodeId, viewId, - interactionId, callback, flags, interrogatingPid, interrogatingTid); + windowLeft, windowTop, interactionId, callback, flags, interrogatingPid, + interrogatingTid); } else { // We cannot make the call and notify the caller so it does not wait. try { @@ -5230,13 +5234,15 @@ public final class ViewRootImpl implements ViewParent, @Override public void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, - int interactionId, IAccessibilityInteractionConnectionCallback callback, - int flags, int interrogatingPid, long interrogatingTid) { + int windowLeft, int windowTop, int interactionId, + IAccessibilityInteractionConnectionCallback callback, int flags, + int interrogatingPid, long interrogatingTid) { ViewRootImpl viewRootImpl = mViewRootImpl.get(); if (viewRootImpl != null && viewRootImpl.mView != null) { viewRootImpl.getAccessibilityInteractionController() .findAccessibilityNodeInfosByTextClientThread(accessibilityNodeId, text, - interactionId, callback, flags, interrogatingPid, interrogatingTid); + windowLeft, windowTop, interactionId, callback, flags, interrogatingPid, + interrogatingTid); } else { // We cannot make the call and notify the caller so it does not wait. try { @@ -5248,14 +5254,15 @@ public final class ViewRootImpl implements ViewParent, } @Override - public void findFocus(long accessibilityNodeId, int interactionId, int focusType, - IAccessibilityInteractionConnectionCallback callback, int flags, + public void findFocus(long accessibilityNodeId, int focusType, int windowLeft, + int windowTop, int interactionId, + IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, long interrogatingTid) { ViewRootImpl viewRootImpl = mViewRootImpl.get(); if (viewRootImpl != null && viewRootImpl.mView != null) { viewRootImpl.getAccessibilityInteractionController() - .findFocusClientThread(accessibilityNodeId, interactionId, focusType, - callback, flags, interrogatingPid, interrogatingTid); + .findFocusClientThread(accessibilityNodeId, focusType, windowLeft, windowTop, + interactionId, callback, flags, interrogatingPid, interrogatingTid); } else { // We cannot make the call and notify the caller so it does not wait. try { @@ -5267,14 +5274,15 @@ public final class ViewRootImpl implements ViewParent, } @Override - public void focusSearch(long accessibilityNodeId, int interactionId, int direction, + public void focusSearch(long accessibilityNodeId, int direction, int windowLeft, + int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, long interrogatingTid) { ViewRootImpl viewRootImpl = mViewRootImpl.get(); if (viewRootImpl != null && viewRootImpl.mView != null) { viewRootImpl.getAccessibilityInteractionController() - .focusSearchClientThread(accessibilityNodeId, interactionId, direction, - callback, flags, interrogatingPid, interrogatingTid); + .focusSearchClientThread(accessibilityNodeId, direction, windowLeft, windowTop, + interactionId, callback, flags, interrogatingPid, interrogatingTid); } else { // We cannot make the call and notify the caller so it does not wait. try { diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index d3c9055..0daf78b 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -382,6 +382,10 @@ public class AccessibilityNodeInfo implements Parcelable { private int mConnectionId = UNDEFINED; + // TODO: These are a workaround for 6623031. Remove when fixed. + private int mActualAndReportedWindowLeftDelta; + private int mActualAndReportedWindowTopDelta; + /** * Hide constructor from clients. */ @@ -428,6 +432,8 @@ public class AccessibilityNodeInfo implements Parcelable { final int rootAccessibilityViewId = (root != null) ? root.getAccessibilityViewId() : UNDEFINED; mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId); + mActualAndReportedWindowLeftDelta = root.getActualAndReportedWindowLeftDelta(); + mActualAndReportedWindowTopDelta = root.getActualAndReportedWindowTopDelta(); } /** @@ -831,6 +837,7 @@ public class AccessibilityNodeInfo implements Parcelable { public void setBoundsInScreen(Rect bounds) { enforceNotSealed(); mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom); + mBoundsInScreen.offset(mActualAndReportedWindowLeftDelta, mActualAndReportedWindowTopDelta); } /** diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl index 9d7a928..292702a 100644 --- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl +++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl @@ -28,25 +28,25 @@ import android.view.accessibility.IAccessibilityInteractionConnectionCallback; */ oneway interface IAccessibilityInteractionConnection { - void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, int interactionId, - IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, - long interrogatingTid); + void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, int windowLeft, + int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback, + int flags, int interrogatingPid, long interrogatingTid); - void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int id, int interactionId, - IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, - long interrogatingTid); + void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int viewId, int windowLeft, + int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback, + int flags, int interrogatingPid, long interrogatingTid); - void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, int interactionId, - IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, - long interrogatingTid); + void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, int windowLeft, + int windowTop, int interactionId, IAccessibilityInteractionConnectionCallback callback, + int flags, int interrogatingPid, long interrogatingTid); - void findFocus(long accessibilityNodeId, int interactionId, int focusType, - IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, - long interrogatingTid); + void findFocus(long accessibilityNodeId, int focusType, int windowLeft, int windowTop, + int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, + int interrogatingPid, long interrogatingTid); - void focusSearch(long accessibilityNodeId, int interactionId, int direction, - IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid, - long interrogatingTid); + void focusSearch(long accessibilityNodeId, int direction, int windowLeft, int windowTop, + int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, + int interrogatingPid, long interrogatingTid); void performAccessibilityAction(long accessibilityNodeId, int action, in Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, diff --git a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java index 3e35b20..baa2f54 100644 --- a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java +++ b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java @@ -25,6 +25,7 @@ import android.view.InputDevice; import android.view.InputEvent; import android.view.MotionEvent; import android.view.WindowManagerPolicy; +import android.view.accessibility.AccessibilityEvent; /** * Input filter for accessibility. @@ -120,4 +121,8 @@ public class AccessibilityInputFilter extends InputFilter { super.onInputEvent(event, policyFlags); } } + + public void onAccessibilityEvent(AccessibilityEvent event) { + mTouchExplorer.onAccessibilityEvent(event); + } } diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java index 5c814d2..3bddd9d 100644 --- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -141,8 +141,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); - private final Rect mTempRect = new Rect(); - private PackageManager mPackageManager; private int mHandledFeedbackTypes = 0; @@ -403,7 +401,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { notifyAccessibilityServicesDelayedLocked(event, false); notifyAccessibilityServicesDelayedLocked(event, true); } - + if (mHasInputFilter && mInputFilter != null) { + mInputFilter.onAccessibilityEvent(event); + } event.recycle(); mHandledFeedbackTypes = 0; } @@ -543,17 +543,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } /** - * Gets the bounds of the accessibility focus if the provided, - * point coordinates are within the currently active window - * and accessibility focus is found within the latter. + * Gets the bounds of the accessibility focus in the active window. * - * @param x X coordinate. - * @param y Y coordinate * @param outBounds The output to which to write the focus bounds. - * @return The accessibility focus rectangle if the point is in the - * window and the window has accessibility focus. + * @return Whether accessibility focus was found and the bounds are populated. */ - boolean getAccessibilityFocusBounds(int x, int y, Rect outBounds) { + boolean getAccessibilityFocusBoundsInActiveWindow(Rect outBounds) { // Instead of keeping track of accessibility focus events per // window to be able to find the focus in the active window, // we take a stateless approach and look it up. This is fine @@ -568,11 +563,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (root == null) { return false; } - Rect bounds = mTempRect; - root.getBoundsInScreen(bounds); - if (!bounds.contains(x, y)) { - return false; - } AccessibilityNodeInfo focus = root.findFocus( AccessibilityNodeInfo.FOCUS_ACCESSIBILITY); if (focus == null) { @@ -585,6 +575,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } + /** + * Gets the bounds of the active window. + * + * @param outBounds The output to which to write the bounds. + */ + void getActiveWindowBounds(Rect outBounds) { + synchronized (mLock) { + final int windowId = mSecurityPolicy.mActiveWindowId; + IBinder token = mWindowIdToWindowTokenMap.get(windowId); + mWindowManagerService.getWindowFrame(token, outBounds); + } + } + private Service getQueryBridge() { if (mQueryBridge == null) { AccessibilityServiceInfo info = new AccessibilityServiceInfo(); @@ -1316,6 +1319,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) throws RemoteException { final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId); + final int windowLeft; + final int windowTop; IAccessibilityInteractionConnection connection = null; synchronized (mLock) { mSecurityPolicy.enforceCanRetrieveWindowContent(this); @@ -1328,6 +1333,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return 0; } } + IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId); + mWindowManagerService.getWindowFrame(token, mTempBounds); + windowLeft = mTempBounds.left; + windowTop = mTempBounds.top; } final int flags = (mIncludeNotImportantViews) ? AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0; @@ -1335,7 +1344,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { final long identityToken = Binder.clearCallingIdentity(); try { connection.findAccessibilityNodeInfoByViewId(accessibilityNodeId, viewId, - interactionId, callback, flags, interrogatingPid, interrogatingTid); + windowLeft, windowTop, interactionId, callback, flags, interrogatingPid, + interrogatingTid); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId()."); @@ -1352,6 +1362,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) throws RemoteException { final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId); + final int windowLeft; + final int windowTop; IAccessibilityInteractionConnection connection = null; synchronized (mLock) { mSecurityPolicy.enforceCanRetrieveWindowContent(this); @@ -1365,14 +1377,19 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return 0; } } + IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId); + mWindowManagerService.getWindowFrame(token, mTempBounds); + windowLeft = mTempBounds.left; + windowTop = mTempBounds.top; } final int flags = (mIncludeNotImportantViews) ? AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0; final int interrogatingPid = Binder.getCallingPid(); final long identityToken = Binder.clearCallingIdentity(); try { - connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text, - interactionId, callback, flags, interrogatingPid, interrogatingTid); + connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text, windowLeft, + windowTop, interactionId, callback, flags, interrogatingPid, + interrogatingTid); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()"); @@ -1389,6 +1406,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { IAccessibilityInteractionConnectionCallback callback, int flags, long interrogatingTid) throws RemoteException { final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId); + final int windowLeft; + final int windowTop; IAccessibilityInteractionConnection connection = null; synchronized (mLock) { mSecurityPolicy.enforceCanRetrieveWindowContent(this); @@ -1402,6 +1421,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return 0; } } + IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId); + mWindowManagerService.getWindowFrame(token, mTempBounds); + windowLeft = mTempBounds.left; + windowTop = mTempBounds.top; } final int allFlags = flags | ((mIncludeNotImportantViews) ? AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0); @@ -1409,7 +1432,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { final long identityToken = Binder.clearCallingIdentity(); try { connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId, - interactionId, callback, allFlags, interrogatingPid, interrogatingTid); + windowLeft, windowTop, interactionId, callback, allFlags, interrogatingPid, + interrogatingTid); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()"); @@ -1426,6 +1450,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) throws RemoteException { final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId); + final int windowLeft; + final int windowTop; IAccessibilityInteractionConnection connection = null; synchronized (mLock) { mSecurityPolicy.enforceCanRetrieveWindowContent(this); @@ -1439,14 +1465,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return 0; } } + IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId); + mWindowManagerService.getWindowFrame(token, mTempBounds); + windowLeft = mTempBounds.left; + windowTop = mTempBounds.top; } final int flags = (mIncludeNotImportantViews) ? AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0; final int interrogatingPid = Binder.getCallingPid(); final long identityToken = Binder.clearCallingIdentity(); try { - connection.findFocus(accessibilityNodeId, interactionId, focusType, callback, - flags, interrogatingPid, interrogatingTid); + connection.findFocus(accessibilityNodeId, focusType, windowLeft, windowTop, + interactionId, callback, flags, interrogatingPid, interrogatingTid); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error calling findAccessibilityFocus()"); @@ -1463,6 +1493,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) throws RemoteException { final int resolvedWindowId = resolveAccessibilityWindowId(accessibilityWindowId); + final int windowLeft; + final int windowTop; IAccessibilityInteractionConnection connection = null; synchronized (mLock) { mSecurityPolicy.enforceCanRetrieveWindowContent(this); @@ -1476,14 +1508,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { return 0; } } + IBinder token = mWindowIdToWindowTokenMap.get(resolvedWindowId); + mWindowManagerService.getWindowFrame(token, mTempBounds); + windowLeft = mTempBounds.left; + windowTop = mTempBounds.top; } final int flags = (mIncludeNotImportantViews) ? AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0; final int interrogatingPid = Binder.getCallingPid(); final long identityToken = Binder.clearCallingIdentity(); try { - connection.focusSearch(accessibilityNodeId, interactionId, direction, callback, - flags, interrogatingPid, interrogatingTid); + connection.focusSearch(accessibilityNodeId, direction, windowLeft, windowTop, + interactionId, callback, flags, interrogatingPid, interrogatingTid); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()"); diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java index 7e88373..14784dc 100644 --- a/services/java/com/android/server/accessibility/TouchExplorer.java +++ b/services/java/com/android/server/accessibility/TouchExplorer.java @@ -33,6 +33,7 @@ import android.view.MotionEvent.PointerProperties; import android.view.VelocityTracker; import android.view.ViewConfiguration; import android.view.WindowManagerPolicy; +import android.view.accessibility.AccessibilityEvent; import com.android.internal.R; import com.android.server.input.InputFilter; @@ -293,6 +294,21 @@ public class TouchExplorer { } } + public void onAccessibilityEvent(AccessibilityEvent event) { + // If a new window opens or the accessibility focus moves we no longer + // want to click/long press on the last touch explored location. + final int eventType = event.getEventType(); + switch (eventType) { + case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: + case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: { + if (mInjectedPointerTracker.mLastInjectedHoverEvent != null) { + mInjectedPointerTracker.mLastInjectedHoverEvent.recycle(); + mInjectedPointerTracker.mLastInjectedHoverEvent = null; + } + } break; + } + } + /** * Handles a motion event in touch exploring state. * @@ -1037,30 +1053,40 @@ public class TouchExplorer { // is actually clicked. sendExitEventsIfNeeded(policyFlags); - // If the last touched explored location is not within the focused - // window we will click at that exact spot, otherwise we find the - // accessibility focus and if the tap is within its bounds we click - // there, otherwise we pick the middle of the focus rectangle. - MotionEvent lastEvent = mInjectedPointerTracker.getLastInjectedHoverEvent(); - if (lastEvent == null) { - return; - } - - final int exploreLocationX = (int) lastEvent.getX(lastEvent.getActionIndex()); - final int exploreLocationY = (int) lastEvent.getY(lastEvent.getActionIndex()); - - Rect bounds = mTempRect; - boolean useLastHoverLocation = false; + int clickLocationX; + int clickLocationY; final int pointerId = secondTapUp.getPointerId(secondTapUp.getActionIndex()); final int pointerIndex = secondTapUp.findPointerIndex(pointerId); - if (mAms.getAccessibilityFocusBounds(exploreLocationX, exploreLocationY, bounds)) { - // If the user's last touch explored location is not - // within the accessibility focus bounds we use the center - // of the accessibility focused rectangle. - if (!bounds.contains((int) secondTapUp.getX(pointerIndex), - (int) secondTapUp.getY(pointerIndex))) { - useLastHoverLocation = true; + + MotionEvent lastExploreEvent = mInjectedPointerTracker.getLastInjectedHoverEvent(); + if (lastExploreEvent == null) { + // No last touch explored event but there is accessibility focus in + // the active window. We click in the middle of the focus bounds. + Rect focusBounds = mTempRect; + if (mAms.getAccessibilityFocusBoundsInActiveWindow(focusBounds)) { + clickLocationX = focusBounds.centerX(); + clickLocationY = focusBounds.centerY(); + } else { + // Out of luck - do nothing. + return; + } + } else { + // If the click is within the active window but not within the + // accessibility focus bounds we click in the focus center. + final int lastExplorePointerIndex = lastExploreEvent.getActionIndex(); + clickLocationX = (int) lastExploreEvent.getX(lastExplorePointerIndex); + clickLocationY = (int) lastExploreEvent.getY(lastExplorePointerIndex); + Rect activeWindowBounds = mTempRect; + mAms.getActiveWindowBounds(activeWindowBounds); + if (activeWindowBounds.contains(clickLocationX, clickLocationY)) { + Rect focusBounds = mTempRect; + if (mAms.getAccessibilityFocusBoundsInActiveWindow(focusBounds)) { + if (!focusBounds.contains(clickLocationX, clickLocationY)) { + clickLocationX = focusBounds.centerX(); + clickLocationY = focusBounds.centerY(); + } + } } } @@ -1070,8 +1096,8 @@ public class TouchExplorer { secondTapUp.getPointerProperties(pointerIndex, properties[0]); PointerCoords[] coords = new PointerCoords[1]; coords[0] = new PointerCoords(); - coords[0].x = (useLastHoverLocation) ? bounds.centerX() : exploreLocationX; - coords[0].y = (useLastHoverLocation) ? bounds.centerY() : exploreLocationY; + coords[0].x = clickLocationX; + coords[0].y = clickLocationY; MotionEvent event = MotionEvent.obtain(secondTapUp.getDownTime(), secondTapUp.getEventTime(), MotionEvent.ACTION_DOWN, 1, properties, coords, 0, 0, 1.0f, 1.0f, secondTapUp.getDeviceId(), 0, @@ -1257,45 +1283,47 @@ public class TouchExplorer { return; } - // If the last touched explored location is not within the focused - // window we will long press at that exact spot, otherwise we find the - // accessibility focus and if the tap is within its bounds we long press - // there, otherwise we pick the middle of the focus rectangle. - MotionEvent lastEvent = mInjectedPointerTracker.getLastInjectedHoverEvent(); - if (lastEvent == null) { - return; - } - - final int exploreLocationX = (int) lastEvent.getX(lastEvent.getActionIndex()); - final int exploreLocationY = (int) lastEvent.getY(lastEvent.getActionIndex()); - - Rect bounds = mTempRect; - boolean useFocusedBounds = false; + int clickLocationX; + int clickLocationY; final int pointerId = mEvent.getPointerId(mEvent.getActionIndex()); final int pointerIndex = mEvent.findPointerIndex(pointerId); - if (mAms.getAccessibilityFocusBounds(exploreLocationX, exploreLocationY, bounds)) { - // If the user's last touch explored location is not - // within the accessibility focus bounds we use the center - // of the accessibility focused rectangle. - if (!bounds.contains((int) mEvent.getX(pointerIndex), - (int) mEvent.getY(pointerIndex))) { - useFocusedBounds = true; - } - } - mLongPressingPointerId = mEvent.getPointerId(pointerIndex); - - final int eventX = (int) mEvent.getX(pointerIndex); - final int eventY = (int) mEvent.getY(pointerIndex); - if (useFocusedBounds) { - mLongPressingPointerDeltaX = eventX - bounds.centerX(); - mLongPressingPointerDeltaY = eventY - bounds.centerY(); + MotionEvent lastExploreEvent = mInjectedPointerTracker.getLastInjectedHoverEvent(); + if (lastExploreEvent == null) { + // No last touch explored event but there is accessibility focus in + // the active window. We click in the middle of the focus bounds. + Rect focusBounds = mTempRect; + if (mAms.getAccessibilityFocusBoundsInActiveWindow(focusBounds)) { + clickLocationX = focusBounds.centerX(); + clickLocationY = focusBounds.centerY(); + } else { + // Out of luck - do nothing. + return; + } } else { - mLongPressingPointerDeltaX = eventX - exploreLocationX; - mLongPressingPointerDeltaY = eventY - exploreLocationY; + // If the click is within the active window but not within the + // accessibility focus bounds we click in the focus center. + final int lastExplorePointerIndex = lastExploreEvent.getActionIndex(); + clickLocationX = (int) lastExploreEvent.getX(lastExplorePointerIndex); + clickLocationY = (int) lastExploreEvent.getY(lastExplorePointerIndex); + Rect activeWindowBounds = mTempRect; + mAms.getActiveWindowBounds(activeWindowBounds); + if (activeWindowBounds.contains(clickLocationX, clickLocationY)) { + Rect focusBounds = mTempRect; + if (mAms.getAccessibilityFocusBoundsInActiveWindow(focusBounds)) { + if (!focusBounds.contains(clickLocationX, clickLocationY)) { + clickLocationX = focusBounds.centerX(); + clickLocationY = focusBounds.centerY(); + } + } + } } + mLongPressingPointerId = pointerId; + mLongPressingPointerDeltaX = (int) mEvent.getX(pointerIndex) - clickLocationX; + mLongPressingPointerDeltaY = (int) mEvent.getY(pointerIndex) - clickLocationY; + sendExitEventsIfNeeded(mPolicyFlags); mCurrentState = STATE_DELEGATING; diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 5f63934..9e08584 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -6675,6 +6675,7 @@ public class WindowManagerService extends IWindowManager.Stub } } + // TODO: Put this on the IWindowManagerService and guard with a permission. public IBinder getFocusedWindowClientToken() { synchronized (mWindowMap) { WindowState windowState = getFocusedWindowLocked(); @@ -6685,6 +6686,18 @@ public class WindowManagerService extends IWindowManager.Stub } } + // TODO: This is a workaround - remove when 6623031 is fixed. + public boolean getWindowFrame(IBinder token, Rect outBounds) { + synchronized (mWindowMap) { + WindowState windowState = mWindowMap.get(token); + if (windowState != null) { + outBounds.set(windowState.getFrameLw()); + return true; + } + } + return false; + } + private WindowState getFocusedWindow() { synchronized (mWindowMap) { return getFocusedWindowLocked(); |