Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ed33cbb authored by Vishnu Nair's avatar Vishnu Nair Committed by Android (Google) Code Review
Browse files

Merge "SF: Introduce background task executor"

parents 36666dd2 34eb9ca5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -144,6 +144,7 @@ cc_library_headers {
filegroup {
    name: "libsurfaceflinger_sources",
    srcs: [
        "BackgroundExecutor.cpp",
        "BufferLayer.cpp",
        "BufferLayerConsumer.cpp",
        "BufferQueueLayer.cpp",
+65 −0
Original line number Diff line number Diff line
/*
 * 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
+42 −0
Original line number Diff line number Diff line
/*
 * 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
+5 −34
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS

#include "TransactionCallbackInvoker.h"
#include "BackgroundExecutor.h"

#include <cinttypes>

@@ -49,31 +50,6 @@ static bool containsOnCommitCallbacks(const std::vector<CallbackId>& callbacks)
    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 @@ void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) {
                // 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)]() {
                BackgroundExecutor::getInstance().execute([stats = std::move(listenerStats)]() {
                    interface_cast<ITransactionCompletedListener>(stats.listener)
                            ->onTransactionCompleted(stats);
                });
                    mCallbackConditionVariable.notify_all();
                }
            }
        }
        completedTransactionsItr++;
+0 −9
Original line number Diff line number Diff line
@@ -61,9 +61,6 @@ public:

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 @@ private:
        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