From 9f410f0adfb4f44fa149cbc7589b13ea88007157 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Sat, 8 Jan 2022 16:22:46 -0800 Subject: 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 --- services/surfaceflinger/DisplayDevice.cpp | 9 ++- services/surfaceflinger/DisplayDevice.h | 11 +++- services/surfaceflinger/SurfaceFlinger.cpp | 65 +++++++++------------- .../surfaceflinger/WindowInfosListenerInvoker.cpp | 23 ++++---- .../surfaceflinger/WindowInfosListenerInvoker.h | 11 ++-- 5 files changed, 58 insertions(+), 61 deletions(-) diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index f542161b93..eef00522dc 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -141,7 +141,7 @@ uint32_t DisplayDevice::getPageFlipCount() const { return mCompositionDisplay->getRenderSurface()->getPageFlipCount(); } -std::pair DisplayDevice::getInputInfo() const { +auto DisplayDevice::getInputInfo() const -> InputInfo { gui::DisplayInfo info; info.displayId = getLayerStack().id; @@ -166,10 +166,13 @@ std::pair 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); diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 3cae30fe92..bf6b31a76b 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -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 getInputInfo() const; + struct InputInfo { + gui::DisplayInfo info; + ui::Transform transform; + bool receivesInput; + bool isSecure; + }; + + InputInfo getInputInfo() const; /* ------------------------------------------------------------------------ * Display power mode management. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9716d8ecea..344c2cc7d4 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -3258,60 +3259,48 @@ void SurfaceFlinger::persistDisplayBrightness(bool needsComposite) { void SurfaceFlinger::buildWindowInfos(std::vector& outWindowInfos, std::vector& 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 inputDisplayDetails; + ftl::SmallMap 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; + // Do not create WindowInfos for windows on displays that cannot receive input. + 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); } } diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp index 23cd99336a..30b9d8f1cb 100644 --- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp +++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp @@ -14,10 +14,11 @@ * limitations under the License. */ -#include "WindowInfosListenerInvoker.h" +#include #include -#include + #include "SurfaceFlinger.h" +#include "WindowInfosListenerInvoker.h" namespace android { @@ -41,18 +42,17 @@ WindowInfosListenerInvoker::WindowInfosListenerInvoker(SurfaceFlinger& flinger) : mFlinger(flinger), mWindowInfosReportedListener(sp::make(*this)) {} -void WindowInfosListenerInvoker::addWindowInfosListener( - const sp& windowInfosListener) { - sp asBinder = IInterface::asBinder(windowInfosListener); - +void WindowInfosListenerInvoker::addWindowInfosListener(sp listener) { + sp 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& windowInfosListener) { - sp asBinder = IInterface::asBinder(windowInfosListener); + const sp& listener) { + sp asBinder = IInterface::asBinder(listener); std::scoped_lock lock(mListenersMutex); asBinder->unlinkToDeath(this); @@ -67,12 +67,11 @@ void WindowInfosListenerInvoker::binderDied(const wp& who) { void WindowInfosListenerInvoker::windowInfosChanged(const std::vector& windowInfos, const std::vector& displayInfos, bool shouldSync) { - std::unordered_set, SpHash> windowInfosListeners; - + ftl::SmallVector, kStaticCapacity> windowInfosListeners; { std::scoped_lock lock(mListenersMutex); for (const auto& [_, listener] : mWindowInfosListeners) { - windowInfosListeners.insert(listener); + windowInfosListeners.push_back(listener); } } diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.h b/services/surfaceflinger/WindowInfosListenerInvoker.h index 2eabf481c8..d8d8d0f570 100644 --- a/services/surfaceflinger/WindowInfosListenerInvoker.h +++ b/services/surfaceflinger/WindowInfosListenerInvoker.h @@ -20,10 +20,8 @@ #include #include #include +#include #include -#include - -#include "WpHash.h" namespace android { @@ -33,7 +31,7 @@ class WindowInfosListenerInvoker : public IBinder::DeathRecipient { public: explicit WindowInfosListenerInvoker(SurfaceFlinger&); - void addWindowInfosListener(const sp& windowInfosListener); + void addWindowInfosListener(sp); void removeWindowInfosListener(const sp& windowInfosListener); void windowInfosChanged(const std::vector&, @@ -48,8 +46,11 @@ private: SurfaceFlinger& mFlinger; std::mutex mListenersMutex; - std::unordered_map, const sp, WpHash> + + static constexpr size_t kStaticCapacity = 3; + ftl::SmallMap, const sp, kStaticCapacity> mWindowInfosListeners GUARDED_BY(mListenersMutex); + sp mWindowInfosReportedListener; std::atomic mCallbacksPending{0}; }; -- cgit v1.2.3-59-g8ed1b