summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2023-03-23 16:16:23 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2023-03-23 16:16:23 +0000
commitb218143d95d241509954a82050c747ee18bdffc8 (patch)
tree434ceba1364b84df7955afc1382675a767b94096
parent18fa257ea2337b3f8dddc9ee68ac64a28853b6a6 (diff)
parentf3213d2ca821472b12ce2452e4bd33b4cd152e8f (diff)
downloadnative-b218143d95d241509954a82050c747ee18bdffc8.tar.gz
Merge "SF: throttle WindowInfosListener calls" into tm-qpr-dev
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp7
-rw-r--r--services/surfaceflinger/WindowInfosListenerInvoker.cpp93
-rw-r--r--services/surfaceflinger/WindowInfosListenerInvoker.h12
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