10029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown/*
20029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * Copyright (C) 2011 The Android Open Source Project
30029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown *
40029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
50029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * you may not use this file except in compliance with the License.
60029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * You may obtain a copy of the License at
70029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown *
80029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
90029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown *
100029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * Unless required by applicable law or agreed to in writing, software
110029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
120029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * See the License for the specific language governing permissions and
140029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * limitations under the License.
150029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown */
160029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
17c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganovpackage android.view;
180029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
190029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.os.Handler;
200029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.os.Looper;
210029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.os.Message;
22c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganovimport android.os.RemoteException;
23c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganovimport android.view.IInputFilter;
240029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.view.InputEvent;
2521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brownimport android.view.InputEventConsistencyVerifier;
260029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.view.KeyEvent;
270029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.view.MotionEvent;
280029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.view.WindowManagerPolicy;
290029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
300029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown/**
310029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * Filters input events before they are dispatched to the system.
320029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * <p>
330029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * At most one input filter can be installed by calling
340029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * {@link WindowManagerService#setInputFilter}.  When an input filter is installed, the
350029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * system's behavior changes as follows:
360029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * <ul>
370029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * <li>Input events are first delivered to the {@link WindowManagerPolicy}
384532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown * interception methods before queuing as usual.  This critical step takes care of managing
390029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * the power state of the device and handling wake keys.</li>
400029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * <li>Input events are then asynchronously delivered to the input filter's
410029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * {@link #onInputEvent(InputEvent)} method instead of being enqueued for dispatch to
420029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * applications as usual.  The input filter only receives input events that were
430029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * generated by input device; the input filter will not receive input events that were
440029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * injected into the system by other means, such as by instrumentation.</li>
450029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * <li>The input filter processes and optionally transforms the stream of events.  For example,
460029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * it may transform a sequence of motion events representing an accessibility gesture into
470029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * a different sequence of motion events, key presses or other system-level interactions.
480029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * The input filter can send events to be dispatched by calling
490029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * {@link #sendInputEvent(InputEvent)} and passing appropriate policy flags for the
500029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * input event.</li>
510029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * </ul>
520029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * </p>
530029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * <h3>The importance of input event consistency</h3>
540029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * <p>
550029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * The input filter mechanism is very low-level.  At a minimum, it needs to ensure that it
560029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * sends an internally consistent stream of input events to the dispatcher.  There are
570029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * very important invariants to be maintained.
580029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * </p><p>
590029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * For example, if a key down is sent, a corresponding key up should also be sent eventually.
600029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * Likewise, for touch events, each pointer must individually go down with
610029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * {@link MotionEvent#ACTION_DOWN} or {@link MotionEvent#ACTION_POINTER_DOWN} and then
620029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * individually go up with {@link MotionEvent#ACTION_POINTER_UP} or {@link MotionEvent#ACTION_UP}
630029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * and the sequence of pointer ids used must be consistent throughout the gesture.
640029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * </p><p>
650029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * Sometimes a filter may wish to cancel a previously dispatched key or motion.  It should
660029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * use {@link KeyEvent#FLAG_CANCELED} or {@link MotionEvent#ACTION_CANCEL} accordingly.
670029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * </p><p>
680029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * The input filter must take into account the fact that the input events coming from different
690029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * devices or even different sources all consist of distinct streams of input.
700029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * Use {@link InputEvent#getDeviceId()} and {@link InputEvent#getSource()} to identify
710029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * the source of the event and its semantics.  There are be multiple sources of keys,
720029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * touches and other input: they must be kept separate.
730029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * </p>
740029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * <h3>Policy flags</h3>
750029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * <p>
760029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * Input events received from the dispatcher and sent to the dispatcher have policy flags
770029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * associated with them.  Policy flags control some functions of the dispatcher.
780029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * </p><p>
790029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * The early policy interception decides whether an input event should be delivered
800029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * to applications or dropped.  The policy indicates its decision by setting the
810029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * {@link WindowManagerPolicy#FLAG_PASS_TO_USER} policy flag.  The input filter may
820029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * sometimes receive events that do not have this flag set.  It should take note of
830029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * the fact that the policy intends to drop the event, clean up its state, and
844532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown * then send appropriate cancellation events to the dispatcher if needed.
850029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * </p><p>
860029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * For example, suppose the input filter is processing a gesture and one of the touch events
870029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * it receives does not have the {@link WindowManagerPolicy#FLAG_PASS_TO_USER} flag set.
880029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * The input filter should clear its internal state about the gesture and then send key or
890029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * motion events to the dispatcher to cancel any keys or pointers that are down.
900029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * </p><p>
910029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * Corollary: Events that set sent to the dispatcher should usually include the
920029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * {@link WindowManagerPolicy#FLAG_PASS_TO_USER} flag.  Otherwise, they will be dropped!
930029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * </p><p>
944532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown * It may be prudent to disable automatic key repeating for synthetic key events
954532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown * by setting the {@link WindowManagerPolicy#FLAG_DISABLE_KEY_REPEAT} policy flag.
960029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown * </p>
97c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov *
98c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov * @hide
990029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown */
100c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganovpublic abstract class InputFilter extends IInputFilter.Stub {
1010029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    private static final int MSG_INSTALL = 1;
1020029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    private static final int MSG_UNINSTALL = 2;
1030029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    private static final int MSG_INPUT_EVENT = 3;
1040029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
10521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown    // Consistency verifiers for debugging purposes.
10621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown    private final InputEventConsistencyVerifier mInboundInputEventConsistencyVerifier =
10721bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
10821bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown                    new InputEventConsistencyVerifier(this,
109736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov                            InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT,
110736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov                            "InputFilter#InboundInputEventConsistencyVerifier") : null;
11121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown    private final InputEventConsistencyVerifier mOutboundInputEventConsistencyVerifier =
11221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
11321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown                    new InputEventConsistencyVerifier(this,
114736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov                            InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT,
115736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov                            "InputFilter#OutboundInputEventConsistencyVerifier") : null;
11621bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown
117c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov    private final H mH;
118c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov
119c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov    private IInputFilterHost mHost;
120c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov
1210029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    /**
1220029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * Creates the input filter.
1230029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     *
1240029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * @param looper The looper to run callbacks on.
1250029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     */
1260029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    public InputFilter(Looper looper) {
1270029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        mH = new H(looper);
1280029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
1290029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
1300029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    /**
1310029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * Called when the input filter is installed.
1320029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * This method is guaranteed to be non-reentrant.
1330029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     *
1340029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * @param host The input filter host environment.
1350029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     */
136c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov    public final void install(IInputFilterHost host) {
1370029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        mH.obtainMessage(MSG_INSTALL, host).sendToTarget();
1380029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
1390029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
1400029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    /**
1410029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * Called when the input filter is uninstalled.
1420029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * This method is guaranteed to be non-reentrant.
1430029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     */
144c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov    public final void uninstall() {
1450029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        mH.obtainMessage(MSG_UNINSTALL).sendToTarget();
1460029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
1470029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
1480029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    /**
1490029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * Called to enqueue the input event for filtering.
1500029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * The event will be recycled after the input filter processes it.
1510029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * This method is guaranteed to be non-reentrant.
1520029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     *
1530029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * @param event The input event to enqueue.
1540029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     */
155c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov    final public void filterInputEvent(InputEvent event, int policyFlags) {
1560029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        mH.obtainMessage(MSG_INPUT_EVENT, policyFlags, 0, event).sendToTarget();
1570029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
1580029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
1590029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    /**
1600029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * Sends an input event to the dispatcher.
1610029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     *
1620029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * @param event The input event to publish.
1630029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * @param policyFlags The input event policy flags.
1640029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     */
1650029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    public void sendInputEvent(InputEvent event, int policyFlags) {
1660029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        if (event == null) {
1670029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            throw new IllegalArgumentException("event must not be null");
1680029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        }
1690029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        if (mHost == null) {
1700029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            throw new IllegalStateException("Cannot send input event because the input filter " +
1710029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                    "is not installed.");
1720029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        }
17321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown        if (mOutboundInputEventConsistencyVerifier != null) {
17421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown            mOutboundInputEventConsistencyVerifier.onInputEvent(event, 0);
17521bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown        }
176c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov        try {
177c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov            mHost.sendInputEvent(event, policyFlags);
178c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov        } catch (RemoteException re) {
179c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov            /* ignore */
180c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov        }
1810029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
1820029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
1830029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    /**
1840029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * Called when an input event has been received from the dispatcher.
1850029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * <p>
1860029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * The default implementation sends the input event back to the dispatcher, unchanged.
1870029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * </p><p>
1880029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * The event will be recycled when this method returns.  If you want to keep it around,
1890029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * make a copy!
1900029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * </p>
1910029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     *
1920029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * @param event The input event that was received.
1930029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * @param policyFlags The input event policy flags.
1940029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     */
1950029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    public void onInputEvent(InputEvent event, int policyFlags) {
1960029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        sendInputEvent(event, policyFlags);
1970029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
1980029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
1990029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    /**
2000029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * Called when the filter is installed into the dispatch pipeline.
2010029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * <p>
2020029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * This method is called before the input filter receives any input events.
2030029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * The input filter should take this opportunity to prepare itself.
2040029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * </p>
2050029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     */
2060029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    public void onInstalled() {
2070029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
2080029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
2090029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    /**
2100029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * Called when the filter is uninstalled from the dispatch pipeline.
2110029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * <p>
2120029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * This method is called after the input filter receives its last input event.
2130029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * The input filter should take this opportunity to clean up.
2140029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * </p>
2150029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     */
2160029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    public void onUninstalled() {
2170029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
2180029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
2190029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    private final class H extends Handler {
2200029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        public H(Looper looper) {
2210029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            super(looper);
2220029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        }
2230029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
2240029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        @Override
2250029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        public void handleMessage(Message msg) {
2260029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            switch (msg.what) {
2270029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                case MSG_INSTALL:
228c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                    mHost = (IInputFilterHost) msg.obj;
22921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown                    if (mInboundInputEventConsistencyVerifier != null) {
23021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown                        mInboundInputEventConsistencyVerifier.reset();
23121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown                    }
23221bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown                    if (mOutboundInputEventConsistencyVerifier != null) {
23321bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown                        mOutboundInputEventConsistencyVerifier.reset();
23421bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown                    }
2350029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                    onInstalled();
2360029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                    break;
2370029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
2380029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                case MSG_UNINSTALL:
2390029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                    try {
2400029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                        onUninstalled();
2410029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                    } finally {
2420029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                        mHost = null;
2430029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                    }
2440029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                    break;
2450029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
2460029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                case MSG_INPUT_EVENT: {
2470029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                    final InputEvent event = (InputEvent)msg.obj;
2480029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                    try {
24921bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown                        if (mInboundInputEventConsistencyVerifier != null) {
25021bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown                            mInboundInputEventConsistencyVerifier.onInputEvent(event, 0);
25121bc5c917d4ee2a9b2b8173091e6bba85eaff899Jeff Brown                        }
2520029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                        onInputEvent(event, msg.arg1);
2530029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                    } finally {
2540029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                        event.recycle();
2550029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                    }
2560029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                    break;
2570029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                }
2580029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            }
2590029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        }
2600029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
2610029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown}
262