diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2023-03-23 16:16:23 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2023-03-23 16:16:23 +0000 |
commit | b218143d95d241509954a82050c747ee18bdffc8 (patch) | |
tree | 434ceba1364b84df7955afc1382675a767b94096 | |
parent | 18fa257ea2337b3f8dddc9ee68ac64a28853b6a6 (diff) | |
parent | f3213d2ca821472b12ce2452e4bd33b4cd152e8f (diff) | |
download | native-b218143d95d241509954a82050c747ee18bdffc8.tar.gz |
Merge "SF: throttle WindowInfosListener calls" into tm-qpr-dev
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 7 | ||||
-rw-r--r-- | services/surfaceflinger/WindowInfosListenerInvoker.cpp | 93 | ||||
-rw-r--r-- | services/surfaceflinger/WindowInfosListenerInvoker.h | 12 |
3 files changed, 85 insertions, 27 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 494aa2c2cf..5db79999c8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3257,8 +3257,11 @@ void SurfaceFlinger::updateInputFlinger() { inputFlinger = mInputFlinger, this]() { ATRACE_NAME("BackgroundExecutor::updateInputFlinger"); if (updateWindowInfo) { - mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos, - inputWindowCommands.syncInputWindows); + mWindowInfosListenerInvoker + ->windowInfosChanged(std::move(windowInfos), std::move(displayInfos), + /* shouldSync= */ inputWindowCommands.syncInputWindows, + /* forceImmediateCall= */ + !inputWindowCommands.focusRequests.empty()); } else if (inputWindowCommands.syncInputWindows) { // If the caller requested to sync input windows, but there are no // changes to input windows, notify immediately. diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp index 30b9d8f1cb..023402f747 100644 --- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp +++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp @@ -28,19 +28,26 @@ using gui::WindowInfo; struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowInfosReportedListener { - explicit WindowInfosReportedListener(WindowInfosListenerInvoker& invoker) : mInvoker(invoker) {} + explicit WindowInfosReportedListener(WindowInfosListenerInvoker& invoker, size_t callbackCount, + bool shouldSync) + : mInvoker(invoker), mCallbacksPending(callbackCount), mShouldSync(shouldSync) {} binder::Status onWindowInfosReported() override { - mInvoker.windowInfosReported(); + mCallbacksPending--; + if (mCallbacksPending == 0) { + mInvoker.windowInfosReported(mShouldSync); + } return binder::Status::ok(); } +private: WindowInfosListenerInvoker& mInvoker; + std::atomic<size_t> mCallbacksPending; + bool mShouldSync; }; WindowInfosListenerInvoker::WindowInfosListenerInvoker(SurfaceFlinger& flinger) - : mFlinger(flinger), - mWindowInfosReportedListener(sp<WindowInfosReportedListener>::make(*this)) {} + : mFlinger(flinger) {} void WindowInfosListenerInvoker::addWindowInfosListener(sp<IWindowInfosListener> listener) { sp<IBinder> asBinder = IInterface::asBinder(listener); @@ -64,30 +71,76 @@ void WindowInfosListenerInvoker::binderDied(const wp<IBinder>& who) { mWindowInfosListeners.erase(who); } -void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo>& windowInfos, - const std::vector<DisplayInfo>& displayInfos, - bool shouldSync) { - ftl::SmallVector<const sp<IWindowInfosListener>, kStaticCapacity> windowInfosListeners; - { - std::scoped_lock lock(mListenersMutex); - for (const auto& [_, listener] : mWindowInfosListeners) { - windowInfosListeners.push_back(listener); +void WindowInfosListenerInvoker::windowInfosChanged(std::vector<WindowInfo> windowInfos, + std::vector<DisplayInfo> displayInfos, + bool shouldSync, bool forceImmediateCall) { + auto callListeners = [this, windowInfos = std::move(windowInfos), + displayInfos = std::move(displayInfos)](bool shouldSync) mutable { + ftl::SmallVector<const sp<IWindowInfosListener>, kStaticCapacity> windowInfosListeners; + { + std::scoped_lock lock(mListenersMutex); + for (const auto& [_, listener] : mWindowInfosListeners) { + windowInfosListeners.push_back(listener); + } } - } - mCallbacksPending = windowInfosListeners.size(); + auto reportedListener = + sp<WindowInfosReportedListener>::make(*this, windowInfosListeners.size(), + shouldSync); + + for (const auto& listener : windowInfosListeners) { + auto status = + listener->onWindowInfosChanged(windowInfos, displayInfos, reportedListener); + if (!status.isOk()) { + reportedListener->onWindowInfosReported(); + } + } + }; + + { + std::scoped_lock lock(mMessagesMutex); + // If there are unacked messages and this isn't a forced call, then return immediately. + // If a forced window infos change doesn't happen first, the update will be sent after + // the WindowInfosReportedListeners are called. If a forced window infos change happens or + // if there are subsequent delayed messages before this update is sent, then this message + // will be dropped and the listeners will only be called with the latest info. This is done + // to reduce the amount of binder memory used. + if (mActiveMessageCount > 0 && !forceImmediateCall) { + mWindowInfosChangedDelayed = std::move(callListeners); + mShouldSyncDelayed |= shouldSync; + return; + } - for (const auto& listener : windowInfosListeners) { - listener->onWindowInfosChanged(windowInfos, displayInfos, - shouldSync ? mWindowInfosReportedListener : nullptr); + mWindowInfosChangedDelayed = nullptr; + shouldSync |= mShouldSyncDelayed; + mShouldSyncDelayed = false; + mActiveMessageCount++; } + callListeners(shouldSync); } -void WindowInfosListenerInvoker::windowInfosReported() { - mCallbacksPending--; - if (mCallbacksPending == 0) { +void WindowInfosListenerInvoker::windowInfosReported(bool shouldSync) { + if (shouldSync) { mFlinger.windowInfosReported(); } + + std::function<void(bool)> callListeners; + bool shouldSyncDelayed; + { + std::scoped_lock lock{mMessagesMutex}; + mActiveMessageCount--; + if (!mWindowInfosChangedDelayed || mActiveMessageCount > 0) { + return; + } + + mActiveMessageCount++; + callListeners = std::move(mWindowInfosChangedDelayed); + mWindowInfosChangedDelayed = nullptr; + shouldSyncDelayed = mShouldSyncDelayed; + mShouldSyncDelayed = false; + } + + callListeners(shouldSyncDelayed); } } // namespace android diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.h b/services/surfaceflinger/WindowInfosListenerInvoker.h index d8d8d0f570..701f11efcd 100644 --- a/services/surfaceflinger/WindowInfosListenerInvoker.h +++ b/services/surfaceflinger/WindowInfosListenerInvoker.h @@ -34,15 +34,15 @@ public: void addWindowInfosListener(sp<gui::IWindowInfosListener>); void removeWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener); - void windowInfosChanged(const std::vector<gui::WindowInfo>&, - const std::vector<gui::DisplayInfo>&, bool shouldSync); + void windowInfosChanged(std::vector<gui::WindowInfo>, std::vector<gui::DisplayInfo>, + bool shouldSync, bool forceImmediateCall); protected: void binderDied(const wp<IBinder>& who) override; private: struct WindowInfosReportedListener; - void windowInfosReported(); + void windowInfosReported(bool shouldSync); SurfaceFlinger& mFlinger; std::mutex mListenersMutex; @@ -51,8 +51,10 @@ private: ftl::SmallMap<wp<IBinder>, const sp<gui::IWindowInfosListener>, kStaticCapacity> mWindowInfosListeners GUARDED_BY(mListenersMutex); - sp<gui::IWindowInfosReportedListener> mWindowInfosReportedListener; - std::atomic<size_t> mCallbacksPending{0}; + std::mutex mMessagesMutex; + uint32_t mActiveMessageCount GUARDED_BY(mMessagesMutex) = 0; + std::function<void(bool)> mWindowInfosChangedDelayed GUARDED_BY(mMessagesMutex); + bool mShouldSyncDelayed; }; } // namespace android |