/*
 * 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.compat.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;
                }
            }
        }
    }
}
