diff options
author | 2015-01-12 09:51:53 +0900 | |
---|---|---|
committer | 2015-01-12 13:10:52 +0900 | |
commit | c3c58e015fa30a0ad87d4af2b95b7071baa8ffe4 (patch) | |
tree | 9d76978e72832d6f33357c39445aecf804ee4b21 | |
parent | 7f94b52fc7c66bc40702b46f59b3929c076cbbfb (diff) |
Fix ANR caused by hwuiTask thread
If hwuiTask thread is exited while HWUI renders something,
some tasks can remain unfinished forever.
This can make ANR problem if RenderThread waits this kind of tasks.
According to the current implementation, hwuiTask threads are
exited when HWUI receives trimMemory() callback with level >= 20
and some applications such as SystemUI can receive trimMemory()
with level >= 20 even though they renders something yet.
(For instance, when RecentsActivity in SystemUI is finished,
HWUI receives trimMemory() callback with level >= 20
but SystemUI should still render the status bar and navigation bar.)
This patch prevents the tasks from remaining unfinished and
make the tasks executed immediately if they cannot be added
to their TaskProcessors.
Change-Id: I5bd26439aa5f183b1a7c1ce466362e27554b4d16
-rw-r--r-- | libs/hwui/PathCache.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/TessellationCache.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/thread/TaskManager.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/thread/TaskProcessor.h | 8 |
4 files changed, 13 insertions, 13 deletions
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index a3d70197cb0f..302d1a920750 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -493,7 +493,9 @@ void PathCache::precache(const SkPath* path, const SkPaint* paint) { if (mProcessor == NULL) { mProcessor = new PathProcessor(Caches::getInstance()); } - mProcessor->add(task); + if (!mProcessor->add(task)) { + mProcessor->process(task); + } } } diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp index 1e38f9e9e615..bc956be8a059 100644 --- a/libs/hwui/TessellationCache.cpp +++ b/libs/hwui/TessellationCache.cpp @@ -385,7 +385,9 @@ void TessellationCache::precacheShadows(const Matrix4* drawTransform, const Rect if (mShadowProcessor == NULL) { mShadowProcessor = new ShadowProcessor(Caches::getInstance()); } - mShadowProcessor->add(task); + if (!mShadowProcessor->add(task)) { + mShadowProcessor->process(task); + } task->incStrong(NULL); // not using sp<>s, so manually ref while in the cache mShadowCache.put(key, task.get()); @@ -421,7 +423,9 @@ TessellationCache::Buffer* TessellationCache::getOrCreateBuffer( if (mProcessor == NULL) { mProcessor = new TessellationProcessor(Caches::getInstance()); } - mProcessor->add(task); + if (!mProcessor->add(task)) { + mProcessor->process(task); + } mCache.put(entry, buffer); } return buffer; diff --git a/libs/hwui/thread/TaskManager.cpp b/libs/hwui/thread/TaskManager.cpp index cb5401cb86e8..d600797d893f 100644 --- a/libs/hwui/thread/TaskManager.cpp +++ b/libs/hwui/thread/TaskManager.cpp @@ -109,6 +109,8 @@ bool TaskManager::WorkerThread::threadLoop() { bool TaskManager::WorkerThread::addTask(TaskWrapper task) { if (!isRunning()) { run(mName.string(), PRIORITY_DEFAULT); + } else if (exitPending()) { + return false; } Mutex::Autolock l(mLock); @@ -124,10 +126,6 @@ size_t TaskManager::WorkerThread::getTaskCount() const { } void TaskManager::WorkerThread::exit() { - { - Mutex::Autolock l(mLock); - mTasks.clear(); - } requestExit(); mSignal.signal(); } diff --git a/libs/hwui/thread/TaskProcessor.h b/libs/hwui/thread/TaskProcessor.h index d1269f0bd55a..30b37192d9b0 100644 --- a/libs/hwui/thread/TaskProcessor.h +++ b/libs/hwui/thread/TaskProcessor.h @@ -30,9 +30,6 @@ public: TaskProcessorBase() { } virtual ~TaskProcessorBase() { }; -private: - friend class TaskManager; - virtual void process(const sp<TaskBase>& task) = 0; }; @@ -44,9 +41,6 @@ public: bool add(const sp<Task<T> >& task); - virtual void onProcess(const sp<Task<T> >& task) = 0; - -private: virtual void process(const sp<TaskBase>& task) { sp<Task<T> > realTask = static_cast<Task<T>* >(task.get()); // This is the right way to do it but sp<> doesn't play nice @@ -54,6 +48,8 @@ private: onProcess(realTask); } + virtual void onProcess(const sp<Task<T> >& task) = 0; + TaskManager* mManager; }; |