From 909106e52a8534a231f2292e99e1c1e478e7f569 Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Thu, 16 Sep 2010 12:31:46 -0700 Subject: [PATCH 1/4] Fix input dispatcher regression on launcher drag&drop. Change-Id: I40e937bd712cd2ed6cceac95dfd1b8c8e070724f --- libs/ui/InputDispatcher.cpp | 79 ++++++++++++++----------------------- 1 file changed, 30 insertions(+), 49 deletions(-) diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp index 3b3c48317..0524ea43a 100644 --- a/libs/ui/InputDispatcher.cpp +++ b/libs/ui/InputDispatcher.cpp @@ -776,6 +776,9 @@ void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout // Give up. mInputTargetWaitTimeoutExpired = true; + // Release the touch target. + releaseTouchedWindowLocked(); + // Input state will not be realistic. Mark it out of sync. ssize_t connectionIndex = getConnectionIndexLocked(inputChannel); if (connectionIndex >= 0) { @@ -2157,9 +2160,8 @@ void InputDispatcher::setInputWindows(const Vector& inputWindows) { { // acquire lock AutoMutex _l(mLock); - sp oldFocusedWindowChannel = mFocusedWindow - ? mFocusedWindow->inputChannel : NULL; - int32_t oldFocusedWindowLayer = mFocusedWindow ? mFocusedWindow->layer : -1; + // Clear old window pointers but remember their associated channels. + mFocusedWindow = NULL; sp touchedWindowChannel; if (mTouchedWindow) { @@ -2173,11 +2175,11 @@ void InputDispatcher::setInputWindows(const Vector& inputWindows) { } mTouchedWallpaperWindows.clear(); } - - mFocusedWindow = NULL; mWallpaperWindows.clear(); - mWindows.clear(); + + // Loop over new windows and rebuild the necessary window pointers for + // tracking focus and touch. mWindows.appendVector(inputWindows); size_t numWindows = mWindows.size(); @@ -2201,41 +2203,8 @@ void InputDispatcher::setInputWindows(const Vector& inputWindows) { mTouchedWindow = window; } } - mTempTouchedWallpaperChannels.clear(); - bool preempt = false; - if (mFocusedWindow - && mFocusedWindow->inputChannel != oldFocusedWindowChannel - && mFocusedWindow->canReceiveKeys) { - // If the new input focus is an error window or appears above the current - // input focus, drop the current touched window so that we can start - // delivering events to the new input focus as soon as possible. - if (mFocusedWindow->layoutParamsFlags & InputWindow::FLAG_SYSTEM_ERROR) { -#if DEBUG_FOCUS - LOGD("Preempting: New SYSTEM_ERROR window; resetting state"); -#endif - preempt = true; - } else if (oldFocusedWindowChannel.get() != NULL - && mFocusedWindow->layer > oldFocusedWindowLayer) { -#if DEBUG_FOCUS - LOGD("Preempting: Transferring focus to new window at higher layer: " - "old win layer=%d, new win layer=%d", - oldFocusedWindowLayer, mFocusedWindow->layer); -#endif - preempt = true; - } - } - if (mTouchedWindow && ! mTouchedWindow->visible) { -#if DEBUG_FOCUS - LOGD("Preempting: Touched window became invisible."); -#endif - preempt = true; - } - if (preempt) { - releaseTouchedWindowLocked(); - } - #if DEBUG_FOCUS logDispatchStateLocked(); #endif @@ -2310,7 +2279,17 @@ void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) { void InputDispatcher::logDispatchStateLocked() { String8 dump; dumpDispatchStateLocked(dump); - LOGD("%s", dump.string()); + + char* text = dump.lockBuffer(dump.size()); + char* start = text; + while (*start != '\0') { + char* end = strchr(start, '\n'); + if (*end == '\n') { + *(end++) = '\0'; + } + LOGD("%s", start); + start = end; + } } void InputDispatcher::dumpDispatchStateLocked(String8& dump) { @@ -2324,28 +2303,30 @@ void InputDispatcher::dumpDispatchStateLocked(String8& dump) { } else { dump.append(" focusedApplication: \n"); } - dump.appendFormat(" focusedWindow: '%s'\n", - mFocusedWindow != NULL ? mFocusedWindow->inputChannel->getName().string() : ""); - dump.appendFormat(" touchedWindow: '%s', touchDown=%d\n", - mTouchedWindow != NULL ? mTouchedWindow->inputChannel->getName().string() : "", + dump.appendFormat(" focusedWindow: name='%s'\n", + mFocusedWindow != NULL ? mFocusedWindow->name.string() : ""); + dump.appendFormat(" touchedWindow: name='%s', touchDown=%d\n", + mTouchedWindow != NULL ? mTouchedWindow->name.string() : "", mTouchDown); for (size_t i = 0; i < mTouchedWallpaperWindows.size(); i++) { - dump.appendFormat(" touchedWallpaperWindows[%d]: '%s'\n", - i, mTouchedWallpaperWindows[i]->inputChannel->getName().string()); + dump.appendFormat(" touchedWallpaperWindows[%d]: name='%s'\n", + i, mTouchedWallpaperWindows[i]->name.string()); } for (size_t i = 0; i < mWindows.size(); i++) { - dump.appendFormat(" windows[%d]: '%s', paused=%s, hasFocus=%s, hasWallpaper=%s, " - "visible=%s, flags=0x%08x, type=0x%08x, " + dump.appendFormat(" windows[%d]: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, " + "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, " "frame=[%d,%d][%d,%d], " "visibleFrame=[%d,%d][%d,%d], " "touchableArea=[%d,%d][%d,%d], " "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n", - i, mWindows[i].inputChannel->getName().string(), + i, mWindows[i].name.string(), toString(mWindows[i].paused), toString(mWindows[i].hasFocus), toString(mWindows[i].hasWallpaper), toString(mWindows[i].visible), + toString(mWindows[i].canReceiveKeys), mWindows[i].layoutParamsFlags, mWindows[i].layoutParamsType, + mWindows[i].layer, mWindows[i].frameLeft, mWindows[i].frameTop, mWindows[i].frameRight, mWindows[i].frameBottom, mWindows[i].visibleFrameLeft, mWindows[i].visibleFrameTop, From 5a38ac119900c5960ff9db7bbf7999199c1febeb Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Tue, 28 Sep 2010 13:24:41 -0700 Subject: [PATCH 2/4] Fix bug in split touches. Cherry-picked down to master. Change-Id: I786761bd6aecc021ae22d8c9a022324f3a9980d1 --- libs/ui/InputDispatcher.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp index 9e78a4a4b..88d7cafd4 100644 --- a/libs/ui/InputDispatcher.cpp +++ b/libs/ui/InputDispatcher.cpp @@ -1070,7 +1070,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, } // Figure out whether splitting will be allowed for this window. - if (newTouchedWindow->layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH) { + if (newTouchedWindow + && (newTouchedWindow->layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH)) { // New window supports splitting. isSplit = true; } else if (isSplit) { From a0d9ab293354f955bbf486b5f04b076259bd635c Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 18 Jan 2011 15:51:30 -0800 Subject: [PATCH 3/4] fix [3361121] hang in glClear() - device unresponsive, OTA fails Generally we never want to lock a buffer for write access if it is at the "head" on the surfaceflinger side. The only exception (1) is when the buffer is not currently in use AND there is at least one queued buffer -- in which case, SurfaceFlinger will never use said buffer anymore, because on the next composition around, it will be able to retire the first queued buffer. The logic above relies on SurfaceFlinger always retiring and locking a buffer before composition -- unfortunately this didn't happen during a screenshot. This could leave us in a situation where a buffer is locked by the application for write, and used by SurfaceFlinger for texturing, causing a hang. Here, we fix this issue by never assuming the exception (1), it was intended as an optimization allowing ANativeWindow::lockBuffer() to return sooner and was justified when most of SF composition was done in software. The actual buffer locking is now ensured by gralloc. We could have handled screenshots in a similar way to a regular composition, but it could have caused glitches on screen, essentially, taking a screenshot could cause to skip a frame. Change-Id: I1f226b1ebdf6918439b687c2723955d55b842c55 --- libs/surfaceflinger_client/SharedBufferStack.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp index 3b2ef848b..af11f97a0 100644 --- a/libs/surfaceflinger_client/SharedBufferStack.cpp +++ b/libs/surfaceflinger_client/SharedBufferStack.cpp @@ -261,8 +261,7 @@ bool SharedBufferClient::LockCondition::operator()() const { // NOTE: if stack.head is messed up, we could crash the client // or cause some drawing artifacts. This is okay, as long as it is // limited to the client. - return (buf != stack.index[stack.head] || - (stack.queued > 0 && stack.inUse != buf)); + return (buf != stack.index[stack.head]); } SharedBufferServer::BuffersAvailableCondition::BuffersAvailableCondition( From c21766342e879db651b124eef1e50ed2ea72d285 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 9 Feb 2011 18:38:55 -0800 Subject: [PATCH 4/4] fix [3408713] Dialog window invisible sometimes weak pointer comparison operators were implemented wrong, they were using the internal "unsafe" pointer. We could end up with two "equal" weak pointer pointing to different objects. this caused KeyedVector keyed by weak pointer to work incorrectly, in turn causing a window that just got added to a list to be immediately removed. Change-Id: Ib191010c39aafa9229109e4211f6c3b2b2f9696d --- include/utils/RefBase.h | 62 +++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/include/utils/RefBase.h b/include/utils/RefBase.h index 9c64ac044..c24c0dbcb 100644 --- a/include/utils/RefBase.h +++ b/include/utils/RefBase.h @@ -31,13 +31,10 @@ template class wp; // --------------------------------------------------------------------------- -#define COMPARE(_op_) \ +#define COMPARE_WEAK(_op_) \ inline bool operator _op_ (const sp& o) const { \ return m_ptr _op_ o.m_ptr; \ } \ -inline bool operator _op_ (const wp& o) const { \ - return m_ptr _op_ o.m_ptr; \ -} \ inline bool operator _op_ (const T* o) const { \ return m_ptr _op_ o; \ } \ @@ -46,12 +43,18 @@ inline bool operator _op_ (const sp& o) const { \ return m_ptr _op_ o.m_ptr; \ } \ template \ -inline bool operator _op_ (const wp& o) const { \ +inline bool operator _op_ (const U* o) const { \ + return m_ptr _op_ o; \ +} + +#define COMPARE(_op_) \ +COMPARE_WEAK(_op_) \ +inline bool operator _op_ (const wp& o) const { \ return m_ptr _op_ o.m_ptr; \ } \ template \ -inline bool operator _op_ (const U* o) const { \ - return m_ptr _op_ o; \ +inline bool operator _op_ (const wp& o) const { \ + return m_ptr _op_ o.m_ptr; \ } // --------------------------------------------------------------------------- @@ -274,13 +277,43 @@ public: inline T* unsafe_get() const { return m_ptr; } // Operators - - COMPARE(==) - COMPARE(!=) - COMPARE(>) - COMPARE(<) - COMPARE(<=) - COMPARE(>=) + + COMPARE_WEAK(==) + COMPARE_WEAK(!=) + COMPARE_WEAK(>) + COMPARE_WEAK(<) + COMPARE_WEAK(<=) + COMPARE_WEAK(>=) + + inline bool operator == (const wp& o) const { + return (m_ptr == o.m_ptr) && (m_refs == o.m_refs); + } + template + inline bool operator == (const wp& o) const { + return m_ptr == o.m_ptr; + } + + inline bool operator > (const wp& o) const { + return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr); + } + template + inline bool operator > (const wp& o) const { + return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr); + } + + inline bool operator < (const wp& o) const { + return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr); + } + template + inline bool operator < (const wp& o) const { + return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr); + } + inline bool operator != (const wp& o) const { return m_refs != o.m_refs; } + template inline bool operator != (const wp& o) const { return !operator == (o); } + inline bool operator <= (const wp& o) const { return !operator > (o); } + template inline bool operator <= (const wp& o) const { return !operator > (o); } + inline bool operator >= (const wp& o) const { return !operator < (o); } + template inline bool operator >= (const wp& o) const { return !operator < (o); } private: template friend class sp; @@ -294,6 +327,7 @@ template TextOutput& operator<<(TextOutput& to, const wp& val); #undef COMPARE +#undef COMPARE_WEAK // --------------------------------------------------------------------------- // No user serviceable parts below here.