AccessibilityInputFilter.java revision 45af84a483165f06c04d74baba67f90da29c6ad2
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.accessibility;
18
19import android.content.Context;
20import android.os.PowerManager;
21import android.util.Slog;
22import android.view.InputDevice;
23import android.view.InputEvent;
24import android.view.InputFilter;
25import android.view.MotionEvent;
26import android.view.WindowManagerPolicy;
27import android.view.accessibility.AccessibilityEvent;
28
29class AccessibilityInputFilter extends InputFilter implements EventStreamTransformation {
30
31    private static final String TAG = AccessibilityInputFilter.class.getSimpleName();
32
33    private static final boolean DEBUG = false;
34
35    private static final int UNDEFINED_DEVICE_ID = -1;
36
37    /**
38     * Flag for enabling the screen magnification feature.
39     *
40     * @see #setEnabledFeatures(int)
41     */
42    static final int FLAG_FEATURE_SCREEN_MAGNIFIER = 0x00000001;
43
44    /**
45     * Flag for enabling the touch exploration feature.
46     *
47     * @see #setEnabledFeatures(int)
48     */
49    static final int FLAG_FEATURE_TOUCH_EXPLORATION = 0x00000002;
50
51    private final Context mContext;
52
53    private final PowerManager mPm;
54
55    private final AccessibilityManagerService mAms;
56
57    private int mCurrentDeviceId;
58
59    private boolean mInstalled;
60
61    private int mEnabledFeatures;
62
63    private TouchExplorer mTouchExplorer;
64    private ScreenMagnifier mScreenMagnifier;
65    private EventStreamTransformation mEventHandler;
66
67    AccessibilityInputFilter(Context context, AccessibilityManagerService service) {
68        super(context.getMainLooper());
69        mContext = context;
70        mAms = service;
71        mPm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
72    }
73
74    @Override
75    public void onInstalled() {
76        if (DEBUG) {
77            Slog.d(TAG, "Accessibility input filter installed.");
78        }
79        mInstalled = true;
80        disableFeatures();
81        enableFeatures();
82        super.onInstalled();
83    }
84
85    @Override
86    public void onUninstalled() {
87        if (DEBUG) {
88            Slog.d(TAG, "Accessibility input filter uninstalled.");
89        }
90        mInstalled = false;
91        disableFeatures();
92        super.onUninstalled();
93    }
94
95    @Override
96    public void onInputEvent(InputEvent event, int policyFlags) {
97        if (DEBUG) {
98            Slog.d(TAG, "Received event: " + event + ", policyFlags=0x"
99                    + Integer.toHexString(policyFlags));
100        }
101        if (mEventHandler == null) {
102            super.onInputEvent(event, policyFlags);
103            return;
104        }
105        if (event.getSource() != InputDevice.SOURCE_TOUCHSCREEN) {
106            super.onInputEvent(event, policyFlags);
107            return;
108        }
109        if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) == 0) {
110            mEventHandler.clear();
111            super.onInputEvent(event, policyFlags);
112            return;
113        }
114        final int deviceId = event.getDeviceId();
115        if (mCurrentDeviceId != deviceId) {
116            if (mCurrentDeviceId != UNDEFINED_DEVICE_ID) {
117                mEventHandler.clear();
118            }
119            mCurrentDeviceId = deviceId;
120        }
121        mPm.userActivity(event.getEventTime(), false);
122        MotionEvent rawEvent = (MotionEvent) event;
123        MotionEvent transformedEvent = MotionEvent.obtain(rawEvent);
124        mEventHandler.onMotionEvent(transformedEvent, rawEvent, policyFlags);
125        transformedEvent.recycle();
126    }
127
128    @Override
129    public void onMotionEvent(MotionEvent transformedEvent, MotionEvent rawEvent,
130            int policyFlags) {
131        sendInputEvent(transformedEvent, policyFlags);
132    }
133
134    @Override
135    public void onAccessibilityEvent(AccessibilityEvent event) {
136        // TODO Implement this to inject the accessibility event
137        //      into the accessibility manager service similarly
138        //      to how this is done for input events.
139    }
140
141    @Override
142    public void setNext(EventStreamTransformation sink) {
143        /* do nothing */
144    }
145
146    @Override
147    public void clear() {
148        /* do nothing */
149    }
150
151    void setEnabledFeatures(int enabledFeatures) {
152        if (mEnabledFeatures == enabledFeatures) {
153            return;
154        }
155        if (mInstalled) {
156            disableFeatures();
157        }
158        mEnabledFeatures = enabledFeatures;
159        if (mInstalled) {
160            enableFeatures();
161        }
162    }
163
164    void notifyAccessibilityEvent(AccessibilityEvent event) {
165        if (mEventHandler != null) {
166            mEventHandler.onAccessibilityEvent(event);
167        }
168    }
169
170    private void enableFeatures() {
171        if ((mEnabledFeatures & FLAG_FEATURE_SCREEN_MAGNIFIER) != 0) {
172            mEventHandler = mScreenMagnifier = new ScreenMagnifier(mContext);
173            mEventHandler.setNext(this);
174        }
175        if ((mEnabledFeatures & FLAG_FEATURE_TOUCH_EXPLORATION) != 0) {
176            mTouchExplorer = new TouchExplorer(mContext, mAms);
177            mTouchExplorer.setNext(this);
178            if (mEventHandler != null) {
179                mEventHandler.setNext(mTouchExplorer);
180            } else {
181                mEventHandler = mTouchExplorer;
182            }
183        }
184    }
185
186    private void disableFeatures() {
187        if (mTouchExplorer != null) {
188            mTouchExplorer.clear();
189            mTouchExplorer.onDestroy();
190            mTouchExplorer = null;
191        }
192        if (mScreenMagnifier != null) {
193            mScreenMagnifier.clear();
194            mScreenMagnifier.onDestroy();
195            mScreenMagnifier = null;
196        }
197        mEventHandler = null;
198    }
199
200    @Override
201    public void onDestroy() {
202        /* ignore */
203    }
204}
205