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

Commit 03ccbd6b authored by Vishnu Nair's avatar Vishnu Nair
Browse files

SF: Update InputFlinger outside main thread

Avoids parceling data inside  main thread and hot path. Also
avoids any binder contention with one way binder calls. See
bug for more details.

Re landing with the following changes:
Don't discard input commands if input dispatcher is not
available. This can happen if system server crashes and
recovers. We want to keep input commands until
input dispatcher becomes available.

Bug: 206380308
Test: presubmit
Test: systrace
Test: flickertests
Test: health/microbench/display/microbench-test-suite
Change-Id: If0344abdeb28c8a409eb2f641c1e78d53e6f59b2
parent 5bc9e109
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -550,9 +550,7 @@ bool InputWindowCommands::merge(const InputWindowCommands& other) {
}

bool InputWindowCommands::empty() const {
    bool empty = true;
    empty = focusRequests.empty() && !syncInputWindows;
    return empty;
    return focusRequests.empty() && !syncInputWindows;
}

void InputWindowCommands::clear() {
+5 −3
Original line number Diff line number Diff line
@@ -32,7 +32,9 @@ BackgroundExecutor::BackgroundExecutor() : Singleton<BackgroundExecutor>() {
            std::vector<std::function<void()>> tasks;
            {
                std::unique_lock lock(mMutex);
                mWorkAvailableCv.wait(lock, [&]() { return mDone || !mTasks.empty(); });
                android::base::ScopedLockAssertion assumeLock(mMutex);
                mWorkAvailableCv.wait(lock,
                                      [&]() REQUIRES(mMutex) { return mDone || !mTasks.empty(); });
                tasks = std::move(mTasks);
                mTasks.clear();
                done = mDone;
@@ -47,7 +49,7 @@ BackgroundExecutor::BackgroundExecutor() : Singleton<BackgroundExecutor>() {

BackgroundExecutor::~BackgroundExecutor() {
    {
        std::unique_lock lock(mMutex);
        std::scoped_lock lock(mMutex);
        mDone = true;
        mWorkAvailableCv.notify_all();
    }
@@ -57,7 +59,7 @@ BackgroundExecutor::~BackgroundExecutor() {
}

void BackgroundExecutor::execute(std::function<void()> task) {
    std::unique_lock lock(mMutex);
    std::scoped_lock lock(mMutex);
    mTasks.emplace_back(std::move(task));
    mWorkAvailableCv.notify_all();
}
+4 −3
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#pragma once

#include <android-base/thread_annotations.h>
#include <utils/Singleton.h>
#include <condition_variable>
#include <mutex>
@@ -33,10 +34,10 @@ public:

private:
    std::mutex mMutex;
    std::condition_variable mWorkAvailableCv;
    std::condition_variable mWorkAvailableCv GUARDED_BY(mMutex);
    bool mDone GUARDED_BY(mMutex) = false;
    std::vector<std::function<void()>> mTasks GUARDED_BY(mMutex);
    std::thread mThread;
    bool mDone = false;
    std::vector<std::function<void()>> mTasks;
};

} // namespace android
+32 −16
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@
#include <type_traits>
#include <unordered_map>

#include "BackgroundExecutor.h"
#include "BufferLayer.h"
#include "BufferQueueLayer.h"
#include "BufferStateLayer.h"
@@ -3054,28 +3055,45 @@ void SurfaceFlinger::updateInputFlinger() {
        return;
    }

    std::vector<WindowInfo> windowInfos;
    std::vector<DisplayInfo> displayInfos;
    bool updateWindowInfo = false;
    if (mVisibleRegionsDirty || mInputInfoChanged) {
        mInputInfoChanged = false;
        notifyWindowInfos();
    } else if (mInputWindowCommands.syncInputWindows) {
        updateWindowInfo = true;
        buildWindowInfos(windowInfos, displayInfos);
    }
    if (!updateWindowInfo && mInputWindowCommands.empty()) {
        return;
    }
    BackgroundExecutor::getInstance().execute([updateWindowInfo,
                                               windowInfos = std::move(windowInfos),
                                               displayInfos = std::move(displayInfos),
                                               inputWindowCommands =
                                                       std::move(mInputWindowCommands),
                                               inputFlinger = mInputFlinger, this]() {
        ATRACE_NAME("BackgroundExecutor::updateInputFlinger");
        if (updateWindowInfo) {
            mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos,
                                                            inputWindowCommands.syncInputWindows);
        } else if (inputWindowCommands.syncInputWindows) {
            // If the caller requested to sync input windows, but there are no
            // changes to input windows, notify immediately.
            windowInfosReported();
        }

    for (const auto& focusRequest : mInputWindowCommands.focusRequests) {
        mInputFlinger->setFocusedWindow(focusRequest);
        for (const auto& focusRequest : inputWindowCommands.focusRequests) {
            inputFlinger->setFocusedWindow(focusRequest);
        }
    });

    mInputWindowCommands.clear();
}

void SurfaceFlinger::notifyWindowInfos() {
    std::vector<WindowInfo> windowInfos;
    std::vector<DisplayInfo> displayInfos;
void SurfaceFlinger::buildWindowInfos(std::vector<WindowInfo>& outWindowInfos,
                                      std::vector<DisplayInfo>& outDisplayInfos) {
    std::unordered_map<uint32_t /*layerStackId*/,
                       std::pair<bool /* isSecure */, const ui::Transform>>
            inputDisplayDetails;

    for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
        if (!display->receivesInput()) {
            continue;
@@ -3089,7 +3107,7 @@ void SurfaceFlinger::notifyWindowInfos() {
                  layerStackId);
            continue;
        }
        displayInfos.emplace_back(info);
        outDisplayInfos.emplace_back(info);
    }

    mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
@@ -3109,10 +3127,8 @@ void SurfaceFlinger::notifyWindowInfos() {
                  layer->getDebugName(), layerStackId);
        }

        windowInfos.push_back(layer->fillInputInfo(displayTransform, isSecure));
        outWindowInfos.push_back(layer->fillInputInfo(displayTransform, isSecure));
    });
    mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos,
                                                    mInputWindowCommands.syncInputWindows);
}

void SurfaceFlinger::updateCursorAsync() {
+3 −2
Original line number Diff line number Diff line
@@ -690,7 +690,8 @@ private:
    void updateLayerGeometry();

    void updateInputFlinger();
    void notifyWindowInfos();
    void buildWindowInfos(std::vector<gui::WindowInfo>& outWindowInfos,
                          std::vector<gui::DisplayInfo>& outDisplayInfos);
    void commitInputWindowCommands() REQUIRES(mStateLock);
    void updateCursorAsync();

@@ -1294,8 +1295,8 @@ private:
    const float mInternalDisplayDensity;
    const float mEmulatedDisplayDensity;

    sp<os::IInputFlinger> mInputFlinger;
    // Should only be accessed by the main thread.
    sp<os::IInputFlinger> mInputFlinger;
    InputWindowCommands mInputWindowCommands;

    Hwc2::impl::PowerAdvisor mPowerAdvisor;