/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.view;

import android.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;

/**
 * Filters input events before they are dispatched to the system.
 * <p>
 * At most one input filter can be installed by calling
 * {@link WindowManagerService#setInputFilter}.  When an input filter is installed, the
 * system's behavior changes as follows:
 * <ul>
 * <li>Input events are first delivered to the {@link WindowManagerPolicy}
 * interception methods before queuing as usual.  This critical step takes care of managing
 * the power state of the device and handling wake keys.</li>
 * <li>Input events are then asynchronously delivered to the input filter's
 * {@link #onInputEvent(InputEvent)} method instead of being enqueued for dispatch to
 * applications as usual.  The input filter only receives input events that were
 * generated by an input device; the input filter will not receive input events that were
 * injected into the system by other means, such as by instrumentation.</li>
 * <li>The input filter processes and optionally transforms the stream of events.  For example,
 * it may transform a sequence of motion events representing an accessibility gesture into
 * a different sequence of motion events, key presses or other system-level interactions.
 * The input filter can send events to be dispatched by calling
 * {@link #sendInputEvent(InputEvent)} and passing appropriate policy flags for the
 * input event.</li>
 * </ul>
 * </p>
 * <h3>The importance of input event consistency</h3>
 * <p>
 * The input filter mechanism is very low-level.  At a minimum, it needs to ensure that it
 * sends an internally consistent stream of input events to the dispatcher.  There are
 * very important invariants to be maintained.
 * </p><p>
 * For example, if a key down is sent, a corresponding key up should also be sent eventually.
 * Likewise, for touch events, each pointer must individually go down with
 * {@link MotionEvent#ACTION_DOWN} or {@link MotionEvent#ACTION_POINTER_DOWN} and then
 * individually go up with {@link MotionEvent#ACTION_POINTER_UP} or {@link MotionEvent#ACTION_UP}
 * and the sequence of pointer ids used must be consistent throughout the gesture.
 * </p><p>
 * Sometimes a filter may wish to cancel a previously dispatched key or motion.  It should
 * use {@link KeyEvent#FLAG_CANCELED} or {@link MotionEvent#ACTION_CANCEL} accordingly.
 * </p><p>
 * The input filter must take into account the fact that the input events coming from different
 * devices or even different sources all consist of distinct streams of input.
 * Use {@link InputEvent#getDeviceId()} and {@link InputEvent#getSource()} to identify
 * the source of the event and its semantics.  There may be multiple sources of keys,
 * touches and other input: they must be kept separate.
 * </p>
 * <h3>Policy flags</h3>
 * <p>
 * Input events received from the dispatcher and sent to the dispatcher have policy flags
 * associated with them.  Policy flags control some functions of the dispatcher.
 * </p><p>
 * The early policy interception decides whether an input event should be delivered
 * to applications or dropped.  The policy indicates its decision by setting the
 * {@link WindowManagerPolicyConstants#FLAG_PASS_TO_USER} policy flag.  The input filter may
 * sometimes receive events that do not have this flag set.  It should take note of
 * the fact that the policy intends to drop the event, clean up its state, and
 * then send appropriate cancellation events to the dispatcher if needed.
 * </p><p>
 * For example, suppose the input filter is processing a gesture and one of the touch events
 * it receives does not have the {@link WindowManagerPolicyConstants#FLAG_PASS_TO_USER} flag set.
 * The input filter should clear its internal state about the gesture and then send key or
 * motion events to the dispatcher to cancel any keys or pointers that are down.
 * </p><p>
 * Corollary: Events that get sent to the dispatcher should usually include the
 * {@link WindowManagerPolicyConstants#FLAG_PASS_TO_USER} flag.  Otherwise, they will be dropped!
 * </p><p>
 * It may be prudent to disable automatic key repeating for synthetic key events
 * by setting the {@link WindowManagerPolicyConstants#FLAG_DISABLE_KEY_REPEAT} policy flag.
 * </p>
 *
 * @hide
 */
public abstract class InputFilter extends IInputFilter.Stub {
    private static final int MSG_INSTALL = 1;
    private static final int MSG_UNINSTALL = 2;
    private static final int MSG_INPUT_EVENT = 3;

    // Consistency verifiers for debugging purposes.
    private final InputEventConsistencyVerifier mInboundInputEventConsistencyVerifier =
            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
                    new InputEventConsistencyVerifier(this,
                            InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT,
                            "InputFilter#InboundInputEventConsistencyVerifier") : null;
    private final InputEventConsistencyVerifier mOutboundInputEventConsistencyVerifier =
            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
                    new InputEventConsistencyVerifier(this,
                            InputEventConsistencyVerifier.FLAG_RAW_DEVICE_INPUT,
                            "InputFilter#OutboundInputEventConsistencyVerifier") : null;

    private final H mH;

    private IInputFilterHost mHost;

    /**
     * Creates the input filter.
     *
     * @param looper The looper to run callbacks on.
     */
    @UnsupportedAppUsage
    public InputFilter(Looper looper) {
        mH = new H(looper);
    }

    /**
     * Called when the input filter is installed.
     * This method is guaranteed to be non-reentrant.
     *
     * @param host The input filter host environment.
     */
    public final void install(IInputFilterHost host) {
        mH.obtainMessage(MSG_INSTALL, host).sendToTarget();
    }

    /**
     * Called when the input filter is uninstalled.
     * This method is guaranteed to be non-reentrant.
     */
    public final void uninstall() {
        mH.obtainMessage(MSG_UNINSTALL).sendToTarget();
    }

    /**
     * Called to enqueue the input event for filtering.
     * The event will be recycled after the input filter processes it.
     * This method is guaranteed to be non-reentrant.
     *
     * @param event The input event to enqueue.
     */
    final public void filterInputEvent(InputEvent event, int policyFlags) {
        mH.obtainMessage(MSG_INPUT_EVENT, policyFlags, 0, event).sendToTarget();
    }

    /**
     * Sends an input event to the dispatcher.
     *
     * @param event The input event to publish.
     * @param policyFlags The input event policy flags.
     */
    public void sendInputEvent(InputEvent event, int policyFlags) {
        if (event == null) {
            throw new IllegalArgumentException("event must not be null");
        }
        if (mHost == null) {
            throw new IllegalStateException("Cannot send input event because the input filter " +
                    "is not installed.");
        }
        if (mOutboundInputEventConsistencyVerifier != null) {
            mOutboundInputEventConsistencyVerifier.onInputEvent(event, 0);
        }
        try {
            mHost.sendInputEvent(event, policyFlags);
        } catch (RemoteException re) {
            /* ignore */
        }
    }

    /**
     * Called when an input event has been received from the dispatcher.
     * <p>
     * The default implementation sends the input event back to the dispatcher, unchanged.
     * </p><p>
     * The event will be recycled when this method returns.  If you want to keep it around,
     * make a copy!
     * </p>
     *
     * @param event The input event that was received.
     * @param policyFlags The input event policy flags.
     */
    @UnsupportedAppUsage
    public void onInputEvent(InputEvent event, int policyFlags) {
        sendInputEvent(event, policyFlags);
    }

    /**
     * Called when the filter is installed into the dispatch pipeline.
     * <p>
     * This method is called before the input filter receives any input events.
     * The input filter should take this opportunity to prepare itself.
     * </p>
     */
    public void onInstalled() {
    }

    /**
     * Called when the filter is uninstalled from the dispatch pipeline.
     * <p>
     * This method is called after the input filter receives its last input event.
     * The input filter should take this opportunity to clean up.
     * </p>
     */
    public void onUninstalled() {
    }

    private final class H extends Handler {
        public H(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_INSTALL:
                    mHost = (IInputFilterHost) msg.obj;
                    if (mInboundInputEventConsistencyVerifier != null) {
                        mInboundInputEventConsistencyVerifier.reset();
                    }
                    if (mOutboundInputEventConsistencyVerifier != null) {
                        mOutboundInputEventConsistencyVerifier.reset();
                    }
                    onInstalled();
                    break;

                case MSG_UNINSTALL:
                    try {
                        onUninstalled();
                    } finally {
                        mHost = null;
                    }
                    break;

                case MSG_INPUT_EVENT: {
                    final InputEvent event = (InputEvent)msg.obj;
                    try {
                        if (mInboundInputEventConsistencyVerifier != null) {
                            mInboundInputEventConsistencyVerifier.onInputEvent(event, 0);
                        }
                        onInputEvent(event, msg.arg1);
                    } finally {
                        event.recycle();
                    }
                    break;
                }
            }
        }
    }
}
