diff options
author | Ken Chen <cken@google.com> | 2023-08-31 01:53:33 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2023-08-31 01:53:34 +0000 |
commit | a8ce8fc1d892ba7dcb27961b7bf49cc6433da7bb (patch) | |
tree | 780232b872244049ccaaf0463f990de8fe4b64a2 | |
parent | 82f3463d449eb13e28c5dbffeee16e10721c71d2 (diff) | |
download | native-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.bp | 2 | ||||
-rw-r--r-- | libs/gui/WindowInfosListenerReporter.cpp | 20 | ||||
-rw-r--r-- | libs/gui/aidl/android/gui/ISurfaceComposer.aidl | 4 | ||||
-rw-r--r-- | libs/gui/aidl/android/gui/WindowInfosListenerInfo.aidl | 25 | ||||
-rw-r--r-- | libs/gui/android/gui/IWindowInfosListener.aidl | 4 | ||||
-rw-r--r-- | libs/gui/android/gui/IWindowInfosPublisher.aidl | 23 | ||||
-rw-r--r-- | libs/gui/fuzzer/libgui_fuzzer_utils.h | 4 | ||||
-rw-r--r-- | libs/gui/include/gui/ISurfaceComposer.h | 1 | ||||
-rw-r--r-- | libs/gui/include/gui/WindowInfosListenerReporter.h | 8 | ||||
-rw-r--r-- | libs/gui/tests/Surface_test.cpp | 3 | ||||
-rw-r--r-- | services/surfaceflinger/BackgroundExecutor.cpp | 14 | ||||
-rw-r--r-- | services/surfaceflinger/BackgroundExecutor.h | 1 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 14 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 7 | ||||
-rw-r--r-- | services/surfaceflinger/WindowInfosListenerInvoker.cpp | 253 | ||||
-rw-r--r-- | services/surfaceflinger/WindowInfosListenerInvoker.h | 35 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/WindowInfosListenerInvokerTest.cpp | 156 |
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}; |