Merge "SF: Introduce background task executor"
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index c9fb7bc..c453d62 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -144,6 +144,7 @@
filegroup {
name: "libsurfaceflinger_sources",
srcs: [
+ "BackgroundExecutor.cpp",
"BufferLayer.cpp",
"BufferLayerConsumer.cpp",
"BufferQueueLayer.cpp",
diff --git a/services/surfaceflinger/BackgroundExecutor.cpp b/services/surfaceflinger/BackgroundExecutor.cpp
new file mode 100644
index 0000000..3663cdb
--- /dev/null
+++ b/services/surfaceflinger/BackgroundExecutor.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2021 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_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "BackgroundExecutor"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "BackgroundExecutor.h"
+
+namespace android {
+
+ANDROID_SINGLETON_STATIC_INSTANCE(BackgroundExecutor);
+
+BackgroundExecutor::BackgroundExecutor() : Singleton<BackgroundExecutor>() {
+ mThread = std::thread([&]() {
+ bool done = false;
+ while (!done) {
+ std::vector<std::function<void()>> tasks;
+ {
+ std::unique_lock lock(mMutex);
+ mWorkAvailableCv.wait(lock, [&]() { return mDone || !mTasks.empty(); });
+ tasks = std::move(mTasks);
+ mTasks.clear();
+ done = mDone;
+ } // unlock mMutex
+
+ for (auto& task : tasks) {
+ task();
+ }
+ }
+ });
+}
+
+BackgroundExecutor::~BackgroundExecutor() {
+ {
+ std::unique_lock lock(mMutex);
+ mDone = true;
+ mWorkAvailableCv.notify_all();
+ }
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
+void BackgroundExecutor::execute(std::function<void()> task) {
+ std::unique_lock lock(mMutex);
+ mTasks.emplace_back(std::move(task));
+ mWorkAvailableCv.notify_all();
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/BackgroundExecutor.h b/services/surfaceflinger/BackgroundExecutor.h
new file mode 100644
index 0000000..6f6d305
--- /dev/null
+++ b/services/surfaceflinger/BackgroundExecutor.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#pragma once
+
+#include <utils/Singleton.h>
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+#include <thread>
+
+namespace android {
+
+// Executes tasks off the main thread.
+class BackgroundExecutor : public Singleton<BackgroundExecutor> {
+public:
+ BackgroundExecutor();
+ ~BackgroundExecutor();
+ void execute(std::function<void()>);
+
+private:
+ std::mutex mMutex;
+ std::condition_variable mWorkAvailableCv;
+ std::thread mThread;
+ bool mDone = false;
+ std::vector<std::function<void()>> mTasks;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp
index f3d46ea..b705d9c 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.cpp
+++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp
@@ -24,6 +24,7 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include "TransactionCallbackInvoker.h"
+#include "BackgroundExecutor.h"
#include <cinttypes>
@@ -49,31 +50,6 @@
return !callbacks.empty() && callbacks.front().type == CallbackId::Type::ON_COMMIT;
}
-TransactionCallbackInvoker::TransactionCallbackInvoker() {
- mThread = std::thread([&]() {
- std::unique_lock lock(mCallbackThreadMutex);
-
- while (mKeepRunning) {
- while (mCallbackThreadWork.size() > 0) {
- mCallbackThreadWork.front()();
- mCallbackThreadWork.pop();
- }
- mCallbackConditionVariable.wait(lock);
- }
- });
-}
-
-TransactionCallbackInvoker::~TransactionCallbackInvoker() {
- {
- std::unique_lock lock(mCallbackThreadMutex);
- mKeepRunning = false;
- mCallbackConditionVariable.notify_all();
- }
- if (mThread.joinable()) {
- mThread.join();
- }
-}
-
void TransactionCallbackInvoker::addEmptyTransaction(const ListenerCallbacks& listenerCallbacks) {
auto& [listener, callbackIds] = listenerCallbacks;
auto& transactionStatsDeque = mCompletedTransactions[listener];
@@ -242,15 +218,10 @@
// keep it as an IBinder due to consistency reasons: if we
// interface_cast at the IPC boundary when reading a Parcel,
// we get pointers that compare unequal in the SF process.
- {
- std::unique_lock lock(mCallbackThreadMutex);
- mCallbackThreadWork.push(
- [stats = std::move(listenerStats)]() {
- interface_cast<ITransactionCompletedListener>(stats.listener)
- ->onTransactionCompleted(stats);
- });
- mCallbackConditionVariable.notify_all();
- }
+ BackgroundExecutor::getInstance().execute([stats = std::move(listenerStats)]() {
+ interface_cast<ITransactionCompletedListener>(stats.listener)
+ ->onTransactionCompleted(stats);
+ });
}
}
completedTransactionsItr++;
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h
index e203d41..5ef5475 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.h
+++ b/services/surfaceflinger/TransactionCallbackInvoker.h
@@ -61,9 +61,6 @@
class TransactionCallbackInvoker {
public:
- TransactionCallbackInvoker();
- ~TransactionCallbackInvoker();
-
status_t addCallbackHandles(const std::deque<sp<CallbackHandle>>& handles,
const std::vector<JankData>& jankData);
status_t addOnCommitCallbackHandles(const std::deque<sp<CallbackHandle>>& handles,
@@ -94,12 +91,6 @@
mCompletedTransactions;
sp<Fence> mPresentFence;
-
- std::mutex mCallbackThreadMutex;
- std::condition_variable mCallbackConditionVariable;
- std::thread mThread;
- bool mKeepRunning = true;
- std::queue<std::function<void()>> mCallbackThreadWork;
};
} // namespace android