diff options
| -rw-r--r-- | include/ui/InputDispatcher.h | 12 | ||||
| -rw-r--r-- | include/ui/InputTransport.h | 7 | ||||
| -rw-r--r-- | include/ui/PowerManager.h | 10 | ||||
| -rw-r--r-- | libs/ui/InputDispatcher.cpp | 78 | ||||
| -rw-r--r-- | libs/ui/InputTransport.cpp | 27 | ||||
| -rw-r--r-- | libs/ui/tests/InputDispatcher_test.cpp | 5 | ||||
| -rw-r--r-- | libs/ui/tests/InputPublisherAndConsumer_test.cpp | 14 | 
7 files changed, 98 insertions, 55 deletions
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h index a5591ba921..d09ff412de 100644 --- a/include/ui/InputDispatcher.h +++ b/include/ui/InputDispatcher.h @@ -304,6 +304,10 @@ public:      virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,              const KeyEvent* keyEvent, uint32_t policyFlags) = 0; +    /* Allows the policy a chance to perform default processing for an unhandled key. */ +    virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel, +            const KeyEvent* keyEvent, uint32_t policyFlags) = 0; +      /* Notifies the policy about switch events.       */      virtual void notifySwitch(nsecs_t when, @@ -609,6 +613,7 @@ private:          sp<InputChannel> inputChannel;          sp<InputApplicationHandle> inputApplicationHandle;          int32_t userActivityEventType; +        bool handled;      };      // Generic queue implementation. @@ -1030,7 +1035,8 @@ private:              EventEntry* eventEntry, const InputTarget* inputTarget,              bool resumeWithAppendedMotionSample);      void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection); -    void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection); +    void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection, +            bool handled);      void startNextDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);      void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);      void drainOutboundQueueLocked(Connection* connection); @@ -1061,7 +1067,7 @@ private:      void onDispatchCycleStartedLocked(              nsecs_t currentTime, const sp<Connection>& connection);      void onDispatchCycleFinishedLocked( -            nsecs_t currentTime, const sp<Connection>& connection); +            nsecs_t currentTime, const sp<Connection>& connection, bool handled);      void onDispatchCycleBrokenLocked(              nsecs_t currentTime, const sp<Connection>& connection);      void onANRLocked( @@ -1073,7 +1079,9 @@ private:      void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry);      void doNotifyANRLockedInterruptible(CommandEntry* commandEntry);      void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry); +    void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry);      void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry); +    void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry);      // Statistics gathering.      void updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry, diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h index dc9e27a985..7efb6cc9dc 100644 --- a/include/ui/InputTransport.h +++ b/include/ui/InputTransport.h @@ -250,12 +250,13 @@ public:      status_t sendDispatchSignal();      /* Receives the finished signal from the consumer in reply to the original dispatch signal. +     * Returns whether the consumer handled the message.       *       * Returns OK on success.       * Returns WOULD_BLOCK if there is no signal present.       * Other errors probably indicate that the channel is broken.       */ -    status_t receiveFinishedSignal(); +    status_t receiveFinishedSignal(bool& outHandled);  private:      sp<InputChannel> mChannel; @@ -305,12 +306,12 @@ public:      status_t consume(InputEventFactoryInterface* factory, InputEvent** outEvent);      /* Sends a finished signal to the publisher to inform it that the current message is -     * finished processing. +     * finished processing and specifies whether the message was handled by the consumer.       *       * Returns OK on success.       * Errors probably indicate that the channel is broken.       */ -    status_t sendFinishedSignal(); +    status_t sendFinishedSignal(bool handled);      /* Receives the dispatched signal from the publisher.       * diff --git a/include/ui/PowerManager.h b/include/ui/PowerManager.h index 5434b4f080..dd80318e63 100644 --- a/include/ui/PowerManager.h +++ b/include/ui/PowerManager.h @@ -22,14 +22,10 @@ namespace android {  enum {      POWER_MANAGER_OTHER_EVENT = 0, -    POWER_MANAGER_CHEEK_EVENT = 1, -    POWER_MANAGER_TOUCH_EVENT = 2, // touch events are TOUCH for 300ms, and then either -                                   // up events or LONG_TOUCH events. -    POWER_MANAGER_LONG_TOUCH_EVENT = 3, -    POWER_MANAGER_TOUCH_UP_EVENT = 4, -    POWER_MANAGER_BUTTON_EVENT = 5, // Button and trackball events. +    POWER_MANAGER_BUTTON_EVENT = 1, +    POWER_MANAGER_TOUCH_EVENT = 2, -    POWER_MANAGER_LAST_EVENT = POWER_MANAGER_BUTTON_EVENT, // Last valid event code. +    POWER_MANAGER_LAST_EVENT = POWER_MANAGER_TOUCH_EVENT, // Last valid event code.  };  } // namespace android diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp index f9c0b9154b..7ddb3c75ee 100644 --- a/libs/ui/InputDispatcher.cpp +++ b/libs/ui/InputDispatcher.cpp @@ -51,9 +51,6 @@  namespace android { -// Delay before reporting long touch events to the power manager. -const nsecs_t LONG_TOUCH_DELAY = 300 * 1000000LL; // 300 ms -  // Default input dispatching timeout if there is no focused application or paused window  // from which to determine an appropriate dispatching timeout.  const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec @@ -1416,21 +1413,7 @@ void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {          }          if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) { -            switch (motionEntry->action) { -            case AMOTION_EVENT_ACTION_DOWN: -                eventType = POWER_MANAGER_TOUCH_EVENT; -                break; -            case AMOTION_EVENT_ACTION_UP: -                eventType = POWER_MANAGER_TOUCH_UP_EVENT; -                break; -            default: -                if (motionEntry->eventTime - motionEntry->downTime < LONG_TOUCH_DELAY) { -                    eventType = POWER_MANAGER_TOUCH_EVENT; -                } else { -                    eventType = POWER_MANAGER_LONG_TOUCH_EVENT; -                } -                break; -            } +            eventType = POWER_MANAGER_TOUCH_EVENT;          }          break;      } @@ -1770,13 +1753,14 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,  }  void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, -        const sp<Connection>& connection) { +        const sp<Connection>& connection, bool handled) {  #if DEBUG_DISPATCH_CYCLE      LOGD("channel '%s' ~ finishDispatchCycle - %01.1fms since event, " -            "%01.1fms since dispatch", +            "%01.1fms since dispatch, handled=%s",              connection->getInputChannelName(),              connection->getEventLatencyMillis(currentTime), -            connection->getDispatchLatencyMillis(currentTime)); +            connection->getDispatchLatencyMillis(currentTime), +            toString(handled));  #endif      if (connection->status == Connection::STATUS_BROKEN @@ -1784,9 +1768,6 @@ void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,          return;      } -    // Notify other system components. -    onDispatchCycleFinishedLocked(currentTime, connection); -      // Reset the publisher since the event has been consumed.      // We do this now so that the publisher can release some of its internal resources      // while waiting for the next dispatch cycle to begin. @@ -1798,7 +1779,8 @@ void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,          return;      } -    startNextDispatchCycleLocked(currentTime, connection); +    // Notify other system components and prepare to start the next dispatch cycle. +    onDispatchCycleFinishedLocked(currentTime, connection, handled);  }  void InputDispatcher::startNextDispatchCycleLocked(nsecs_t currentTime, @@ -1898,7 +1880,8 @@ int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data              return 1;          } -        status_t status = connection->inputPublisher.receiveFinishedSignal(); +        bool handled = false; +        status_t status = connection->inputPublisher.receiveFinishedSignal(handled);          if (status) {              LOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",                      connection->getInputChannelName(), status); @@ -1907,7 +1890,7 @@ int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data              return 0; // remove the callback          } -        d->finishDispatchCycleLocked(currentTime, connection); +        d->finishDispatchCycleLocked(currentTime, connection, handled);          d->runCommandsLockedInterruptible();          return 1;      } // release lock @@ -2945,7 +2928,11 @@ void InputDispatcher::onDispatchCycleStartedLocked(  }  void InputDispatcher::onDispatchCycleFinishedLocked( -        nsecs_t currentTime, const sp<Connection>& connection) { +        nsecs_t currentTime, const sp<Connection>& connection, bool handled) { +    CommandEntry* commandEntry = postCommandLocked( +            & InputDispatcher::doDispatchCycleFinishedLockedInterruptible); +    commandEntry->connection = connection; +    commandEntry->handled = handled;  }  void InputDispatcher::onDispatchCycleBrokenLocked( @@ -3014,9 +3001,7 @@ void InputDispatcher::doNotifyANRLockedInterruptible(  void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(          CommandEntry* commandEntry) {      KeyEntry* entry = commandEntry->keyEntry; -    mReusableKeyEvent.initialize(entry->deviceId, entry->source, entry->action, entry->flags, -            entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount, -            entry->downTime, entry->eventTime); +    initializeKeyEvent(&mReusableKeyEvent, entry);      mLock.unlock(); @@ -3031,6 +3016,31 @@ void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(      mAllocator.releaseKeyEntry(entry);  } +void InputDispatcher::doDispatchCycleFinishedLockedInterruptible( +        CommandEntry* commandEntry) { +    sp<Connection> connection = commandEntry->connection; +    bool handled = commandEntry->handled; + +    if (!handled && !connection->outboundQueue.isEmpty()) { +        DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next; +        if (dispatchEntry->inProgress +                && dispatchEntry->hasForegroundTarget() +                && dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) { +            KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry); +            initializeKeyEvent(&mReusableKeyEvent, keyEntry); + +            mLock.unlock(); + +            mPolicy->dispatchUnhandledKey(connection->inputChannel, +                    & mReusableKeyEvent, keyEntry->policyFlags); + +            mLock.lock(); +        } +    } + +    startNextDispatchCycleLocked(now(), connection); +} +  void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {      mLock.unlock(); @@ -3039,6 +3049,12 @@ void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* comman      mLock.lock();  } +void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) { +    event->initialize(entry->deviceId, entry->source, entry->action, entry->flags, +            entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount, +            entry->downTime, entry->eventTime); +} +  void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,          int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {      // TODO Write some statistics about how long we spend waiting. diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp index 2c6346ebee..1885691040 100644 --- a/libs/ui/InputTransport.cpp +++ b/libs/ui/InputTransport.cpp @@ -35,8 +35,12 @@ static const int DEFAULT_MESSAGE_BUFFER_SIZE = 16384;  static const char INPUT_SIGNAL_DISPATCH = 'D';  // Signal sent by the consumer to the producer to inform it that it has finished -// consuming the most recent message. -static const char INPUT_SIGNAL_FINISHED = 'f'; +// consuming the most recent message and it handled it. +static const char INPUT_SIGNAL_FINISHED_HANDLED = 'f'; + +// Signal sent by the consumer to the producer to inform it that it has finished +// consuming the most recent message but it did not handle it. +static const char INPUT_SIGNAL_FINISHED_UNHANDLED = 'u';  // --- InputChannel --- @@ -497,7 +501,7 @@ status_t InputPublisher::sendDispatchSignal() {      return mChannel->sendSignal(INPUT_SIGNAL_DISPATCH);  } -status_t InputPublisher::receiveFinishedSignal() { +status_t InputPublisher::receiveFinishedSignal(bool& outHandled) {  #if DEBUG_TRANSPORT_ACTIONS      LOGD("channel '%s' publisher ~ receiveFinishedSignal",              mChannel->getName().string()); @@ -506,9 +510,14 @@ status_t InputPublisher::receiveFinishedSignal() {      char signal;      status_t result = mChannel->receiveSignal(& signal);      if (result) { +        outHandled = false;          return result;      } -    if (signal != INPUT_SIGNAL_FINISHED) { +    if (signal == INPUT_SIGNAL_FINISHED_HANDLED) { +        outHandled = true; +    } else if (signal == INPUT_SIGNAL_FINISHED_UNHANDLED) { +        outHandled = false; +    } else {          LOGE("channel '%s' publisher ~ Received unexpected signal '%c' from consumer",                  mChannel->getName().string(), signal);          return UNKNOWN_ERROR; @@ -626,13 +635,15 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, InputEvent*      return OK;  } -status_t InputConsumer::sendFinishedSignal() { +status_t InputConsumer::sendFinishedSignal(bool handled) {  #if DEBUG_TRANSPORT_ACTIONS -    LOGD("channel '%s' consumer ~ sendFinishedSignal", -            mChannel->getName().string()); +    LOGD("channel '%s' consumer ~ sendFinishedSignal: handled=%d", +            mChannel->getName().string(), handled);  #endif -    return mChannel->sendSignal(INPUT_SIGNAL_FINISHED); +    return mChannel->sendSignal(handled +            ? INPUT_SIGNAL_FINISHED_HANDLED +            : INPUT_SIGNAL_FINISHED_UNHANDLED);  }  status_t InputConsumer::receiveDispatchSignal() { diff --git a/libs/ui/tests/InputDispatcher_test.cpp b/libs/ui/tests/InputDispatcher_test.cpp index 8874dfe3c9..f352dbf6af 100644 --- a/libs/ui/tests/InputDispatcher_test.cpp +++ b/libs/ui/tests/InputDispatcher_test.cpp @@ -67,6 +67,11 @@ private:          return false;      } +    virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel, +            const KeyEvent* keyEvent, uint32_t policyFlags) { +        return false; +    } +      virtual void notifySwitch(nsecs_t when,              int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {      } diff --git a/libs/ui/tests/InputPublisherAndConsumer_test.cpp b/libs/ui/tests/InputPublisherAndConsumer_test.cpp index 952b974769..c6eac25e18 100644 --- a/libs/ui/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/ui/tests/InputPublisherAndConsumer_test.cpp @@ -118,13 +118,16 @@ void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() {      EXPECT_EQ(downTime, keyEvent->getDownTime());      EXPECT_EQ(eventTime, keyEvent->getEventTime()); -    status = mConsumer->sendFinishedSignal(); +    status = mConsumer->sendFinishedSignal(true);      ASSERT_EQ(OK, status)              << "consumer sendFinishedSignal should return OK"; -    status = mPublisher->receiveFinishedSignal(); +    bool handled = false; +    status = mPublisher->receiveFinishedSignal(handled);      ASSERT_EQ(OK, status)              << "publisher receiveFinishedSignal should return OK"; +    ASSERT_TRUE(handled) +            << "publisher receiveFinishedSignal should have set handled to consumer's reply";      status = mPublisher->reset();      ASSERT_EQ(OK, status) @@ -279,13 +282,16 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(          EXPECT_EQ(samplePointerCoords[offset].orientation, motionEvent->getOrientation(i));      } -    status = mConsumer->sendFinishedSignal(); +    status = mConsumer->sendFinishedSignal(false);      ASSERT_EQ(OK, status)              << "consumer sendFinishedSignal should return OK"; -    status = mPublisher->receiveFinishedSignal(); +    bool handled = true; +    status = mPublisher->receiveFinishedSignal(handled);      ASSERT_EQ(OK, status)              << "publisher receiveFinishedSignal should return OK"; +    ASSERT_FALSE(handled) +            << "publisher receiveFinishedSignal should have set handled to consumer's reply";      status = mPublisher->reset();      ASSERT_EQ(OK, status)  |