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 android.view; 18 19import android.os.Handler; 20import android.os.Looper; 21import android.os.Message; 22import android.os.RemoteException; 23 24/** 25 * Filters input events before they are dispatched to the system. 26 * <p> 27 * At most one input filter can be installed by calling 28 * {@link WindowManagerService#setInputFilter}. When an input filter is installed, the 29 * system's behavior changes as follows: 30 * <ul> 31 * <li>Input events are first delivered to the {@link WindowManagerPolicy} 32 * interception methods before queuing as usual. This critical step takes care of managing 33 * the power state of the device and handling wake keys.</li> 34 * <li>Input events are then asynchronously delivered to the input filter's 35 * {@link #onInputEvent(InputEvent)} method instead of being enqueued for dispatch to 36 * applications as usual. The input filter only receives input events that were 37 * generated by an input device; the input filter will not receive input events that were 38 * injected into the system by other means, such as by instrumentation.</li> 39 * <li>The input filter processes and optionally transforms the stream of events. For example, 40 * it may transform a sequence of motion events representing an accessibility gesture into 41 * a different sequence of motion events, key presses or other system-level interactions. 42 * The input filter can send events to be dispatched by calling 43 * {@link #sendInputEvent(InputEvent)} and passing appropriate policy flags for the 44 * input event.</li> 45 * </ul> 46 * </p> 47 * <h3>The importance of input event consistency</h3> 48 * <p> 49 * The input filter mechanism is very low-level. At a minimum, it needs to ensure that it 50 * sends an internally consistent stream of input events to the dispatcher. There are 51 * very important invariants to be maintained. 52 * </p><p> 53 * For example, if a key down is sent, a corresponding key up should also be sent eventually. 54 * Likewise, for touch events, each pointer must individually go down with 55 * {@link MotionEvent#ACTION_DOWN} or {@link MotionEvent#ACTION_POINTER_DOWN} and then 56 * individually go up with {@link MotionEvent#ACTION_POINTER_UP} or {@link MotionEvent#ACTION_UP} 57 * and the sequence of pointer ids used must be consistent throughout the gesture. 58 * </p><p> 59 * Sometimes a filter may wish to cancel a previously dispatched key or motion. It should 60 * use {@link KeyEvent#FLAG_CANCELED} or {@link MotionEvent#ACTION_CANCEL} accordingly. 61 * </p><p> 62 * The input filter must take into account the fact that the input events coming from different 63 * devices or even different sources all consist of distinct streams of input. 64 * Use {@link InputEvent#getDeviceId()} and {@link InputEvent#getSource()} to identify 65 * the source of the event and its semantics. There may be multiple sources of keys, 66 * touches and other input: they must be kept separate. 67 * </p> 68 * <h3>Policy flags</h3> 69 * <p> 70 * Input events received from the dispatcher and sent to the dispatcher have policy flags 71 * associated with them. Policy flags control some functions of the dispatcher. 72 * </p><p> 73 * The early policy interception decides whether an input event should be delivered 74 * to applications or dropped. The policy indicates its decision by setting the 75 * {@link WindowManagerPolicyConstants#FLAG_PASS_TO_USER} policy flag. The input filter may 76 * sometimes receive events that do not have this flag set. It should take note of 77 * the fact that the policy intends to drop the event, clean up its state, and 78 * then send appropriate cancellation events to the dispatcher if needed. 79 * </p><p> 80 * For example, suppose the input filter is processing a gesture and one of the touch events 81 * it receives does not have the {@link WindowManagerPolicyConstants#FLAG_PASS_TO_USER} flag set. 82 * The input filter should clear its internal state about the gesture and then send key or 83 * motion events to the dispatcher to cancel any keys or pointers that are down. 84 * </p><p> 85 * Corollary: Events that get sent to the dispatcher should usually include the 86 * {@link WindowManagerPolicyConstants#FLAG_PASS_TO_USER} flag. Otherwise, they will be dropped! 87 * </p><p> 88 * It may be prudent to disable automatic key repeating for synthetic key events 89 * by setting the {@link WindowManagerPolicyConstants#FLAG_DISABLE_KEY_REPEAT} policy flag. 90 * </p> 91 * 92 * @hide 93 */ 94public abstract class InputFilter extends IInputFilter.Stub { 95 private static final int MSG_INSTALL = 1; 96 private static final int MSG_UNINSTALL = 2; 97 private static final int MSG_INPUT_EVENT = 3; 98 99 // Consistency verifiers for debugging purposes. 100 private final InputEventConsistencyVerifier mInboundInputEventConsistencyVerifier = 101 InputEventConsistencyVerifier.isInstrumentationEnabled() ? 102 new InputEventConsistencyVerifier(this, 103 InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT, 104 "InputFilter#InboundInputEventConsistencyVerifier") : null; 105 private final InputEventConsistencyVerifier mOutboundInputEventConsistencyVerifier = 106 InputEventConsistencyVerifier.isInstrumentationEnabled() ? 107 new InputEventConsistencyVerifier(this, 108 InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT, 109 "InputFilter#OutboundInputEventConsistencyVerifier") : null; 110 111 private final H mH; 112 113 private IInputFilterHost mHost; 114 115 /** 116 * Creates the input filter. 117 * 118 * @param looper The looper to run callbacks on. 119 */ 120 public InputFilter(Looper looper) { 121 mH = new H(looper); 122 } 123 124 /** 125 * Called when the input filter is installed. 126 * This method is guaranteed to be non-reentrant. 127 * 128 * @param host The input filter host environment. 129 */ 130 public final void install(IInputFilterHost host) { 131 mH.obtainMessage(MSG_INSTALL, host).sendToTarget(); 132 } 133 134 /** 135 * Called when the input filter is uninstalled. 136 * This method is guaranteed to be non-reentrant. 137 */ 138 public final void uninstall() { 139 mH.obtainMessage(MSG_UNINSTALL).sendToTarget(); 140 } 141 142 /** 143 * Called to enqueue the input event for filtering. 144 * The event will be recycled after the input filter processes it. 145 * This method is guaranteed to be non-reentrant. 146 * 147 * @param event The input event to enqueue. 148 */ 149 final public void filterInputEvent(InputEvent event, int policyFlags) { 150 mH.obtainMessage(MSG_INPUT_EVENT, policyFlags, 0, event).sendToTarget(); 151 } 152 153 /** 154 * Sends an input event to the dispatcher. 155 * 156 * @param event The input event to publish. 157 * @param policyFlags The input event policy flags. 158 */ 159 public void sendInputEvent(InputEvent event, int policyFlags) { 160 if (event == null) { 161 throw new IllegalArgumentException("event must not be null"); 162 } 163 if (mHost == null) { 164 throw new IllegalStateException("Cannot send input event because the input filter " + 165 "is not installed."); 166 } 167 if (mOutboundInputEventConsistencyVerifier != null) { 168 mOutboundInputEventConsistencyVerifier.onInputEvent(event, 0); 169 } 170 try { 171 mHost.sendInputEvent(event, policyFlags); 172 } catch (RemoteException re) { 173 /* ignore */ 174 } 175 } 176 177 /** 178 * Called when an input event has been received from the dispatcher. 179 * <p> 180 * The default implementation sends the input event back to the dispatcher, unchanged. 181 * </p><p> 182 * The event will be recycled when this method returns. If you want to keep it around, 183 * make a copy! 184 * </p> 185 * 186 * @param event The input event that was received. 187 * @param policyFlags The input event policy flags. 188 */ 189 public void onInputEvent(InputEvent event, int policyFlags) { 190 sendInputEvent(event, policyFlags); 191 } 192 193 /** 194 * Called when the filter is installed into the dispatch pipeline. 195 * <p> 196 * This method is called before the input filter receives any input events. 197 * The input filter should take this opportunity to prepare itself. 198 * </p> 199 */ 200 public void onInstalled() { 201 } 202 203 /** 204 * Called when the filter is uninstalled from the dispatch pipeline. 205 * <p> 206 * This method is called after the input filter receives its last input event. 207 * The input filter should take this opportunity to clean up. 208 * </p> 209 */ 210 public void onUninstalled() { 211 } 212 213 private final class H extends Handler { 214 public H(Looper looper) { 215 super(looper); 216 } 217 218 @Override 219 public void handleMessage(Message msg) { 220 switch (msg.what) { 221 case MSG_INSTALL: 222 mHost = (IInputFilterHost) msg.obj; 223 if (mInboundInputEventConsistencyVerifier != null) { 224 mInboundInputEventConsistencyVerifier.reset(); 225 } 226 if (mOutboundInputEventConsistencyVerifier != null) { 227 mOutboundInputEventConsistencyVerifier.reset(); 228 } 229 onInstalled(); 230 break; 231 232 case MSG_UNINSTALL: 233 try { 234 onUninstalled(); 235 } finally { 236 mHost = null; 237 } 238 break; 239 240 case MSG_INPUT_EVENT: { 241 final InputEvent event = (InputEvent)msg.obj; 242 try { 243 if (mInboundInputEventConsistencyVerifier != null) { 244 mInboundInputEventConsistencyVerifier.onInputEvent(event, 0); 245 } 246 onInputEvent(event, msg.arg1); 247 } finally { 248 event.recycle(); 249 } 250 break; 251 } 252 } 253 } 254 } 255} 256