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

Commit 9f410f0a authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

SF: Avoid allocation on hot path to IF

The number of layer stacks and listeners is small, and the predominant
operations are lookup and iteration respectively, so store them on the
stack contiguously to avoid hashing/allocation/indirection.

Preallocate the WindowInfo and DisplayInfo vectors, since reallocating
the former involves copying strings and fiddling with sp<> ref counts.

Bug: 185536303
Test: simpleperf
Test: WindowInfosListenerTest
Change-Id: I5d1d1fc3b2639a4ee5056697e1a3581c11174173
parent 99a9750a
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -141,7 +141,7 @@ uint32_t DisplayDevice::getPageFlipCount() const {
    return mCompositionDisplay->getRenderSurface()->getPageFlipCount();
}

std::pair<gui::DisplayInfo, ui::Transform> DisplayDevice::getInputInfo() const {
auto DisplayDevice::getInputInfo() const -> InputInfo {
    gui::DisplayInfo info;
    info.displayId = getLayerStack().id;

@@ -166,10 +166,13 @@ std::pair<gui::DisplayInfo, ui::Transform> DisplayDevice::getInputInfo() const {

    info.logicalWidth = getLayerStackSpaceRect().width();
    info.logicalHeight = getLayerStackSpaceRect().height();
    return {info, displayTransform};

    return {.info = info,
            .transform = displayTransform,
            .receivesInput = receivesInput(),
            .isSecure = isSecure()};
}

// ----------------------------------------------------------------------------
void DisplayDevice::setPowerMode(hal::PowerMode mode) {
    mPowerMode = mode;
    getCompositionDisplay()->setCompositionEnabled(mPowerMode != hal::PowerMode::OFF);
+8 −3
Original line number Diff line number Diff line
@@ -174,9 +174,14 @@ public:
        return mDeviceProductInfo;
    }

    // Get the DisplayInfo that will be sent to InputFlinger, and the display transform that should
    // be applied to all the input windows on the display.
    std::pair<gui::DisplayInfo, ui::Transform> getInputInfo() const;
    struct InputInfo {
        gui::DisplayInfo info;
        ui::Transform transform;
        bool receivesInput;
        bool isSecure;
    };

    InputInfo getInputInfo() const;

    /* ------------------------------------------------------------------------
     * Display power mode management.
+27 −38
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@
#include <cutils/compiler.h>
#include <cutils/properties.h>
#include <ftl/future.h>
#include <ftl/small_map.h>
#include <gui/BufferQueue.h>
#include <gui/DebugEGLImageTracker.h>
#include <gui/IProducerListener.h>
@@ -3258,60 +3259,48 @@ void SurfaceFlinger::persistDisplayBrightness(bool needsComposite) {

void SurfaceFlinger::buildWindowInfos(std::vector<WindowInfo>& outWindowInfos,
                                      std::vector<DisplayInfo>& outDisplayInfos) {
    struct Details {
        Details(bool receivesInput, bool isSecure, const ui::Transform& transform,
                const DisplayInfo& info)
              : receivesInput(receivesInput),
                isSecure(isSecure),
                transform(std::move(transform)),
                info(std::move(info)) {}
        bool receivesInput;
        bool isSecure;
        ui::Transform transform;
        DisplayInfo info;
    };
    std::unordered_map<uint32_t /*layerStackId*/, Details> inputDisplayDetails;
    ftl::SmallMap<ui::LayerStack, DisplayDevice::InputInfo, 4> displayInputInfos;

    for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
        const uint32_t layerStackId = display->getLayerStack().id;
        const auto& [info, transform] = display->getInputInfo();
        const auto& [it, emplaced] =
                inputDisplayDetails.try_emplace(layerStackId, display->receivesInput(),
                                                display->isSecure(), transform, info);
        const auto layerStack = display->getLayerStack();
        const auto info = display->getInputInfo();

        const auto [it, emplaced] = displayInputInfos.try_emplace(layerStack, info);
        if (emplaced) {
            continue;
        }

        // There is more than one display for the layerStack. In this case, the first display that
        // is configured to receive input takes precedence.
        auto& details = it->second;
        if (details.receivesInput) {
        // If the layer stack is mirrored on multiple displays, the first display that is configured
        // to receive input takes precedence.
        auto& otherInfo = it->second;
        if (otherInfo.receivesInput) {
            ALOGW_IF(display->receivesInput(),
                     "Multiple displays claim to accept input for the same layer stack: %u",
                     layerStackId);
            continue;
                     layerStack.id);
        } else {
            otherInfo = info;
        }
        details.receivesInput = display->receivesInput();
        details.isSecure = display->isSecure();
        details.transform = std::move(transform);
        details.info = std::move(info);
    }

    static size_t sNumWindowInfos = 0;
    outWindowInfos.reserve(sNumWindowInfos);
    sNumWindowInfos = 0;

    mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
        if (!layer->needsInputInfo()) return;

        const uint32_t layerStackId = layer->getLayerStack().id;
        const auto it = inputDisplayDetails.find(layerStackId);
        if (it == inputDisplayDetails.end()) {
        // Do not create WindowInfos for windows on displays that cannot receive input.
            return;
        if (const auto opt = displayInputInfos.get(layer->getLayerStack())) {
            const auto& info = opt->get();
            outWindowInfos.push_back(layer->fillInputInfo(info.transform, info.isSecure));
        }

        const auto& details = it->second;
        outWindowInfos.push_back(layer->fillInputInfo(details.transform, details.isSecure));
    });

    for (const auto& [_, details] : inputDisplayDetails) {
        outDisplayInfos.push_back(std::move(details.info));
    sNumWindowInfos = outWindowInfos.size();

    outDisplayInfos.reserve(displayInputInfos.size());
    for (const auto& [_, info] : displayInputInfos) {
        outDisplayInfos.push_back(info.info);
    }
}

+11 −12
Original line number Diff line number Diff line
@@ -14,10 +14,11 @@
 * limitations under the License.
 */

#include "WindowInfosListenerInvoker.h"
#include <ftl/small_vector.h>
#include <gui/ISurfaceComposer.h>
#include <unordered_set>

#include "SurfaceFlinger.h"
#include "WindowInfosListenerInvoker.h"

namespace android {

@@ -41,18 +42,17 @@ WindowInfosListenerInvoker::WindowInfosListenerInvoker(SurfaceFlinger& flinger)
      : mFlinger(flinger),
        mWindowInfosReportedListener(sp<WindowInfosReportedListener>::make(*this)) {}

void WindowInfosListenerInvoker::addWindowInfosListener(
        const sp<IWindowInfosListener>& windowInfosListener) {
    sp<IBinder> asBinder = IInterface::asBinder(windowInfosListener);

void WindowInfosListenerInvoker::addWindowInfosListener(sp<IWindowInfosListener> listener) {
    sp<IBinder> asBinder = IInterface::asBinder(listener);
    asBinder->linkToDeath(this);

    std::scoped_lock lock(mListenersMutex);
    mWindowInfosListeners.emplace(asBinder, windowInfosListener);
    mWindowInfosListeners.try_emplace(asBinder, std::move(listener));
}

void WindowInfosListenerInvoker::removeWindowInfosListener(
        const sp<IWindowInfosListener>& windowInfosListener) {
    sp<IBinder> asBinder = IInterface::asBinder(windowInfosListener);
        const sp<IWindowInfosListener>& listener) {
    sp<IBinder> asBinder = IInterface::asBinder(listener);

    std::scoped_lock lock(mListenersMutex);
    asBinder->unlinkToDeath(this);
@@ -67,12 +67,11 @@ void WindowInfosListenerInvoker::binderDied(const wp<IBinder>& who) {
void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo>& windowInfos,
                                                    const std::vector<DisplayInfo>& displayInfos,
                                                    bool shouldSync) {
    std::unordered_set<sp<IWindowInfosListener>, SpHash<IWindowInfosListener>> windowInfosListeners;

    ftl::SmallVector<const sp<IWindowInfosListener>, kStaticCapacity> windowInfosListeners;
    {
        std::scoped_lock lock(mListenersMutex);
        for (const auto& [_, listener] : mWindowInfosListeners) {
            windowInfosListeners.insert(listener);
            windowInfosListeners.push_back(listener);
        }
    }

+6 −5
Original line number Diff line number Diff line
@@ -20,10 +20,8 @@
#include <android/gui/IWindowInfosListener.h>
#include <android/gui/IWindowInfosReportedListener.h>
#include <binder/IBinder.h>
#include <ftl/small_map.h>
#include <utils/Mutex.h>
#include <unordered_map>

#include "WpHash.h"

namespace android {

@@ -33,7 +31,7 @@ class WindowInfosListenerInvoker : public IBinder::DeathRecipient {
public:
    explicit WindowInfosListenerInvoker(SurfaceFlinger&);

    void addWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener);
    void addWindowInfosListener(sp<gui::IWindowInfosListener>);
    void removeWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener);

    void windowInfosChanged(const std::vector<gui::WindowInfo>&,
@@ -48,8 +46,11 @@ private:

    SurfaceFlinger& mFlinger;
    std::mutex mListenersMutex;
    std::unordered_map<wp<IBinder>, const sp<gui::IWindowInfosListener>, WpHash>

    static constexpr size_t kStaticCapacity = 3;
    ftl::SmallMap<wp<IBinder>, const sp<gui::IWindowInfosListener>, kStaticCapacity>
            mWindowInfosListeners GUARDED_BY(mListenersMutex);

    sp<gui::IWindowInfosReportedListener> mWindowInfosReportedListener;
    std::atomic<size_t> mCallbacksPending{0};
};