OSDN Git Service

Deliver key events to the system if no accessibility service handles them.
authorSvetoslav <svetoslavganov@google.com>
Fri, 26 Apr 2013 20:11:11 +0000 (13:11 -0700)
committerSvetoslav <svetoslavganov@google.com>
Fri, 26 Apr 2013 20:58:09 +0000 (13:58 -0700)
We have APIs that allow an accessibility service to filter key events. The
service has to declare the capability to toggle event filtering in its
manifest and then it can set a flag to toggle the feature at runtime. The
problem was that even if no accessibility service was handling key events
these events were not fed back to the input system.

This change adds a new feature flag in the accessibility input filter that
is set only if at least one service can and wants to filter key events. If
the feature flag is set then the filter will deliver events to services and
,if they are not handled, to the system. This change also cleaned the logic
for updating the input filter.

bug:8713422

Change-Id: I4bc0c1348676569d1b76e9024708d1ed43ceb26a

services/java/com/android/server/accessibility/AccessibilityInputFilter.java
services/java/com/android/server/accessibility/AccessibilityManagerService.java

index 0d8a571..6a7aad3 100644 (file)
@@ -56,6 +56,13 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
      */
     static final int FLAG_FEATURE_TOUCH_EXPLORATION = 0x00000002;
 
+    /**
+     * Flag for enabling the filtering key events feature.
+     *
+     * @see #setEnabledFeatures(int)
+     */
+    static final int FLAG_FEATURE_FILTER_KEY_EVENTS = 0x00000004;
+
     private final Runnable mProcessBatchedEventsRunnable = new Runnable() {
         @Override
         public void run() {
@@ -101,6 +108,8 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
 
     private boolean mKeyEventSequenceStarted;
 
+    private boolean mFilterKeyEvents;
+
     AccessibilityInputFilter(Context context, AccessibilityManagerService service) {
         super(context.getMainLooper());
         mContext = context;
@@ -198,6 +207,10 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
     }
 
     private void onKeyEvent(KeyEvent event, int policyFlags) {
+        if (!mFilterKeyEvents) {
+            super.onInputEvent(event, policyFlags);
+            return;
+        }
         if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) == 0) {
             mKeyEventSequenceStarted = false;
             super.onInputEvent(event, policyFlags);
@@ -314,13 +327,6 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
         }
     }
 
-    void reset() {
-        setEnabledFeatures(0);
-        mKeyEventSequenceStarted = false;
-        mMotionEventSequenceStarted = false;
-        mHoverEventSequenceStarted = false;
-    }
-
     private void enableFeatures() {
         mMotionEventSequenceStarted = false;
         mHoverEventSequenceStarted = false;
@@ -338,6 +344,9 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
                 mEventHandler = mTouchExplorer;
             }
         }
+        if ((mEnabledFeatures & FLAG_FEATURE_FILTER_KEY_EVENTS) != 0) {
+            mFilterKeyEvents = true;
+        }
     }
 
     private void disableFeatures() {
@@ -352,6 +361,10 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
             mScreenMagnifier = null;
         }
         mEventHandler = null;
+        mKeyEventSequenceStarted = false;
+        mMotionEventSequenceStarted = false;
+        mHoverEventSequenceStarted = false;
+        mFilterKeyEvents = false;
     }
 
     @Override
index 3fd534e..d51f48f 100644 (file)
@@ -1170,9 +1170,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
         boolean setInputFilter = false;
         AccessibilityInputFilter inputFilter = null;
         synchronized (mLock) {
-            // Accessibility enabled means at least one service is enabled.
-            if (userState.mIsAccessibilityEnabled
-                    || userState.mIsDisplayMagnificationEnabled) {
+            int flags = 0;
+            if (userState.mIsDisplayMagnificationEnabled) {
+                flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
+            }
+            // Touch exploration without accessibility makes no sense.
+            if (userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) {
+                flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
+            }
+            if (userState.mIsFilterKeyEventsEnabled) {
+                flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS;
+            }
+            if (flags != 0) {
                 if (!mHasInputFilter) {
                     mHasInputFilter = true;
                     if (mInputFilter == null) {
@@ -1182,19 +1191,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
                     inputFilter = mInputFilter;
                     setInputFilter = true;
                 }
-                int flags = 0;
-                if (userState.mIsDisplayMagnificationEnabled) {
-                    flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
-                }
-                // Touch exploration without accessibility makes no sense.
-                if (userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) {
-                    flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
-                }
                 mInputFilter.setEnabledFeatures(flags);
             } else {
                 if (mHasInputFilter) {
                     mHasInputFilter = false;
-                    mInputFilter.reset();
+                    mInputFilter.disableFeatures();
                     inputFilter = null;
                     setInputFilter = true;
                 }
@@ -1263,6 +1264,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
     private void onUserStateChangedLocked(UserState userState) {
         updateLegacyCapabilities(userState);
         updateServicesLocked(userState);
+        updateFilterKeyEventsLocked(userState);
         updateTouchExplorationLocked(userState);
         updateEnhancedWebAccessibilityLocked(userState);
         scheduleUpdateInputFilter(userState);
@@ -1291,6 +1293,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
         }
     }
 
+    private void updateFilterKeyEventsLocked(UserState userState) {
+        final int serviceCount = userState.mBoundServices.size();
+        for (int i = 0; i < serviceCount; i++) {
+            Service service = userState.mBoundServices.get(i);
+            if (service.mRequestFilterKeyEvents
+                    && (service.mAccessibilityServiceInfo.getCapabilities()
+                            & AccessibilityServiceInfo
+                            .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) != 0) {
+                userState.mIsFilterKeyEventsEnabled = true;
+                return;
+            }
+        }
+        userState.mIsFilterKeyEventsEnabled = false;
+    }
+
     private void updateServicesLocked(UserState userState) {
         if (userState.mIsAccessibilityEnabled) {
             manageServicesLocked(userState);
@@ -2899,6 +2916,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
         public boolean mIsTouchExplorationEnabled;
         public boolean mIsEnhancedWebAccessibilityEnabled;
         public boolean mIsDisplayMagnificationEnabled;
+        public boolean mIsFilterKeyEventsEnabled;
 
         private Service mUiAutomationService;
         private IAccessibilityServiceClient mUiAutomationServiceClient;