diff options
Diffstat (limited to 'libs')
-rw-r--r-- | libs/gui/SensorEventQueue.cpp | 18 | ||||
-rw-r--r-- | libs/ui/InputDispatcher.cpp | 123 | ||||
-rw-r--r-- | libs/ui/InputTransport.cpp | 11 | ||||
-rw-r--r-- | libs/utils/Looper.cpp | 14 |
4 files changed, 110 insertions, 56 deletions
diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp index c3a9f22..f935524 100644 --- a/libs/gui/SensorEventQueue.cpp +++ b/libs/gui/SensorEventQueue.cpp @@ -70,9 +70,13 @@ ssize_t SensorEventQueue::write(ASensorEvent const* events, size_t numEvents) ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents) { ssize_t size = mSensorChannel->read(events, numEvents*sizeof(events[0])); + LOGE_IF(size<0 && size!=-EAGAIN, + "SensorChannel::read error (%s)", strerror(-size)); if (size >= 0) { if (size % sizeof(events[0])) { // partial read!!! should never happen. + LOGE("SensorEventQueue partial read (event-size=%u, read=%d)", + sizeof(events[0]), int(size)); return -EINVAL; } // returns number of events read @@ -95,8 +99,18 @@ status_t SensorEventQueue::waitForEvent() const { const int fd = getFd(); sp<Looper> looper(getLooper()); - int32_t result = looper->pollOnce(-1); - return (result == fd) ? status_t(NO_ERROR) : status_t(-1); + + int32_t result; + do { + result = looper->pollOnce(-1); + if (result == ALOOPER_EVENT_ERROR) { + LOGE("SensorChannel::waitForEvent error (errno=%d)", errno); + result = -EPIPE; // unknown error, so we make up one + break; + } + } while (result != fd); + + return (result == fd) ? status_t(NO_ERROR) : result; } status_t SensorEventQueue::wake() const diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp index 6713817..1cf7592 100644 --- a/libs/ui/InputDispatcher.cpp +++ b/libs/ui/InputDispatcher.cpp @@ -122,7 +122,7 @@ InputDispatcher::~InputDispatcher() { AutoMutex _l(mLock); resetKeyRepeatLocked(); - releasePendingEventLocked(true); + releasePendingEventLocked(); drainInboundQueueLocked(); } @@ -174,7 +174,7 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, if (! mDispatchEnabled) { if (mPendingEvent || ! mInboundQueue.isEmpty()) { LOGI("Dropping pending events because input dispatch is disabled."); - releasePendingEventLocked(true); + releasePendingEventLocked(); drainInboundQueueLocked(); } return; @@ -281,51 +281,50 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t keyRepeatTimeout, // Now we have an event to dispatch. assert(mPendingEvent != NULL); - bool wasDispatched = false; - bool wasDropped = false; + bool done = false; switch (mPendingEvent->type) { case EventEntry::TYPE_CONFIGURATION_CHANGED: { ConfigurationChangedEntry* typedEntry = static_cast<ConfigurationChangedEntry*>(mPendingEvent); - wasDispatched = dispatchConfigurationChangedLocked(currentTime, typedEntry); + done = dispatchConfigurationChangedLocked(currentTime, typedEntry); break; } case EventEntry::TYPE_KEY: { KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent); - if (isAppSwitchPendingLocked()) { - if (isAppSwitchKey(typedEntry->keyCode)) { + bool appSwitchKey = isAppSwitchKey(typedEntry->keyCode); + bool dropEvent = isAppSwitchDue && ! appSwitchKey; + done = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout, dropEvent, + nextWakeupTime); + if (done) { + if (dropEvent) { + LOGI("Dropped key because of pending overdue app switch."); + } else if (appSwitchKey) { resetPendingAppSwitchLocked(true); - } else if (isAppSwitchDue) { - LOGI("Dropping key because of pending overdue app switch."); - wasDropped = true; - break; } } - wasDispatched = dispatchKeyLocked(currentTime, typedEntry, keyRepeatTimeout, - nextWakeupTime); break; } case EventEntry::TYPE_MOTION: { MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent); - if (isAppSwitchDue) { - LOGI("Dropping motion because of pending overdue app switch."); - wasDropped = true; - break; + bool dropEvent = isAppSwitchDue; + done = dispatchMotionLocked(currentTime, typedEntry, dropEvent, nextWakeupTime); + if (done) { + if (dropEvent) { + LOGI("Dropped motion because of pending overdue app switch."); + } } - wasDispatched = dispatchMotionLocked(currentTime, typedEntry, nextWakeupTime); break; } default: assert(false); - wasDropped = true; break; } - if (wasDispatched || wasDropped) { - releasePendingEventLocked(wasDropped); + if (done) { + releasePendingEventLocked(); *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately } } @@ -403,21 +402,21 @@ InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command comman void InputDispatcher::drainInboundQueueLocked() { while (! mInboundQueue.isEmpty()) { EventEntry* entry = mInboundQueue.dequeueAtHead(); - releaseInboundEventLocked(entry, true /*wasDropped*/); + releaseInboundEventLocked(entry); } } -void InputDispatcher::releasePendingEventLocked(bool wasDropped) { +void InputDispatcher::releasePendingEventLocked() { if (mPendingEvent) { - releaseInboundEventLocked(mPendingEvent, wasDropped); + releaseInboundEventLocked(mPendingEvent); mPendingEvent = NULL; } } -void InputDispatcher::releaseInboundEventLocked(EventEntry* entry, bool wasDropped) { - if (wasDropped) { +void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) { + if (entry->injectionResult == INPUT_EVENT_INJECTION_PENDING) { #if DEBUG_DISPATCH_CYCLE - LOGD("Pending event was dropped."); + LOGD("Inbound event was dropped. Setting injection result to failed."); #endif setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED); } @@ -492,7 +491,41 @@ bool InputDispatcher::dispatchConfigurationChangedLocked( bool InputDispatcher::dispatchKeyLocked( nsecs_t currentTime, KeyEntry* entry, nsecs_t keyRepeatTimeout, - nsecs_t* nextWakeupTime) { + bool dropEvent, nsecs_t* nextWakeupTime) { + // Give the policy a chance to intercept the key. + if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) { + bool trusted; + if (! dropEvent && mFocusedWindow) { + trusted = checkInjectionPermission(mFocusedWindow, + entry->injectorPid, entry->injectorUid); + } else { + trusted = isEventFromReliableSourceLocked(entry); + } + if (trusted) { + CommandEntry* commandEntry = postCommandLocked( + & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible); + if (! dropEvent && mFocusedWindow) { + commandEntry->inputChannel = mFocusedWindow->inputChannel; + } + commandEntry->keyEntry = entry; + entry->refCount += 1; + return false; // wait for the command to run + } else { + entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE; + } + } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) { + resetTargetsLocked(); + setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_SUCCEEDED); + return true; + } + + // Clean up if dropping the event. + if (dropEvent) { + resetTargetsLocked(); + setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED); + return true; + } + // Preprocessing. if (! entry->dispatchInProgress) { logOutboundKeyDetailsLocked("dispatchKey - ", entry); @@ -521,7 +554,7 @@ bool InputDispatcher::dispatchKeyLocked( } entry->dispatchInProgress = true; - startFindingTargetsLocked(); // resets mCurrentInputTargetsValid + resetTargetsLocked(); } // Identify targets. @@ -539,20 +572,7 @@ bool InputDispatcher::dispatchKeyLocked( } addMonitoringTargetsLocked(); - finishFindingTargetsLocked(window); - } - - // Give the policy a chance to intercept the key. - if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) { - CommandEntry* commandEntry = postCommandLocked( - & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible); - commandEntry->inputChannel = mCurrentInputChannel; - commandEntry->keyEntry = entry; - entry->refCount += 1; - return false; // wait for the command to run - } - if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) { - return true; + commitTargetsLocked(window); } // Dispatch the key. @@ -576,13 +596,20 @@ void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyE } bool InputDispatcher::dispatchMotionLocked( - nsecs_t currentTime, MotionEntry* entry, nsecs_t* nextWakeupTime) { + nsecs_t currentTime, MotionEntry* entry, bool dropEvent, nsecs_t* nextWakeupTime) { + // Clean up if dropping the event. + if (dropEvent) { + resetTargetsLocked(); + setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED); + return true; + } + // Preprocessing. if (! entry->dispatchInProgress) { logOutboundMotionDetailsLocked("dispatchMotion - ", entry); entry->dispatchInProgress = true; - startFindingTargetsLocked(); // resets mCurrentInputTargetsValid + resetTargetsLocked(); } bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER; @@ -610,7 +637,7 @@ bool InputDispatcher::dispatchMotionLocked( } addMonitoringTargetsLocked(); - finishFindingTargetsLocked(window); + commitTargetsLocked(window); } // Dispatch the motion. @@ -705,14 +732,14 @@ void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTi } } -void InputDispatcher::startFindingTargetsLocked() { +void InputDispatcher::resetTargetsLocked() { mCurrentInputTargetsValid = false; mCurrentInputTargets.clear(); mCurrentInputChannel.clear(); mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE; } -void InputDispatcher::finishFindingTargetsLocked(const InputWindow* window) { +void InputDispatcher::commitTargetsLocked(const InputWindow* window) { mCurrentInputWindowType = window->layoutParamsType; mCurrentInputChannel = window->inputChannel; mCurrentInputTargetsValid = true; diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp index 4c402dc..2c6346e 100644 --- a/libs/ui/InputTransport.cpp +++ b/libs/ui/InputTransport.cpp @@ -131,7 +131,10 @@ status_t InputChannel::openInputChannelPair(const String8& name, } status_t InputChannel::sendSignal(char signal) { - ssize_t nWrite = ::write(mSendPipeFd, & signal, 1); + ssize_t nWrite; + do { + nWrite = ::write(mSendPipeFd, & signal, 1); + } while (nWrite == -1 && errno == EINTR); if (nWrite == 1) { #if DEBUG_CHANNEL_SIGNALS @@ -147,7 +150,11 @@ status_t InputChannel::sendSignal(char signal) { } status_t InputChannel::receiveSignal(char* outSignal) { - ssize_t nRead = ::read(mReceivePipeFd, outSignal, 1); + ssize_t nRead; + do { + nRead = ::read(mReceivePipeFd, outSignal, 1); + } while (nRead == -1 && errno == EINTR); + if (nRead == 1) { #if DEBUG_CHANNEL_SIGNALS LOGD("channel '%s' ~ received signal '%c'", mName.string(), *outSignal); diff --git a/libs/utils/Looper.cpp b/libs/utils/Looper.cpp index fd287da..4aa50d6 100644 --- a/libs/utils/Looper.cpp +++ b/libs/utils/Looper.cpp @@ -162,9 +162,11 @@ int Looper::pollInner(int timeoutMillis) { struct epoll_event eventItems[EPOLL_MAX_EVENTS]; int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis); if (eventCount < 0) { - if (errno != EINTR) { - LOGW("Poll failed with an unexpected error, errno=%d", errno); + if (errno == EINTR) { + return ALOOPER_POLL_WAKE; } + + LOGW("Poll failed with an unexpected error, errno=%d", errno); return ALOOPER_POLL_ERROR; } @@ -196,7 +198,7 @@ int Looper::pollInner(int timeoutMillis) { ssize_t nRead; do { nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer)); - } while (nRead == sizeof(buffer)); + } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer)); } else { LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents); } @@ -272,7 +274,11 @@ void Looper::wake() { LOGD("%p ~ wake", this); #endif - ssize_t nWrite = write(mWakeWritePipeFd, "W", 1); + ssize_t nWrite; + do { + nWrite = write(mWakeWritePipeFd, "W", 1); + } while (nWrite == -1 && errno == EINTR); + if (nWrite != 1) { if (errno != EAGAIN) { LOGW("Could not write wake signal, errno=%d", errno); |