diff options
author | Svetoslav <svetoslavganov@google.com> | 2014-10-23 23:17:20 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-10-23 23:17:21 +0000 |
commit | bd6fabe2ae535cf5d31fc7a1952e43ad6e653e2e (patch) | |
tree | 086532257ec25a3c7e3329fb2d9d2146bb15f5ca /core | |
parent | 9920a0dcf15ba2036cdcc5d6548efa6b4a8bc944 (diff) | |
parent | 3a5c721072c60c7ed9c8a95d0a65d0e3cb4eb9bb (diff) | |
download | frameworks_base-bd6fabe2ae535cf5d31fc7a1952e43ad6e653e2e.zip frameworks_base-bd6fabe2ae535cf5d31fc7a1952e43ad6e653e2e.tar.gz frameworks_base-bd6fabe2ae535cf5d31fc7a1952e43ad6e653e2e.tar.bz2 |
Merge "APIs for an accessibility service to put interaction tracking overlays." into lmp-mr1-dev
Diffstat (limited to 'core')
6 files changed, 144 insertions, 21 deletions
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index 13ceb4a..1e1b33f 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -24,13 +24,18 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.util.Log; +import android.view.Display; import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityInteractionClient; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityWindowInfo; import com.android.internal.os.HandlerCaller; +import com.android.internal.os.SomeArgs; import java.util.List; @@ -366,7 +371,7 @@ public abstract class AccessibilityService extends Service { public void onAccessibilityEvent(AccessibilityEvent event); public void onInterrupt(); public void onServiceConnected(); - public void onSetConnectionId(int connectionId); + public void init(int connectionId, IBinder windowToken); public boolean onGesture(int gestureId); public boolean onKeyEvent(KeyEvent event); } @@ -375,6 +380,10 @@ public abstract class AccessibilityService extends Service { private AccessibilityServiceInfo mInfo; + private IBinder mWindowToken; + + private WindowManager mWindowManager; + /** * Callback for {@link android.view.accessibility.AccessibilityEvent}s. * @@ -611,6 +620,18 @@ public abstract class AccessibilityService extends Service { } } + @Override + public Object getSystemService(String name) { + if (Context.WINDOW_SERVICE.equals(name)) { + if (mWindowManager == null) { + WindowManager wrapped = (WindowManager) super.getSystemService(name); + mWindowManager = new LocalWindowManager(wrapped); + } + return mWindowManager; + } + return super.getSystemService(name); + } + /** * Implement to return the implementation of the internal accessibility * service interface. @@ -634,8 +655,9 @@ public abstract class AccessibilityService extends Service { } @Override - public void onSetConnectionId( int connectionId) { + public void init(int connectionId, IBinder windowToken) { mConnectionId = connectionId; + mWindowToken = windowToken; } @Override @@ -658,7 +680,7 @@ public abstract class AccessibilityService extends Service { */ public static class IAccessibilityServiceClientWrapper extends IAccessibilityServiceClient.Stub implements HandlerCaller.Callback { - private static final int DO_SET_SET_CONNECTION = 1; + private static final int DO_INIT = 1; private static final int DO_ON_INTERRUPT = 2; private static final int DO_ON_ACCESSIBILITY_EVENT = 3; private static final int DO_ON_GESTURE = 4; @@ -677,9 +699,10 @@ public abstract class AccessibilityService extends Service { mCaller = new HandlerCaller(context, looper, this, true /*asyncHandler*/); } - public void setConnection(IAccessibilityServiceConnection connection, int connectionId) { - Message message = mCaller.obtainMessageIO(DO_SET_SET_CONNECTION, connectionId, - connection); + public void init(IAccessibilityServiceConnection connection, int connectionId, + IBinder windowToken) { + Message message = mCaller.obtainMessageIOO(DO_INIT, connectionId, + connection, windowToken); mCaller.sendMessage(message); } @@ -730,20 +753,24 @@ public abstract class AccessibilityService extends Service { mCallback.onInterrupt(); } return; - case DO_SET_SET_CONNECTION: { + case DO_INIT: { mConnectionId = message.arg1; + SomeArgs args = (SomeArgs) message.obj; IAccessibilityServiceConnection connection = - (IAccessibilityServiceConnection) message.obj; + (IAccessibilityServiceConnection) args.arg1; + IBinder windowToken = (IBinder) args.arg2; + args.recycle(); if (connection != null) { AccessibilityInteractionClient.getInstance().addConnection(mConnectionId, connection); - mCallback.onSetConnectionId(mConnectionId); + mCallback.init(mConnectionId, windowToken); mCallback.onServiceConnected(); } else { AccessibilityInteractionClient.getInstance().removeConnection( mConnectionId); + mConnectionId = AccessibilityInteractionClient.NO_ID; AccessibilityInteractionClient.getInstance().clearCache(); - mCallback.onSetConnectionId(AccessibilityInteractionClient.NO_ID); + mCallback.init(AccessibilityInteractionClient.NO_ID, null); } } return; @@ -785,4 +812,53 @@ public abstract class AccessibilityService extends Service { } } } + + private class LocalWindowManager implements WindowManager { + private final WindowManager mImpl; + + private LocalWindowManager(WindowManager impl) { + mImpl = impl; + } + + @Override + public Display getDefaultDisplay() { + return mImpl.getDefaultDisplay(); + } + + @Override + public void addView(View view, ViewGroup.LayoutParams params) { + if (!(params instanceof WindowManager.LayoutParams)) { + throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); + } + WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params; + if (windowParams.type == LayoutParams.TYPE_ACCESSIBILITY_OVERLAY + && windowParams.token == null) { + windowParams.token = mWindowToken; + } + mImpl.addView(view, params); + } + + @Override + public void updateViewLayout(View view, ViewGroup.LayoutParams params) { + if (!(params instanceof WindowManager.LayoutParams)) { + throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); + } + WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params; + if (windowParams.type == LayoutParams.TYPE_ACCESSIBILITY_OVERLAY + && windowParams.token == null) { + windowParams.token = mWindowToken; + } + mImpl.updateViewLayout(view, params); + } + + @Override + public void removeViewImmediate(View view) { + mImpl.removeViewImmediate(view); + } + + @Override + public void removeView(View view) { + mImpl.removeView(view); + } + } } diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl index 6ce0219..8b503dd 100644 --- a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl +++ b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl @@ -28,7 +28,7 @@ import android.view.KeyEvent; */ oneway interface IAccessibilityServiceClient { - void setConnection(in IAccessibilityServiceConnection connection, int connectionId); + void init(in IAccessibilityServiceConnection connection, int connectionId, IBinder windowToken); void onAccessibilityEvent(in AccessibilityEvent event); diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java index 4aec9e0..b0dd70f 100644 --- a/core/java/android/app/UiAutomation.java +++ b/core/java/android/app/UiAutomation.java @@ -25,6 +25,7 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Point; import android.hardware.display.DisplayManagerGlobal; +import android.os.IBinder; import android.os.Looper; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -919,7 +920,7 @@ public final class UiAutomation { public IAccessibilityServiceClientImpl(Looper looper) { super(null, looper, new Callbacks() { @Override - public void onSetConnectionId(int connectionId) { + public void init(int connectionId, IBinder windowToken) { synchronized (mLock) { mConnectionId = connectionId; mLock.notifyAll(); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 3f84c9b..5b48c0d 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -542,6 +542,19 @@ public interface WindowManager extends ViewManager { public static final int TYPE_VOICE_INTERACTION = FIRST_SYSTEM_WINDOW+31; /** + * Window type: Windows that are overlaid <em>only</em> by an {@link + * android.accessibilityservice.AccessibilityService} for interception of + * user interactions without changing the windows an accessibility service + * can introspect. In particular, an accessibility service can introspect + * only windows that a sighted user can interact with which is they can touch + * these windows or can type into these windows. For example, if there + * is a full screen accessibility overlay that is touchable, the windows + * below it will be introspectable by an accessibility service regardless + * they are covered by a touchable window. + */ + public static final int TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32; + + /** * End of types of system windows. */ public static final int LAST_SYSTEM_WINDOW = 2999; diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java index 38e3723..f557b97 100644 --- a/core/java/android/view/WindowManagerInternal.java +++ b/core/java/android/view/WindowManagerInternal.java @@ -173,4 +173,20 @@ public abstract class WindowManagerInternal { * redrawn. */ public abstract void waitForAllWindowsDrawn(Runnable callback, long timeout); + + /** + * Adds a window token for a given window type. + * + * @param token The token to add. + * @param type The window type. + */ + public abstract void addWindowToken(android.os.IBinder token, int type); + + /** + * Removes a window token. + * + * @param token The toke to remove. + * @param removeWindows Whether to also remove the windows associated with the token. + */ + public abstract void removeWindowToken(android.os.IBinder token, boolean removeWindows); } diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java index ad55f5f..e1942be 100644 --- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java +++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java @@ -51,11 +51,24 @@ public final class AccessibilityWindowInfo implements Parcelable { */ public static final int TYPE_SYSTEM = 3; + /** + * Window type: Windows that are overlaid <em>only</em> by an {@link + * android.accessibilityservice.AccessibilityService} for interception of + * user interactions without changing the windows an accessibility service + * can introspect. In particular, an accessibility service can introspect + * only windows that a sighted user can interact with which they can touch + * these windows or can type into these windows. For example, if there + * is a full screen accessibility overlay that is touchable, the windows + * below it will be introspectable by an accessibility service regardless + * they are covered by a touchable window. + */ + public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; + private static final int UNDEFINED = -1; private static final int BOOLEAN_PROPERTY_ACTIVE = 1 << 0; private static final int BOOLEAN_PROPERTY_FOCUSED = 1 << 1; - private static final int BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED = 1 << 2; + private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 1 << 2; // Housekeeping. private static final int MAX_POOL_SIZE = 10; @@ -85,6 +98,7 @@ public final class AccessibilityWindowInfo implements Parcelable { * @see #TYPE_APPLICATION * @see #TYPE_INPUT_METHOD * @see #TYPE_SYSTEM + * @see #TYPE_ACCESSIBILITY_OVERLAY */ public int getType() { return mType; @@ -93,7 +107,7 @@ public final class AccessibilityWindowInfo implements Parcelable { /** * Sets the type of the window. * - * @param The type + * @param type The type * * @hide */ @@ -115,7 +129,7 @@ public final class AccessibilityWindowInfo implements Parcelable { * Sets the layer which determines the Z-order of the window. Windows * with greater layer appear on top of windows with lesser layer. * - * @param The window layer. + * @param layer The window layer. * * @hide */ @@ -174,7 +188,7 @@ public final class AccessibilityWindowInfo implements Parcelable { /** * Sets the unique window id. * - * @param windowId The window id. + * @param id The window id. * * @hide */ @@ -230,7 +244,7 @@ public final class AccessibilityWindowInfo implements Parcelable { * the user is currently touching or the window has input focus * and the user is not touching any window. * - * @param Whether this is the active window. + * @param active Whether this is the active window. * * @hide */ @@ -250,7 +264,7 @@ public final class AccessibilityWindowInfo implements Parcelable { /** * Sets if this window has input focus. * - * @param Whether has input focus. + * @param focused Whether has input focus. * * @hide */ @@ -264,18 +278,18 @@ public final class AccessibilityWindowInfo implements Parcelable { * @return Whether has accessibility focus. */ public boolean isAccessibilityFocused() { - return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED); + return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED); } /** * Sets if this window has accessibility focus. * - * @param Whether has accessibility focus. + * @param focused Whether has accessibility focus. * * @hide */ public void setAccessibilityFocused(boolean focused) { - setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED, focused); + setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED, focused); } /** @@ -534,6 +548,9 @@ public final class AccessibilityWindowInfo implements Parcelable { case TYPE_SYSTEM: { return "TYPE_SYSTEM"; } + case TYPE_ACCESSIBILITY_OVERLAY: { + return "TYPE_ACCESSIBILITY_OVERLAY"; + } default: return "<UNKNOWN>"; } |