summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Chen <cken@google.com>2023-08-31 01:53:33 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2023-08-31 01:53:34 +0000
commita8ce8fc1d892ba7dcb27961b7bf49cc6433da7bb (patch)
tree780232b872244049ccaaf0463f990de8fe4b64a2
parent82f3463d449eb13e28c5dbffeee16e10721c71d2 (diff)
downloadnative-a8ce8fc1d892ba7dcb27961b7bf49cc6433da7bb.tar.gz
Revert "Improve updateInputFlinger performance"
This reverts commit 82f3463d449eb13e28c5dbffeee16e10721c71d2. Reason for revert: Broken Build 10741338 on git_udc-mainline-prod on mainline_modules_arm-userdebug Bug: 298282482 Change-Id: I9a8eaaff637017cd84caaa5c0d570e24f257ed81
-rw-r--r--libs/gui/Android.bp2
-rw-r--r--libs/gui/WindowInfosListenerReporter.cpp20
-rw-r--r--libs/gui/aidl/android/gui/ISurfaceComposer.aidl4
-rw-r--r--libs/gui/aidl/android/gui/WindowInfosListenerInfo.aidl25
-rw-r--r--libs/gui/android/gui/IWindowInfosListener.aidl4
-rw-r--r--libs/gui/android/gui/IWindowInfosPublisher.aidl23
-rw-r--r--libs/gui/fuzzer/libgui_fuzzer_utils.h4
-rw-r--r--libs/gui/include/gui/ISurfaceComposer.h1
-rw-r--r--libs/gui/include/gui/WindowInfosListenerReporter.h8
-rw-r--r--libs/gui/tests/Surface_test.cpp3
-rw-r--r--services/surfaceflinger/BackgroundExecutor.cpp14
-rw-r--r--services/surfaceflinger/BackgroundExecutor.h1
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp14
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h7
-rw-r--r--services/surfaceflinger/WindowInfosListenerInvoker.cpp253
-rw-r--r--services/surfaceflinger/WindowInfosListenerInvoker.h35
-rw-r--r--services/surfaceflinger/tests/unittests/WindowInfosListenerInvokerTest.cpp156
17 files changed, 242 insertions, 332 deletions
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 3c8df2bb29..bf34987b9e 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -73,7 +73,6 @@ filegroup {
"android/gui/FocusRequest.aidl",
"android/gui/InputApplicationInfo.aidl",
"android/gui/IWindowInfosListener.aidl",
- "android/gui/IWindowInfosPublisher.aidl",
"android/gui/IWindowInfosReportedListener.aidl",
"android/gui/WindowInfo.aidl",
"android/gui/WindowInfosUpdate.aidl",
@@ -91,7 +90,6 @@ cc_library_static {
"android/gui/FocusRequest.aidl",
"android/gui/InputApplicationInfo.aidl",
"android/gui/IWindowInfosListener.aidl",
- "android/gui/IWindowInfosPublisher.aidl",
"android/gui/IWindowInfosReportedListener.aidl",
"android/gui/WindowInfosUpdate.aidl",
"android/gui/WindowInfo.aidl",
diff --git a/libs/gui/WindowInfosListenerReporter.cpp b/libs/gui/WindowInfosListenerReporter.cpp
index 0929b8e120..76e7b6e162 100644
--- a/libs/gui/WindowInfosListenerReporter.cpp
+++ b/libs/gui/WindowInfosListenerReporter.cpp
@@ -22,6 +22,7 @@
namespace android {
using gui::DisplayInfo;
+using gui::IWindowInfosReportedListener;
using gui::WindowInfo;
using gui::WindowInfosListener;
using gui::aidl_utils::statusTFromBinderStatus;
@@ -39,13 +40,8 @@ status_t WindowInfosListenerReporter::addWindowInfosListener(
{
std::scoped_lock lock(mListenersMutex);
if (mWindowInfosListeners.empty()) {
- gui::WindowInfosListenerInfo listenerInfo;
- binder::Status s = surfaceComposer->addWindowInfosListener(this, &listenerInfo);
+ binder::Status s = surfaceComposer->addWindowInfosListener(this);
status = statusTFromBinderStatus(s);
- if (status == OK) {
- mWindowInfosPublisher = std::move(listenerInfo.windowInfosPublisher);
- mListenerId = listenerInfo.listenerId;
- }
}
if (status == OK) {
@@ -89,7 +85,8 @@ status_t WindowInfosListenerReporter::removeWindowInfosListener(
}
binder::Status WindowInfosListenerReporter::onWindowInfosChanged(
- const gui::WindowInfosUpdate& update) {
+ const gui::WindowInfosUpdate& update,
+ const sp<IWindowInfosReportedListener>& windowInfosReportedListener) {
std::unordered_set<sp<WindowInfosListener>, gui::SpHash<WindowInfosListener>>
windowInfosListeners;
@@ -107,7 +104,9 @@ binder::Status WindowInfosListenerReporter::onWindowInfosChanged(
listener->onWindowInfosChanged(update);
}
- mWindowInfosPublisher->ackWindowInfosReceived(update.vsyncId, mListenerId);
+ if (windowInfosReportedListener) {
+ windowInfosReportedListener->onWindowInfosReported();
+ }
return binder::Status::ok();
}
@@ -115,10 +114,7 @@ binder::Status WindowInfosListenerReporter::onWindowInfosChanged(
void WindowInfosListenerReporter::reconnect(const sp<gui::ISurfaceComposer>& composerService) {
std::scoped_lock lock(mListenersMutex);
if (!mWindowInfosListeners.empty()) {
- gui::WindowInfosListenerInfo listenerInfo;
- composerService->addWindowInfosListener(this, &listenerInfo);
- mWindowInfosPublisher = std::move(listenerInfo.windowInfosPublisher);
- mListenerId = listenerInfo.listenerId;
+ composerService->addWindowInfosListener(this);
}
}
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index 539a1c140e..ec3266ca83 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -40,14 +40,12 @@ import android.gui.IScreenCaptureListener;
import android.gui.ISurfaceComposerClient;
import android.gui.ITunnelModeEnabledListener;
import android.gui.IWindowInfosListener;
-import android.gui.IWindowInfosPublisher;
import android.gui.LayerCaptureArgs;
import android.gui.LayerDebugInfo;
import android.gui.OverlayProperties;
import android.gui.PullAtomData;
import android.gui.ARect;
import android.gui.StaticDisplayInfo;
-import android.gui.WindowInfosListenerInfo;
/** @hide */
interface ISurfaceComposer {
@@ -502,7 +500,7 @@ interface ISurfaceComposer {
*/
int getMaxAcquiredBufferCount();
- WindowInfosListenerInfo addWindowInfosListener(IWindowInfosListener windowInfosListener);
+ void addWindowInfosListener(IWindowInfosListener windowInfosListener);
void removeWindowInfosListener(IWindowInfosListener windowInfosListener);
diff --git a/libs/gui/aidl/android/gui/WindowInfosListenerInfo.aidl b/libs/gui/aidl/android/gui/WindowInfosListenerInfo.aidl
deleted file mode 100644
index 0ca13b768a..0000000000
--- a/libs/gui/aidl/android/gui/WindowInfosListenerInfo.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Copyright (c) 2023, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.gui;
-
-import android.gui.IWindowInfosPublisher;
-
-/** @hide */
-parcelable WindowInfosListenerInfo {
- long listenerId;
- IWindowInfosPublisher windowInfosPublisher;
-} \ No newline at end of file
diff --git a/libs/gui/android/gui/IWindowInfosListener.aidl b/libs/gui/android/gui/IWindowInfosListener.aidl
index 07cb5ed0e6..400229d99f 100644
--- a/libs/gui/android/gui/IWindowInfosListener.aidl
+++ b/libs/gui/android/gui/IWindowInfosListener.aidl
@@ -16,9 +16,11 @@
package android.gui;
+import android.gui.IWindowInfosReportedListener;
import android.gui.WindowInfosUpdate;
/** @hide */
oneway interface IWindowInfosListener {
- void onWindowInfosChanged(in WindowInfosUpdate update);
+ void onWindowInfosChanged(
+ in WindowInfosUpdate update, in @nullable IWindowInfosReportedListener windowInfosReportedListener);
}
diff --git a/libs/gui/android/gui/IWindowInfosPublisher.aidl b/libs/gui/android/gui/IWindowInfosPublisher.aidl
deleted file mode 100644
index 5a9c32845e..0000000000
--- a/libs/gui/android/gui/IWindowInfosPublisher.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright (c) 2023, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.gui;
-
-/** @hide */
-oneway interface IWindowInfosPublisher
-{
- void ackWindowInfosReceived(long vsyncId, long listenerId);
-}
diff --git a/libs/gui/fuzzer/libgui_fuzzer_utils.h b/libs/gui/fuzzer/libgui_fuzzer_utils.h
index 4c7d0562af..8c003d8ad4 100644
--- a/libs/gui/fuzzer/libgui_fuzzer_utils.h
+++ b/libs/gui/fuzzer/libgui_fuzzer_utils.h
@@ -153,8 +153,8 @@ public:
MOCK_METHOD(binder::Status, setOverrideFrameRate, (int32_t, float), (override));
MOCK_METHOD(binder::Status, getGpuContextPriority, (int32_t*), (override));
MOCK_METHOD(binder::Status, getMaxAcquiredBufferCount, (int32_t*), (override));
- MOCK_METHOD(binder::Status, addWindowInfosListener,
- (const sp<gui::IWindowInfosListener>&, gui::WindowInfosListenerInfo*), (override));
+ MOCK_METHOD(binder::Status, addWindowInfosListener, (const sp<gui::IWindowInfosListener>&),
+ (override));
MOCK_METHOD(binder::Status, removeWindowInfosListener, (const sp<gui::IWindowInfosListener>&),
(override));
MOCK_METHOD(binder::Status, getOverlaySupport, (gui::OverlayProperties*), (override));
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 3ff6735926..7c150d53d9 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -26,7 +26,6 @@
#include <android/gui/IScreenCaptureListener.h>
#include <android/gui/ITunnelModeEnabledListener.h>
#include <android/gui/IWindowInfosListener.h>
-#include <android/gui/IWindowInfosPublisher.h>
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <gui/ITransactionCompletedListener.h>
diff --git a/libs/gui/include/gui/WindowInfosListenerReporter.h b/libs/gui/include/gui/WindowInfosListenerReporter.h
index 684e21ad96..38cb108912 100644
--- a/libs/gui/include/gui/WindowInfosListenerReporter.h
+++ b/libs/gui/include/gui/WindowInfosListenerReporter.h
@@ -18,7 +18,7 @@
#include <android/gui/BnWindowInfosListener.h>
#include <android/gui/ISurfaceComposer.h>
-#include <android/gui/IWindowInfosPublisher.h>
+#include <android/gui/IWindowInfosReportedListener.h>
#include <binder/IBinder.h>
#include <gui/SpHash.h>
#include <gui/WindowInfosListener.h>
@@ -30,7 +30,8 @@ namespace android {
class WindowInfosListenerReporter : public gui::BnWindowInfosListener {
public:
static sp<WindowInfosListenerReporter> getInstance();
- binder::Status onWindowInfosChanged(const gui::WindowInfosUpdate& update) override;
+ binder::Status onWindowInfosChanged(const gui::WindowInfosUpdate& update,
+ const sp<gui::IWindowInfosReportedListener>&) override;
status_t addWindowInfosListener(
const sp<gui::WindowInfosListener>& windowInfosListener,
const sp<gui::ISurfaceComposer>&,
@@ -46,8 +47,5 @@ private:
std::vector<gui::WindowInfo> mLastWindowInfos GUARDED_BY(mListenersMutex);
std::vector<gui::DisplayInfo> mLastDisplayInfos GUARDED_BY(mListenersMutex);
-
- sp<gui::IWindowInfosPublisher> mWindowInfosPublisher;
- int64_t mListenerId;
};
} // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 8d7cf07b96..096a43cd95 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -998,8 +998,7 @@ public:
}
binder::Status addWindowInfosListener(
- const sp<gui::IWindowInfosListener>& /*windowInfosListener*/,
- gui::WindowInfosListenerInfo* /*outInfo*/) override {
+ const sp<gui::IWindowInfosListener>& /*windowInfosListener*/) override {
return binder::Status::ok();
}
diff --git a/services/surfaceflinger/BackgroundExecutor.cpp b/services/surfaceflinger/BackgroundExecutor.cpp
index 5a1ec6f501..6ddf790d47 100644
--- a/services/surfaceflinger/BackgroundExecutor.cpp
+++ b/services/surfaceflinger/BackgroundExecutor.cpp
@@ -20,7 +20,6 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <utils/Log.h>
-#include <mutex>
#include "BackgroundExecutor.h"
@@ -61,17 +60,4 @@ void BackgroundExecutor::sendCallbacks(Callbacks&& tasks) {
LOG_ALWAYS_FATAL_IF(sem_post(&mSemaphore), "sem_post failed");
}
-void BackgroundExecutor::flushQueue() {
- std::mutex mutex;
- std::condition_variable cv;
- bool flushComplete = false;
- sendCallbacks({[&]() {
- std::scoped_lock lock{mutex};
- flushComplete = true;
- cv.notify_one();
- }});
- std::unique_lock<std::mutex> lock{mutex};
- cv.wait(lock, [&]() { return flushComplete; });
-}
-
} // namespace android
diff --git a/services/surfaceflinger/BackgroundExecutor.h b/services/surfaceflinger/BackgroundExecutor.h
index 66b7d7a1fc..0fae5a5c93 100644
--- a/services/surfaceflinger/BackgroundExecutor.h
+++ b/services/surfaceflinger/BackgroundExecutor.h
@@ -34,7 +34,6 @@ public:
// Queues callbacks onto a work queue to be executed by a background thread.
// This is safe to call from multiple threads.
void sendCallbacks(Callbacks&& tasks);
- void flushQueue();
private:
sem_t mSemaphore;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index db205b8a95..fe2db940f7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -6158,7 +6158,8 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, const std::string& comp
windowInfosDebug.maxSendDelayVsyncId.value);
StringAppendF(&result, " max send delay (ns): %" PRId64 " ns\n",
windowInfosDebug.maxSendDelayDuration);
- StringAppendF(&result, " unsent messages: %zu\n", windowInfosDebug.pendingMessageCount);
+ StringAppendF(&result, " unsent messages: %" PRIu32 "\n",
+ windowInfosDebug.pendingMessageCount);
result.append("\n");
}
@@ -7991,9 +7992,9 @@ void SurfaceFlinger::onActiveDisplayChangedLocked(const DisplayDevice* inactiveD
forceApplyPolicy);
}
-status_t SurfaceFlinger::addWindowInfosListener(const sp<IWindowInfosListener>& windowInfosListener,
- gui::WindowInfosListenerInfo* outInfo) {
- mWindowInfosListenerInvoker->addWindowInfosListener(windowInfosListener, outInfo);
+status_t SurfaceFlinger::addWindowInfosListener(
+ const sp<IWindowInfosListener>& windowInfosListener) {
+ mWindowInfosListenerInvoker->addWindowInfosListener(windowInfosListener);
setTransactionFlags(eInputInfoUpdateNeeded);
return NO_ERROR;
}
@@ -9075,8 +9076,7 @@ binder::Status SurfaceComposerAIDL::getMaxAcquiredBufferCount(int32_t* buffers)
}
binder::Status SurfaceComposerAIDL::addWindowInfosListener(
- const sp<gui::IWindowInfosListener>& windowInfosListener,
- gui::WindowInfosListenerInfo* outInfo) {
+ const sp<gui::IWindowInfosListener>& windowInfosListener) {
status_t status;
const int pid = IPCThreadState::self()->getCallingPid();
const int uid = IPCThreadState::self()->getCallingUid();
@@ -9084,7 +9084,7 @@ binder::Status SurfaceComposerAIDL::addWindowInfosListener(
// WindowInfosListeners
if (uid == AID_SYSTEM || uid == AID_GRAPHICS ||
checkPermission(sAccessSurfaceFlinger, pid, uid)) {
- status = mFlinger->addWindowInfosListener(windowInfosListener, outInfo);
+ status = mFlinger->addWindowInfosListener(windowInfosListener);
} else {
status = PERMISSION_DENIED;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index d4700a4e25..0bc506f1fe 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -612,8 +612,7 @@ private:
status_t getMaxAcquiredBufferCount(int* buffers) const;
- status_t addWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener,
- gui::WindowInfosListenerInfo* outResult);
+ status_t addWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener);
status_t removeWindowInfosListener(
const sp<gui::IWindowInfosListener>& windowInfosListener) const;
@@ -1557,8 +1556,8 @@ public:
binder::Status setOverrideFrameRate(int32_t uid, float frameRate) override;
binder::Status getGpuContextPriority(int32_t* outPriority) override;
binder::Status getMaxAcquiredBufferCount(int32_t* buffers) override;
- binder::Status addWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener,
- gui::WindowInfosListenerInfo* outInfo) override;
+ binder::Status addWindowInfosListener(
+ const sp<gui::IWindowInfosListener>& windowInfosListener) override;
binder::Status removeWindowInfosListener(
const sp<gui::IWindowInfosListener>& windowInfosListener) override;
diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp
index 7062a4e3a7..20699ef123 100644
--- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp
+++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#include <android/gui/BnWindowInfosPublisher.h>
-#include <android/gui/IWindowInfosPublisher.h>
-#include <android/gui/WindowInfosListenerInfo.h>
+#include <ftl/small_vector.h>
#include <gui/ISurfaceComposer.h>
#include <gui/TraceUtils.h>
#include <gui/WindowInfosUpdate.h>
@@ -25,130 +23,162 @@
#include "BackgroundExecutor.h"
#include "WindowInfosListenerInvoker.h"
-#undef ATRACE_TAG
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
namespace android {
using gui::DisplayInfo;
using gui::IWindowInfosListener;
using gui::WindowInfo;
-void WindowInfosListenerInvoker::addWindowInfosListener(sp<IWindowInfosListener> listener,
- gui::WindowInfosListenerInfo* outInfo) {
- int64_t listenerId = mNextListenerId++;
- outInfo->listenerId = listenerId;
- outInfo->windowInfosPublisher = sp<gui::IWindowInfosPublisher>::fromExisting(this);
+using WindowInfosListenerVector = ftl::SmallVector<const sp<gui::IWindowInfosListener>, 3>;
+
+struct WindowInfosReportedListenerInvoker : gui::BnWindowInfosReportedListener,
+ IBinder::DeathRecipient {
+ WindowInfosReportedListenerInvoker(WindowInfosListenerVector windowInfosListeners,
+ WindowInfosReportedListenerSet windowInfosReportedListeners)
+ : mCallbacksPending(windowInfosListeners.size()),
+ mWindowInfosListeners(std::move(windowInfosListeners)),
+ mWindowInfosReportedListeners(std::move(windowInfosReportedListeners)) {}
- BackgroundExecutor::getInstance().sendCallbacks(
- {[this, listener = std::move(listener), listenerId]() {
- ATRACE_NAME("WindowInfosListenerInvoker::addWindowInfosListener");
+ binder::Status onWindowInfosReported() override {
+ if (--mCallbacksPending == 0) {
+ for (const auto& listener : mWindowInfosReportedListeners) {
sp<IBinder> asBinder = IInterface::asBinder(listener);
- asBinder->linkToDeath(sp<DeathRecipient>::fromExisting(this));
- mWindowInfosListeners.try_emplace(asBinder,
- std::make_pair(listenerId, std::move(listener)));
- }});
+ if (asBinder->isBinderAlive()) {
+ listener->onWindowInfosReported();
+ }
+ }
+
+ auto wpThis = wp<WindowInfosReportedListenerInvoker>::fromExisting(this);
+ for (const auto& listener : mWindowInfosListeners) {
+ sp<IBinder> binder = IInterface::asBinder(listener);
+ binder->unlinkToDeath(wpThis);
+ }
+ }
+ return binder::Status::ok();
+ }
+
+ void binderDied(const wp<IBinder>&) { onWindowInfosReported(); }
+
+private:
+ std::atomic<size_t> mCallbacksPending;
+ static constexpr size_t kStaticCapacity = 3;
+ const WindowInfosListenerVector mWindowInfosListeners;
+ WindowInfosReportedListenerSet mWindowInfosReportedListeners;
+};
+
+void WindowInfosListenerInvoker::addWindowInfosListener(sp<IWindowInfosListener> listener) {
+ sp<IBinder> asBinder = IInterface::asBinder(listener);
+ asBinder->linkToDeath(sp<DeathRecipient>::fromExisting(this));
+
+ std::scoped_lock lock(mListenersMutex);
+ mWindowInfosListeners.try_emplace(asBinder, std::move(listener));
}
void WindowInfosListenerInvoker::removeWindowInfosListener(
const sp<IWindowInfosListener>& listener) {
- BackgroundExecutor::getInstance().sendCallbacks({[this, listener]() {
- ATRACE_NAME("WindowInfosListenerInvoker::removeWindowInfosListener");
- sp<IBinder> asBinder = IInterface::asBinder(listener);
- asBinder->unlinkToDeath(sp<DeathRecipient>::fromExisting(this));
- mWindowInfosListeners.erase(asBinder);
- }});
+ sp<IBinder> asBinder = IInterface::asBinder(listener);
+
+ std::scoped_lock lock(mListenersMutex);
+ asBinder->unlinkToDeath(sp<DeathRecipient>::fromExisting(this));
+ mWindowInfosListeners.erase(asBinder);
}
void WindowInfosListenerInvoker::binderDied(const wp<IBinder>& who) {
- BackgroundExecutor::getInstance().sendCallbacks({[this, who]() {
- ATRACE_NAME("WindowInfosListenerInvoker::binderDied");
- auto it = mWindowInfosListeners.find(who);
- int64_t listenerId = it->second.first;
- mWindowInfosListeners.erase(who);
-
- std::vector<int64_t> vsyncIds;
- for (auto& [vsyncId, state] : mUnackedState) {
- if (std::find(state.unackedListenerIds.begin(), state.unackedListenerIds.end(),
- listenerId) != state.unackedListenerIds.end()) {
- vsyncIds.push_back(vsyncId);
- }
- }
-
- for (int64_t vsyncId : vsyncIds) {
- ackWindowInfosReceived(vsyncId, listenerId);
- }
- }});
+ std::scoped_lock lock(mListenersMutex);
+ mWindowInfosListeners.erase(who);
}
void WindowInfosListenerInvoker::windowInfosChanged(
gui::WindowInfosUpdate update, WindowInfosReportedListenerSet reportedListeners,
bool forceImmediateCall) {
- if (!mDelayInfo) {
- mDelayInfo = DelayInfo{
- .vsyncId = update.vsyncId,
- .frameTime = update.timestamp,
- };
- }
+ WindowInfosListenerVector listeners;
+ {
+ std::scoped_lock lock{mMessagesMutex};
+
+ if (!mDelayInfo) {
+ mDelayInfo = DelayInfo{
+ .vsyncId = update.vsyncId,
+ .frameTime = update.timestamp,
+ };
+ }
- // 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 (!mUnackedState.empty() && !forceImmediateCall) {
- mDelayedUpdate = std::move(update);
- mReportedListeners.merge(reportedListeners);
- return;
- }
+ // 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) {
+ mDelayedUpdate = std::move(update);
+ mReportedListeners.merge(reportedListeners);
+ return;
+ }
- if (mDelayedUpdate) {
- mDelayedUpdate.reset();
- }
+ if (mDelayedUpdate) {
+ mDelayedUpdate.reset();
+ }
+
+ {
+ std::scoped_lock lock{mListenersMutex};
+ for (const auto& [_, listener] : mWindowInfosListeners) {
+ listeners.push_back(listener);
+ }
+ }
+ if (CC_UNLIKELY(listeners.empty())) {
+ mReportedListeners.merge(reportedListeners);
+ mDelayInfo.reset();
+ return;
+ }
+
+ reportedListeners.insert(sp<WindowInfosListenerInvoker>::fromExisting(this));
+ reportedListeners.merge(mReportedListeners);
+ mReportedListeners.clear();
- if (CC_UNLIKELY(mWindowInfosListeners.empty())) {
- mReportedListeners.merge(reportedListeners);
+ mActiveMessageCount++;
+ updateMaxSendDelay();
mDelayInfo.reset();
- return;
}
- reportedListeners.merge(mReportedListeners);
- mReportedListeners.clear();
-
- // Update mUnackedState to include the message we're about to send
- auto [it, _] = mUnackedState.try_emplace(update.vsyncId,
- UnackedState{.reportedListeners =
- std::move(reportedListeners)});
- auto& unackedState = it->second;
- for (auto& pair : mWindowInfosListeners) {
- int64_t listenerId = pair.second.first;
- unackedState.unackedListenerIds.push_back(listenerId);
- }
+ auto reportedInvoker =
+ sp<WindowInfosReportedListenerInvoker>::make(listeners, std::move(reportedListeners));
- mDelayInfo.reset();
- updateMaxSendDelay();
+ for (const auto& listener : listeners) {
+ sp<IBinder> asBinder = IInterface::asBinder(listener);
- // Call the listeners
- for (auto& pair : mWindowInfosListeners) {
- auto& [listenerId, listener] = pair.second;
- auto status = listener->onWindowInfosChanged(update);
+ // linkToDeath is used here to ensure that the windowInfosReportedListeners
+ // are called even if one of the windowInfosListeners dies before
+ // calling onWindowInfosReported.
+ asBinder->linkToDeath(reportedInvoker);
+
+ auto status = listener->onWindowInfosChanged(update, reportedInvoker);
if (!status.isOk()) {
- ackWindowInfosReceived(update.vsyncId, listenerId);
+ reportedInvoker->onWindowInfosReported();
}
}
}
-WindowInfosListenerInvoker::DebugInfo WindowInfosListenerInvoker::getDebugInfo() {
- DebugInfo result;
- BackgroundExecutor::getInstance().sendCallbacks({[&, this]() {
- ATRACE_NAME("WindowInfosListenerInvoker::getDebugInfo");
- updateMaxSendDelay();
- result = mDebugInfo;
- result.pendingMessageCount = mUnackedState.size();
+binder::Status WindowInfosListenerInvoker::onWindowInfosReported() {
+ BackgroundExecutor::getInstance().sendCallbacks({[this]() {
+ gui::WindowInfosUpdate update;
+ {
+ std::scoped_lock lock{mMessagesMutex};
+ mActiveMessageCount--;
+ if (!mDelayedUpdate || mActiveMessageCount > 0) {
+ return;
+ }
+ update = std::move(*mDelayedUpdate);
+ mDelayedUpdate.reset();
+ }
+ windowInfosChanged(std::move(update), {}, false);
}});
- BackgroundExecutor::getInstance().flushQueue();
- return result;
+ return binder::Status::ok();
+}
+
+WindowInfosListenerInvoker::DebugInfo WindowInfosListenerInvoker::getDebugInfo() {
+ std::scoped_lock lock{mMessagesMutex};
+ updateMaxSendDelay();
+ mDebugInfo.pendingMessageCount = mActiveMessageCount;
+ return mDebugInfo;
}
void WindowInfosListenerInvoker::updateMaxSendDelay() {
@@ -162,41 +192,4 @@ void WindowInfosListenerInvoker::updateMaxSendDelay() {
}
}
-binder::Status WindowInfosListenerInvoker::ackWindowInfosReceived(int64_t vsyncId,
- int64_t listenerId) {
- BackgroundExecutor::getInstance().sendCallbacks({[this, vsyncId, listenerId]() {
- ATRACE_NAME("WindowInfosListenerInvoker::ackWindowInfosReceived");
- auto it = mUnackedState.find(vsyncId);
- if (it == mUnackedState.end()) {
- return;
- }
-
- auto& state = it->second;
- state.unackedListenerIds.unstable_erase(std::find(state.unackedListenerIds.begin(),
- state.unackedListenerIds.end(),
- listenerId));
- if (!state.unackedListenerIds.empty()) {
- return;
- }
-
- WindowInfosReportedListenerSet reportedListeners{std::move(state.reportedListeners)};
- mUnackedState.erase(vsyncId);
-
- for (const auto& reportedListener : reportedListeners) {
- sp<IBinder> asBinder = IInterface::asBinder(reportedListener);
- if (asBinder->isBinderAlive()) {
- reportedListener->onWindowInfosReported();
- }
- }
-
- if (!mDelayedUpdate || !mUnackedState.empty()) {
- return;
- }
- gui::WindowInfosUpdate update{std::move(*mDelayedUpdate)};
- mDelayedUpdate.reset();
- windowInfosChanged(std::move(update), {}, false);
- }});
- return binder::Status::ok();
-}
-
} // namespace android
diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.h b/services/surfaceflinger/WindowInfosListenerInvoker.h
index f36b0edd7d..bc465a3a2b 100644
--- a/services/surfaceflinger/WindowInfosListenerInvoker.h
+++ b/services/surfaceflinger/WindowInfosListenerInvoker.h
@@ -19,12 +19,11 @@
#include <optional>
#include <unordered_set>
-#include <android/gui/BnWindowInfosPublisher.h>
+#include <android/gui/BnWindowInfosReportedListener.h>
#include <android/gui/IWindowInfosListener.h>
#include <android/gui/IWindowInfosReportedListener.h>
#include <binder/IBinder.h>
#include <ftl/small_map.h>
-#include <ftl/small_vector.h>
#include <gui/SpHash.h>
#include <utils/Mutex.h>
@@ -36,22 +35,22 @@ using WindowInfosReportedListenerSet =
std::unordered_set<sp<gui::IWindowInfosReportedListener>,
gui::SpHash<gui::IWindowInfosReportedListener>>;
-class WindowInfosListenerInvoker : public gui::BnWindowInfosPublisher,
+class WindowInfosListenerInvoker : public gui::BnWindowInfosReportedListener,
public IBinder::DeathRecipient {
public:
- void addWindowInfosListener(sp<gui::IWindowInfosListener>, gui::WindowInfosListenerInfo*);
+ void addWindowInfosListener(sp<gui::IWindowInfosListener>);
void removeWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener);
void windowInfosChanged(gui::WindowInfosUpdate update,
WindowInfosReportedListenerSet windowInfosReportedListeners,
bool forceImmediateCall);
- binder::Status ackWindowInfosReceived(int64_t, int64_t) override;
+ binder::Status onWindowInfosReported() override;
struct DebugInfo {
VsyncId maxSendDelayVsyncId;
nsecs_t maxSendDelayDuration;
- size_t pendingMessageCount;
+ uint32_t pendingMessageCount;
};
DebugInfo getDebugInfo();
@@ -59,28 +58,24 @@ protected:
void binderDied(const wp<IBinder>& who) override;
private:
+ std::mutex mListenersMutex;
+
static constexpr size_t kStaticCapacity = 3;
- std::atomic<int64_t> mNextListenerId{0};
- ftl::SmallMap<wp<IBinder>, const std::pair<int64_t, sp<gui::IWindowInfosListener>>,
- kStaticCapacity>
- mWindowInfosListeners;
+ ftl::SmallMap<wp<IBinder>, const sp<gui::IWindowInfosListener>, kStaticCapacity>
+ mWindowInfosListeners GUARDED_BY(mListenersMutex);
- std::optional<gui::WindowInfosUpdate> mDelayedUpdate;
+ std::mutex mMessagesMutex;
+ uint32_t mActiveMessageCount GUARDED_BY(mMessagesMutex) = 0;
+ std::optional<gui::WindowInfosUpdate> mDelayedUpdate GUARDED_BY(mMessagesMutex);
WindowInfosReportedListenerSet mReportedListeners;
- struct UnackedState {
- ftl::SmallVector<int64_t, kStaticCapacity> unackedListenerIds;
- WindowInfosReportedListenerSet reportedListeners;
- };
- ftl::SmallMap<int64_t /* vsyncId */, UnackedState, 5> mUnackedState;
-
- DebugInfo mDebugInfo;
+ DebugInfo mDebugInfo GUARDED_BY(mMessagesMutex);
struct DelayInfo {
int64_t vsyncId;
nsecs_t frameTime;
};
- std::optional<DelayInfo> mDelayInfo;
- void updateMaxSendDelay();
+ std::optional<DelayInfo> mDelayInfo GUARDED_BY(mMessagesMutex);
+ void updateMaxSendDelay() REQUIRES(mMessagesMutex);
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/WindowInfosListenerInvokerTest.cpp b/services/surfaceflinger/tests/unittests/WindowInfosListenerInvokerTest.cpp
index c7b845e668..af4971b063 100644
--- a/services/surfaceflinger/tests/unittests/WindowInfosListenerInvokerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/WindowInfosListenerInvokerTest.cpp
@@ -15,23 +15,35 @@ protected:
WindowInfosListenerInvokerTest() : mInvoker(sp<WindowInfosListenerInvoker>::make()) {}
~WindowInfosListenerInvokerTest() {
+ std::mutex mutex;
+ std::condition_variable cv;
+ bool flushComplete = false;
// Flush the BackgroundExecutor thread to ensure any scheduled tasks are complete.
// Otherwise, references those tasks hold may go out of scope before they are done
// executing.
- BackgroundExecutor::getInstance().flushQueue();
+ BackgroundExecutor::getInstance().sendCallbacks({[&]() {
+ std::scoped_lock lock{mutex};
+ flushComplete = true;
+ cv.notify_one();
+ }});
+ std::unique_lock<std::mutex> lock{mutex};
+ cv.wait(lock, [&]() { return flushComplete; });
}
sp<WindowInfosListenerInvoker> mInvoker;
};
-using WindowInfosUpdateConsumer = std::function<void(const gui::WindowInfosUpdate&)>;
+using WindowInfosUpdateConsumer = std::function<void(const gui::WindowInfosUpdate&,
+ const sp<gui::IWindowInfosReportedListener>&)>;
class Listener : public gui::BnWindowInfosListener {
public:
Listener(WindowInfosUpdateConsumer consumer) : mConsumer(std::move(consumer)) {}
- binder::Status onWindowInfosChanged(const gui::WindowInfosUpdate& update) override {
- mConsumer(update);
+ binder::Status onWindowInfosChanged(
+ const gui::WindowInfosUpdate& update,
+ const sp<gui::IWindowInfosReportedListener>& reportedListener) override {
+ mConsumer(update, reportedListener);
return binder::Status::ok();
}
@@ -46,17 +58,15 @@ TEST_F(WindowInfosListenerInvokerTest, callsSingleListener) {
int callCount = 0;
- gui::WindowInfosListenerInfo listenerInfo;
- mInvoker->addWindowInfosListener(sp<Listener>::make([&](const gui::WindowInfosUpdate& update) {
- std::scoped_lock lock{mutex};
- callCount++;
- cv.notify_one();
+ mInvoker->addWindowInfosListener(
+ sp<Listener>::make([&](const gui::WindowInfosUpdate&,
+ const sp<gui::IWindowInfosReportedListener>& reportedListener) {
+ std::scoped_lock lock{mutex};
+ callCount++;
+ cv.notify_one();
- listenerInfo.windowInfosPublisher
- ->ackWindowInfosReceived(update.vsyncId,
- listenerInfo.listenerId);
- }),
- &listenerInfo);
+ reportedListener->onWindowInfosReported();
+ }));
BackgroundExecutor::getInstance().sendCallbacks(
{[this]() { mInvoker->windowInfosChanged({}, {}, false); }});
@@ -71,27 +81,21 @@ TEST_F(WindowInfosListenerInvokerTest, callsMultipleListeners) {
std::mutex mutex;
std::condition_variable cv;
- size_t callCount = 0;
- const size_t expectedCallCount = 3;
- std::vector<gui::WindowInfosListenerInfo> listenerInfos{expectedCallCount,
- gui::WindowInfosListenerInfo{}};
-
- for (size_t i = 0; i < expectedCallCount; i++) {
- mInvoker->addWindowInfosListener(sp<Listener>::make([&, &listenerInfo = listenerInfos[i]](
- const gui::WindowInfosUpdate&
- update) {
- std::scoped_lock lock{mutex};
- callCount++;
- if (callCount == expectedCallCount) {
- cv.notify_one();
- }
-
- listenerInfo.windowInfosPublisher
- ->ackWindowInfosReceived(update.vsyncId,
- listenerInfo
- .listenerId);
- }),
- &listenerInfos[i]);
+ int callCount = 0;
+ const int expectedCallCount = 3;
+
+ for (int i = 0; i < expectedCallCount; i++) {
+ mInvoker->addWindowInfosListener(sp<Listener>::make(
+ [&](const gui::WindowInfosUpdate&,
+ const sp<gui::IWindowInfosReportedListener>& reportedListener) {
+ std::scoped_lock lock{mutex};
+ callCount++;
+ if (callCount == expectedCallCount) {
+ cv.notify_one();
+ }
+
+ reportedListener->onWindowInfosReported();
+ }));
}
BackgroundExecutor::getInstance().sendCallbacks(
@@ -110,20 +114,17 @@ TEST_F(WindowInfosListenerInvokerTest, delaysUnackedCall) {
int callCount = 0;
- // Simulate a slow ack by not calling IWindowInfosPublisher.ackWindowInfosReceived
- gui::WindowInfosListenerInfo listenerInfo;
- mInvoker->addWindowInfosListener(sp<Listener>::make([&](const gui::WindowInfosUpdate&) {
- std::scoped_lock lock{mutex};
- callCount++;
- cv.notify_one();
- }),
- &listenerInfo);
+ // Simulate a slow ack by not calling the WindowInfosReportedListener.
+ mInvoker->addWindowInfosListener(sp<Listener>::make(
+ [&](const gui::WindowInfosUpdate&, const sp<gui::IWindowInfosReportedListener>&) {
+ std::scoped_lock lock{mutex};
+ callCount++;
+ cv.notify_one();
+ }));
BackgroundExecutor::getInstance().sendCallbacks({[&]() {
- mInvoker->windowInfosChanged(gui::WindowInfosUpdate{{}, {}, /* vsyncId= */ 0, 0}, {},
- false);
- mInvoker->windowInfosChanged(gui::WindowInfosUpdate{{}, {}, /* vsyncId= */ 1, 0}, {},
- false);
+ mInvoker->windowInfosChanged({}, {}, false);
+ mInvoker->windowInfosChanged({}, {}, false);
}});
{
@@ -133,7 +134,7 @@ TEST_F(WindowInfosListenerInvokerTest, delaysUnackedCall) {
EXPECT_EQ(callCount, 1);
// Ack the first message.
- listenerInfo.windowInfosPublisher->ackWindowInfosReceived(0, listenerInfo.listenerId);
+ mInvoker->onWindowInfosReported();
{
std::unique_lock lock{mutex};
@@ -151,21 +152,19 @@ TEST_F(WindowInfosListenerInvokerTest, sendsForcedMessage) {
int callCount = 0;
const int expectedCallCount = 2;
- // Simulate a slow ack by not calling IWindowInfosPublisher.ackWindowInfosReceived
- gui::WindowInfosListenerInfo listenerInfo;
- mInvoker->addWindowInfosListener(sp<Listener>::make([&](const gui::WindowInfosUpdate&) {
- std::scoped_lock lock{mutex};
- callCount++;
- if (callCount == expectedCallCount) {
- cv.notify_one();
- }
- }),
- &listenerInfo);
+ // Simulate a slow ack by not calling the WindowInfosReportedListener.
+ mInvoker->addWindowInfosListener(sp<Listener>::make(
+ [&](const gui::WindowInfosUpdate&, const sp<gui::IWindowInfosReportedListener>&) {
+ std::scoped_lock lock{mutex};
+ callCount++;
+ if (callCount == expectedCallCount) {
+ cv.notify_one();
+ }
+ }));
BackgroundExecutor::getInstance().sendCallbacks({[&]() {
- mInvoker->windowInfosChanged(gui::WindowInfosUpdate{{}, {}, /* vsyncId= */ 0, 0}, {},
- false);
- mInvoker->windowInfosChanged(gui::WindowInfosUpdate{{}, {}, /* vsyncId= */ 1, 0}, {}, true);
+ mInvoker->windowInfosChanged({}, {}, false);
+ mInvoker->windowInfosChanged({}, {}, true);
}});
{
@@ -183,14 +182,14 @@ TEST_F(WindowInfosListenerInvokerTest, skipsDelayedMessage) {
int64_t lastUpdateId = -1;
- // Simulate a slow ack by not calling IWindowInfosPublisher.ackWindowInfosReceived
- gui::WindowInfosListenerInfo listenerInfo;
- mInvoker->addWindowInfosListener(sp<Listener>::make([&](const gui::WindowInfosUpdate& update) {
- std::scoped_lock lock{mutex};
- lastUpdateId = update.vsyncId;
- cv.notify_one();
- }),
- &listenerInfo);
+ // Simulate a slow ack by not calling the WindowInfosReportedListener.
+ mInvoker->addWindowInfosListener(
+ sp<Listener>::make([&](const gui::WindowInfosUpdate& update,
+ const sp<gui::IWindowInfosReportedListener>&) {
+ std::scoped_lock lock{mutex};
+ lastUpdateId = update.vsyncId;
+ cv.notify_one();
+ }));
BackgroundExecutor::getInstance().sendCallbacks({[&]() {
mInvoker->windowInfosChanged({{}, {}, /* vsyncId= */ 1, 0}, {}, false);
@@ -205,7 +204,7 @@ TEST_F(WindowInfosListenerInvokerTest, skipsDelayedMessage) {
EXPECT_EQ(lastUpdateId, 1);
// Ack the first message. The third update should be sent.
- listenerInfo.windowInfosPublisher->ackWindowInfosReceived(1, listenerInfo.listenerId);
+ mInvoker->onWindowInfosReported();
{
std::unique_lock lock{mutex};
@@ -226,17 +225,14 @@ TEST_F(WindowInfosListenerInvokerTest, noListeners) {
// delayed.
BackgroundExecutor::getInstance().sendCallbacks({[&]() {
mInvoker->windowInfosChanged({}, {}, false);
- gui::WindowInfosListenerInfo listenerInfo;
- mInvoker->addWindowInfosListener(sp<Listener>::make([&](const gui::WindowInfosUpdate&) {
- std::scoped_lock lock{mutex};
- callCount++;
- cv.notify_one();
- }),
- &listenerInfo);
+ mInvoker->addWindowInfosListener(sp<Listener>::make(
+ [&](const gui::WindowInfosUpdate&, const sp<gui::IWindowInfosReportedListener>&) {
+ std::scoped_lock lock{mutex};
+ callCount++;
+ cv.notify_one();
+ }));
+ mInvoker->windowInfosChanged({}, {}, false);
}});
- BackgroundExecutor::getInstance().flushQueue();
- BackgroundExecutor::getInstance().sendCallbacks(
- {[&]() { mInvoker->windowInfosChanged({}, {}, false); }});
{
std::unique_lock lock{mutex};