Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f527a1d9 authored by Jeff Brown's avatar Jeff Brown Committed by Android (Google) Code Review
Browse files

Merge "Prevent events from getting backlogged." into honeycomb

parents 3459e27e 928e0549
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ LOCAL_SRC_FILES:= \
    InputDispatcher.cpp \
    InputManager.cpp \
    InputReader.cpp \
    InputWindow.cpp \
    PointerController.cpp

LOCAL_SHARED_LIBRARIES := \
+51 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#ifndef _UI_INPUT_APPLICATION_H
#define _UI_INPUT_APPLICATION_H

#include <ui/Input.h>

#include <utils/RefBase.h>
#include <utils/Timers.h>
#include <utils/String8.h>

namespace android {

/*
 * A handle to an application that can receive input.
 * Used by the native input dispatcher to indirectly refer to the window manager objects
 * that describe an application.
 */
class InputApplicationHandle : public RefBase {
protected:
    InputApplicationHandle() { }
    virtual ~InputApplicationHandle() { }
};


/*
 * An input application describes properties of an application that can receive input.
 */
struct InputApplication {
    sp<InputApplicationHandle> inputApplicationHandle;
    String8 name;
    nsecs_t dispatchingTimeout;
};

} // namespace android

#endif // _UI_INPUT_APPLICATION_H
+121 −35
Original line number Diff line number Diff line
@@ -72,6 +72,10 @@ const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
// when an application takes too long to respond and the user has pressed an app switch key.
const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec

// Amount of time to allow for an event to be dispatched (measured since its eventTime)
// before considering it stale and dropping it.
const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec


static inline nsecs_t now() {
    return systemTime(SYSTEM_TIME_MONOTONIC);
@@ -151,34 +155,12 @@ static bool validateMotionEvent(int32_t action, size_t pointerCount,
}


// --- InputWindow ---

bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
    return x >= touchableAreaLeft && x <= touchableAreaRight
            && y >= touchableAreaTop && y <= touchableAreaBottom;
}

bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
    return x >= frameLeft && x <= frameRight
            && y >= frameTop && y <= frameBottom;
}

bool InputWindow::isTrustedOverlay() const {
    return layoutParamsType == TYPE_INPUT_METHOD
            || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
            || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
}

bool InputWindow::supportsSplitTouch() const {
    return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
}


// --- InputDispatcher ---

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
    mPolicy(policy),
    mPendingEvent(NULL), mAppSwitchDueTime(LONG_LONG_MAX),
    mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
    mNextUnblockedEvent(NULL),
    mDispatchEnabled(true), mDispatchFrozen(false),
    mFocusedWindow(NULL),
    mFocusedApplication(NULL),
@@ -368,6 +350,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
    }

    // Now we have an event to dispatch.
    // All events are eventually dequeued and processed this way, even if we intend to drop them.
    assert(mPendingEvent != NULL);
    bool done = false;
    DropReason dropReason = DROP_REASON_NOT_DROPPED;
@@ -376,6 +359,11 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
    } else if (!mDispatchEnabled) {
        dropReason = DROP_REASON_DISABLED;
    }

    if (mNextUnblockedEvent == mPendingEvent) {
        mNextUnblockedEvent = NULL;
    }

    switch (mPendingEvent->type) {
    case EventEntry::TYPE_CONFIGURATION_CHANGED: {
        ConfigurationChangedEntry* typedEntry =
@@ -395,6 +383,13 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
                dropReason = DROP_REASON_APP_SWITCH;
            }
        }
        if (dropReason == DROP_REASON_NOT_DROPPED
                && isStaleEventLocked(currentTime, typedEntry)) {
            dropReason = DROP_REASON_STALE;
        }
        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
            dropReason = DROP_REASON_BLOCKED;
        }
        done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout,
                &dropReason, nextWakeupTime);
        break;
@@ -405,6 +400,13 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout,
        if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
            dropReason = DROP_REASON_APP_SWITCH;
        }
        if (dropReason == DROP_REASON_NOT_DROPPED
                && isStaleEventLocked(currentTime, typedEntry)) {
            dropReason = DROP_REASON_STALE;
        }
        if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
            dropReason = DROP_REASON_BLOCKED;
        }
        done = dispatchMotionLocked(currentTime, typedEntry,
                &dropReason, nextWakeupTime);
        break;
@@ -431,6 +433,9 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {

    switch (entry->type) {
    case EventEntry::TYPE_KEY: {
        // Optimize app switch latency.
        // If the application takes too long to catch up then we drop all events preceding
        // the app switch key.
        KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
        if (isAppSwitchKeyEventLocked(keyEntry)) {
            if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
@@ -448,11 +453,63 @@ bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
        }
        break;
    }

    case EventEntry::TYPE_MOTION: {
        // Optimize case where the current application is unresponsive and the user
        // decides to touch a window in a different application.
        // If the application takes too long to catch up then we drop all events preceding
        // the touch into the other window.
        MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
        if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
                && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
                && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
                && mInputTargetWaitApplication != NULL) {
            int32_t x = int32_t(motionEntry->firstSample.pointerCoords[0].x);
            int32_t y = int32_t(motionEntry->firstSample.pointerCoords[0].y);
            const InputWindow* touchedWindow = findTouchedWindowAtLocked(x, y);
            if (touchedWindow
                    && touchedWindow->inputWindowHandle != NULL
                    && touchedWindow->inputWindowHandle->getInputApplicationHandle()
                            != mInputTargetWaitApplication) {
                // User touched a different application than the one we are waiting on.
                // Flag the event, and start pruning the input queue.
                mNextUnblockedEvent = motionEntry;
                needWake = true;
            }
        }
        break;
    }
    }

    return needWake;
}

const InputWindow* InputDispatcher::findTouchedWindowAtLocked(int32_t x, int32_t y) {
    // Traverse windows from front to back to find touched window.
    size_t numWindows = mWindows.size();
    for (size_t i = 0; i < numWindows; i++) {
        const InputWindow* window = & mWindows.editItemAt(i);
        int32_t flags = window->layoutParamsFlags;

        if (window->visible) {
            if (!(flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
                bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
                        | InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
                if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
                    // Found window.
                    return window;
                }
            }
        }

        if (flags & InputWindow::FLAG_SYSTEM_ERROR) {
            // Error window is on top but not visible, so touch is dropped.
            return NULL;
        }
    }
    return NULL;
}

void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
    const char* reason;
    switch (dropReason) {
@@ -470,6 +527,16 @@ void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropR
        LOGI("Dropped event because of pending overdue app switch.");
        reason = "inbound event was dropped because of pending overdue app switch";
        break;
    case DROP_REASON_BLOCKED:
        LOGI("Dropped event because the current application is not responding and the user "
                "has started interating with a different application.");
        reason = "inbound event was dropped because the current application is not responding "
                "and the user has started interating with a different application";
        break;
    case DROP_REASON_STALE:
        LOGI("Dropped event because it is stale.");
        reason = "inbound event was dropped because it is stale";
        break;
    default:
        assert(false);
        return;
@@ -521,6 +588,10 @@ void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
#endif
}

bool InputDispatcher::isStaleEventLocked(nsecs_t currentTime, EventEntry* entry) {
    return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT;
}

bool InputDispatcher::runCommandsLockedInterruptible() {
    if (mCommandQueue.isEmpty()) {
        return false;
@@ -670,7 +741,7 @@ bool InputDispatcher::dispatchKeyLocked(
            CommandEntry* commandEntry = postCommandLocked(
                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
            if (mFocusedWindow) {
                commandEntry->inputChannel = mFocusedWindow->inputChannel;
                commandEntry->inputWindowHandle = mFocusedWindow->inputWindowHandle;
            }
            commandEntry->keyEntry = entry;
            entry->refCount += 1;
@@ -848,6 +919,7 @@ void InputDispatcher::resetTargetsLocked() {
    mCurrentInputTargetsValid = false;
    mCurrentInputTargets.clear();
    mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
    mInputTargetWaitApplication.clear();
}

void InputDispatcher::commitTargetsLocked() {
@@ -866,6 +938,7 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
            mInputTargetWaitStartTime = currentTime;
            mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
            mInputTargetWaitTimeoutExpired = false;
            mInputTargetWaitApplication.clear();
        }
    } else {
        if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
@@ -880,6 +953,15 @@ int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
            mInputTargetWaitStartTime = currentTime;
            mInputTargetWaitTimeoutTime = currentTime + timeout;
            mInputTargetWaitTimeoutExpired = false;
            mInputTargetWaitApplication.clear();

            if (window && window->inputWindowHandle != NULL) {
                mInputTargetWaitApplication =
                        window->inputWindowHandle->getInputApplicationHandle();
            }
            if (mInputTargetWaitApplication == NULL && application) {
                mInputTargetWaitApplication = application->inputApplicationHandle;
            }
        }
    }

@@ -2624,7 +2706,7 @@ void InputDispatcher::setFocusedApplication(const InputApplication* inputApplica
void InputDispatcher::releaseFocusedApplicationLocked() {
    if (mFocusedApplication) {
        mFocusedApplication = NULL;
        mFocusedApplicationStorage.handle.clear();
        mFocusedApplicationStorage.inputApplicationHandle.clear();
    }
}

@@ -2860,7 +2942,8 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
    }
}

status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
        const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
#if DEBUG_REGISTRATION
    LOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
            toString(monitor));
@@ -2875,7 +2958,7 @@ status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChan
            return BAD_VALUE;
        }

        sp<Connection> connection = new Connection(inputChannel);
        sp<Connection> connection = new Connection(inputChannel, inputWindowHandle);
        status_t status = connection->initialize();
        if (status) {
            LOGE("Failed to initialize input publisher for input channel '%s', status=%d",
@@ -3002,9 +3085,10 @@ void InputDispatcher::onANRLocked(
    CommandEntry* commandEntry = postCommandLocked(
            & InputDispatcher::doNotifyANRLockedInterruptible);
    if (application) {
        commandEntry->inputApplicationHandle = application->handle;
        commandEntry->inputApplicationHandle = application->inputApplicationHandle;
    }
    if (window) {
        commandEntry->inputWindowHandle = window->inputWindowHandle;
        commandEntry->inputChannel = window->inputChannel;
    }
}
@@ -3025,7 +3109,7 @@ void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
    if (connection->status != Connection::STATUS_ZOMBIE) {
        mLock.unlock();

        mPolicy->notifyInputChannelBroken(connection->inputChannel);
        mPolicy->notifyInputChannelBroken(connection->inputWindowHandle);

        mLock.lock();
    }
@@ -3036,7 +3120,7 @@ void InputDispatcher::doNotifyANRLockedInterruptible(
    mLock.unlock();

    nsecs_t newTimeout = mPolicy->notifyANR(
            commandEntry->inputApplicationHandle, commandEntry->inputChannel);
            commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle);

    mLock.lock();

@@ -3052,7 +3136,7 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(

    mLock.unlock();

    bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputChannel,
    bool consumed = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
            &event, entry->policyFlags);

    mLock.lock();
@@ -3095,7 +3179,7 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(

                    mLock.unlock();

                    bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel,
                    bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
                            &event, keyEntry->policyFlags, &event);

                    mLock.lock();
@@ -3604,8 +3688,10 @@ bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& mement

// --- InputDispatcher::Connection ---

InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel) :
        status(STATUS_NORMAL), inputChannel(inputChannel), inputPublisher(inputChannel),
InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
        const sp<InputWindowHandle>& inputWindowHandle) :
        status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
        inputPublisher(inputChannel),
        lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
}

+28 −139
Original line number Diff line number Diff line
@@ -33,6 +33,9 @@
#include <unistd.h>
#include <limits.h>

#include "InputWindow.h"
#include "InputApplication.h"


namespace android {

@@ -115,137 +118,6 @@ struct InputTarget {
};


/*
 * An input window describes the bounds of a window that can receive input.
 */
struct InputWindow {
    // Window flags from WindowManager.LayoutParams
    enum {
        FLAG_ALLOW_LOCK_WHILE_SCREEN_ON     = 0x00000001,
        FLAG_DIM_BEHIND        = 0x00000002,
        FLAG_BLUR_BEHIND        = 0x00000004,
        FLAG_NOT_FOCUSABLE      = 0x00000008,
        FLAG_NOT_TOUCHABLE      = 0x00000010,
        FLAG_NOT_TOUCH_MODAL    = 0x00000020,
        FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
        FLAG_KEEP_SCREEN_ON     = 0x00000080,
        FLAG_LAYOUT_IN_SCREEN   = 0x00000100,
        FLAG_LAYOUT_NO_LIMITS   = 0x00000200,
        FLAG_FULLSCREEN      = 0x00000400,
        FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800,
        FLAG_DITHER             = 0x00001000,
        FLAG_SECURE             = 0x00002000,
        FLAG_SCALED             = 0x00004000,
        FLAG_IGNORE_CHEEK_PRESSES    = 0x00008000,
        FLAG_LAYOUT_INSET_DECOR = 0x00010000,
        FLAG_ALT_FOCUSABLE_IM = 0x00020000,
        FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
        FLAG_SHOW_WHEN_LOCKED = 0x00080000,
        FLAG_SHOW_WALLPAPER = 0x00100000,
        FLAG_TURN_SCREEN_ON = 0x00200000,
        FLAG_DISMISS_KEYGUARD = 0x00400000,
        FLAG_SPLIT_TOUCH = 0x00800000,
        FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
        FLAG_COMPATIBLE_WINDOW = 0x20000000,
        FLAG_SYSTEM_ERROR = 0x40000000,
    };

    // Window types from WindowManager.LayoutParams
    enum {
        FIRST_APPLICATION_WINDOW = 1,
        TYPE_BASE_APPLICATION   = 1,
        TYPE_APPLICATION        = 2,
        TYPE_APPLICATION_STARTING = 3,
        LAST_APPLICATION_WINDOW = 99,
        FIRST_SUB_WINDOW        = 1000,
        TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW,
        TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1,
        TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
        TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
        TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW+4,
        LAST_SUB_WINDOW         = 1999,
        FIRST_SYSTEM_WINDOW     = 2000,
        TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW,
        TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1,
        TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2,
        TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3,
        TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4,
        TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5,
        TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6,
        TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7,
        TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8,
        TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9,
        TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10,
        TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11,
        TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
        TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13,
        TYPE_STATUS_BAR_SUB_PANEL  = FIRST_SYSTEM_WINDOW+14,
        TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
        TYPE_DRAG               = FIRST_SYSTEM_WINDOW+16,
        TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+17,
        LAST_SYSTEM_WINDOW      = 2999,
    };

    sp<InputChannel> inputChannel;
    String8 name;
    int32_t layoutParamsFlags;
    int32_t layoutParamsType;
    nsecs_t dispatchingTimeout;
    int32_t frameLeft;
    int32_t frameTop;
    int32_t frameRight;
    int32_t frameBottom;
    int32_t visibleFrameLeft;
    int32_t visibleFrameTop;
    int32_t visibleFrameRight;
    int32_t visibleFrameBottom;
    int32_t touchableAreaLeft;
    int32_t touchableAreaTop;
    int32_t touchableAreaRight;
    int32_t touchableAreaBottom;
    bool visible;
    bool canReceiveKeys;
    bool hasFocus;
    bool hasWallpaper;
    bool paused;
    int32_t layer;
    int32_t ownerPid;
    int32_t ownerUid;

    bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
    bool frameContainsPoint(int32_t x, int32_t y) const;

    /* Returns true if the window is of a trusted type that is allowed to silently
     * overlay other windows for the purpose of implementing the secure views feature.
     * Trusted overlays, such as IME windows, can partly obscure other windows without causing
     * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
     */
    bool isTrustedOverlay() const;

    bool supportsSplitTouch() const;
};


/*
 * A private handle type used by the input manager to track the window.
 */
class InputApplicationHandle : public RefBase {
protected:
    InputApplicationHandle() { }
    virtual ~InputApplicationHandle() { }
};


/*
 * An input application describes properties of an application that can receive input.
 */
struct InputApplication {
    String8 name;
    nsecs_t dispatchingTimeout;
    sp<InputApplicationHandle> handle;
};


/*
 * Input dispatcher policy interface.
 *
@@ -267,10 +139,10 @@ public:
    /* Notifies the system that an application is not responding.
     * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
    virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
            const sp<InputChannel>& inputChannel) = 0;
            const sp<InputWindowHandle>& inputWindowHandle) = 0;

    /* Notifies the system that an input channel is unrecoverably broken. */
    virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) = 0;
    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0;

    /* Gets the key repeat initial timeout or -1 if automatic key repeating is disabled. */
    virtual nsecs_t getKeyRepeatTimeout() = 0;
@@ -303,12 +175,12 @@ public:
    virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;

    /* Allows the policy a chance to intercept a key before dispatching. */
    virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
    virtual bool interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
            const KeyEvent* keyEvent, uint32_t policyFlags) = 0;

    /* Allows the policy a chance to perform default processing for an unhandled key.
     * Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
    virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
            const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;

    /* Notifies the policy about switch events.
@@ -407,7 +279,8 @@ public:
     *
     * These methods may be called on any thread (usually by the input manager).
     */
    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) = 0;
    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
            const sp<InputWindowHandle>& inputWindowHandle, bool monitor) = 0;
    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
};

@@ -461,7 +334,8 @@ public:
    virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
            const sp<InputChannel>& toChannel);

    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor);
    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
            const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
    virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);

private:
@@ -615,6 +489,7 @@ private:
        KeyEntry* keyEntry;
        sp<InputChannel> inputChannel;
        sp<InputApplicationHandle> inputApplicationHandle;
        sp<InputWindowHandle> inputWindowHandle;
        int32_t userActivityEventType;
        bool handled;
    };
@@ -815,7 +690,8 @@ private:
        };

        Status status;
        sp<InputChannel> inputChannel;
        sp<InputChannel> inputChannel; // never null
        sp<InputWindowHandle> inputWindowHandle; // may be null
        InputPublisher inputPublisher;
        InputState inputState;
        Queue<DispatchEntry> outboundQueue;
@@ -823,7 +699,8 @@ private:
        nsecs_t lastEventTime; // the time when the event was originally captured
        nsecs_t lastDispatchTime; // the time when the last event was dispatched

        explicit Connection(const sp<InputChannel>& inputChannel);
        explicit Connection(const sp<InputChannel>& inputChannel,
                const sp<InputWindowHandle>& inputWindowHandle);

        inline const char* getInputChannelName() const { return inputChannel->getName().string(); }

@@ -851,6 +728,8 @@ private:
        DROP_REASON_POLICY = 1,
        DROP_REASON_APP_SWITCH = 2,
        DROP_REASON_DISABLED = 3,
        DROP_REASON_BLOCKED = 4,
        DROP_REASON_STALE = 5,
    };

    sp<InputDispatcherPolicyInterface> mPolicy;
@@ -884,6 +763,15 @@ private:
    bool isAppSwitchPendingLocked();
    void resetPendingAppSwitchLocked(bool handled);

    // Stale event latency optimization.
    static bool isStaleEventLocked(nsecs_t currentTime, EventEntry* entry);

    // Blocked event latency optimization.  Drops old events when the user intends
    // to transfer focus to a new application.
    EventEntry* mNextUnblockedEvent;

    const InputWindow* findTouchedWindowAtLocked(int32_t x, int32_t y);

    // All registered connections mapped by receive pipe file descriptor.
    KeyedVector<int, sp<Connection> > mConnectionsByReceiveFd;

@@ -1006,6 +894,7 @@ private:
    nsecs_t mInputTargetWaitStartTime;
    nsecs_t mInputTargetWaitTimeoutTime;
    bool mInputTargetWaitTimeoutExpired;
    sp<InputApplicationHandle> mInputTargetWaitApplication;

    // Finding targets for input events.
    void resetTargetsLocked();
+47 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#define LOG_TAG "InputWindow"

#include "InputWindow.h"

#include <cutils/log.h>

namespace android {

// --- InputWindow ---

bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
    return x >= touchableAreaLeft && x <= touchableAreaRight
            && y >= touchableAreaTop && y <= touchableAreaBottom;
}

bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
    return x >= frameLeft && x <= frameRight
            && y >= frameTop && y <= frameBottom;
}

bool InputWindow::isTrustedOverlay() const {
    return layoutParamsType == TYPE_INPUT_METHOD
            || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
            || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
}

bool InputWindow::supportsSplitTouch() const {
    return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
}

} // namespace android
Loading