summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java114
-rw-r--r--core/java/android/view/View.java39
-rw-r--r--core/java/android/view/ViewRootImpl.java40
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java7
-rw-r--r--core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl30
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityInputFilter.java5
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java84
-rw-r--r--services/java/com/android/server/accessibility/TouchExplorer.java138
-rwxr-xr-xservices/java/com/android/server/wm/WindowManagerService.java13
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();