Loading services/surfaceflinger/SurfaceFlinger.cpp +5 −2 Original line number Diff line number Diff line Loading @@ -3725,8 +3725,11 @@ void SurfaceFlinger::updateInputFlinger() { ATRACE_NAME("BackgroundExecutor::updateInputFlinger"); if (updateWindowInfo) { mWindowInfosListenerInvoker ->windowInfosChanged(windowInfos, displayInfos, inputWindowCommands.windowInfosReportedListeners); ->windowInfosChanged(std::move(windowInfos), std::move(displayInfos), std::move( inputWindowCommands.windowInfosReportedListeners), /* forceImmediateCall= */ !inputWindowCommands.focusRequests.empty()); } else { // If there are listeners but no changes to input windows, call the listeners // immediately. Loading services/surfaceflinger/WindowInfosListenerInvoker.cpp +69 −39 Original line number Diff line number Diff line Loading @@ -25,20 +25,14 @@ using gui::DisplayInfo; using gui::IWindowInfosListener; using gui::WindowInfo; struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowInfosReportedListener, DeathRecipient { explicit WindowInfosReportedListener( size_t callbackCount, const std::unordered_set<sp<gui::IWindowInfosReportedListener>, SpHash<gui::IWindowInfosReportedListener>>& windowInfosReportedListeners) struct WindowInfosReportedListenerInvoker : gui::BnWindowInfosReportedListener, IBinder::DeathRecipient { WindowInfosReportedListenerInvoker(size_t callbackCount, WindowInfosReportedListenerSet windowInfosReportedListeners) : mCallbacksPending(callbackCount), mWindowInfosReportedListeners(windowInfosReportedListeners) {} mWindowInfosReportedListeners(std::move(windowInfosReportedListeners)) {} binder::Status onWindowInfosReported() override { // TODO(b/222421815) There could potentially be callbacks that we don't need to wait for // before calling the WindowInfosReportedListeners coming from InputWindowCommands. Filter // the list of callbacks down to those from system server. if (--mCallbacksPending == 0) { for (const auto& listener : mWindowInfosReportedListeners) { sp<IBinder> asBinder = IInterface::asBinder(listener); Loading @@ -54,9 +48,7 @@ struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowIn private: std::atomic<size_t> mCallbacksPending; std::unordered_set<sp<gui::IWindowInfosReportedListener>, SpHash<gui::IWindowInfosReportedListener>> mWindowInfosReportedListeners; WindowInfosReportedListenerSet mWindowInfosReportedListeners; }; void WindowInfosListenerInvoker::addWindowInfosListener(sp<IWindowInfosListener> listener) { Loading @@ -82,10 +74,12 @@ void WindowInfosListenerInvoker::binderDied(const wp<IBinder>& who) { } void WindowInfosListenerInvoker::windowInfosChanged( const std::vector<WindowInfo>& windowInfos, const std::vector<DisplayInfo>& displayInfos, const std::unordered_set<sp<gui::IWindowInfosReportedListener>, SpHash<gui::IWindowInfosReportedListener>>& windowInfosReportedListeners) { std::vector<WindowInfo> windowInfos, std::vector<DisplayInfo> displayInfos, WindowInfosReportedListenerSet reportedListeners, bool forceImmediateCall) { reportedListeners.insert(sp<WindowInfosListenerInvoker>::fromExisting(this)); auto callListeners = [this, windowInfos = std::move(windowInfos), displayInfos = std::move(displayInfos), reportedListeners = std::move(reportedListeners)]() mutable { ftl::SmallVector<const sp<IWindowInfosListener>, kStaticCapacity> windowInfosListeners; { std::scoped_lock lock(mListenersMutex); Loading @@ -94,26 +88,62 @@ void WindowInfosListenerInvoker::windowInfosChanged( } } auto windowInfosReportedListener = windowInfosReportedListeners.empty() ? nullptr : sp<WindowInfosReportedListener>::make(windowInfosListeners.size(), windowInfosReportedListeners); auto reportedInvoker = sp<WindowInfosReportedListenerInvoker>::make(windowInfosListeners.size(), std::move(reportedListeners)); for (const auto& listener : windowInfosListeners) { sp<IBinder> asBinder = IInterface::asBinder(listener); // linkToDeath is used here to ensure that the windowInfosReportedListeners // are called even if one of the windowInfosListeners dies before // calling onWindowInfosReported. if (windowInfosReportedListener) { asBinder->linkToDeath(windowInfosReportedListener); asBinder->linkToDeath(reportedInvoker); auto status = listener->onWindowInfosChanged(windowInfos, displayInfos, reportedInvoker); if (!status.isOk()) { reportedInvoker->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); return; } mWindowInfosChangedDelayed = nullptr; mActiveMessageCount++; } callListeners(); } auto status = listener->onWindowInfosChanged(windowInfos, displayInfos, windowInfosReportedListener); if (windowInfosReportedListener && !status.isOk()) { windowInfosReportedListener->onWindowInfosReported(); binder::Status WindowInfosListenerInvoker::onWindowInfosReported() { std::function<void()> callListeners; { std::scoped_lock lock{mMessagesMutex}; mActiveMessageCount--; if (!mWindowInfosChangedDelayed || mActiveMessageCount > 0) { return binder::Status::ok(); } mActiveMessageCount++; callListeners = std::move(mWindowInfosChangedDelayed); mWindowInfosChangedDelayed = nullptr; } callListeners(); return binder::Status::ok(); } } // namespace android services/surfaceflinger/WindowInfosListenerInvoker.h +15 −9 Original line number Diff line number Diff line Loading @@ -23,34 +23,40 @@ #include <android/gui/IWindowInfosReportedListener.h> #include <binder/IBinder.h> #include <ftl/small_map.h> #include <gui/SpHash.h> #include <utils/Mutex.h> namespace android { class SurfaceFlinger; using WindowInfosReportedListenerSet = std::unordered_set<sp<gui::IWindowInfosReportedListener>, gui::SpHash<gui::IWindowInfosReportedListener>>; class WindowInfosListenerInvoker : public IBinder::DeathRecipient { class WindowInfosListenerInvoker : public gui::BnWindowInfosReportedListener, public IBinder::DeathRecipient { 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>&, const std::unordered_set<sp<gui::IWindowInfosReportedListener>, SpHash<gui::IWindowInfosReportedListener>>& windowInfosReportedListeners); void windowInfosChanged(std::vector<gui::WindowInfo>, std::vector<gui::DisplayInfo>, WindowInfosReportedListenerSet windowInfosReportedListeners, bool forceImmediateCall); binder::Status onWindowInfosReported() override; protected: void binderDied(const wp<IBinder>& who) override; private: struct WindowInfosReportedListener; std::mutex mListenersMutex; static constexpr size_t kStaticCapacity = 3; ftl::SmallMap<wp<IBinder>, const sp<gui::IWindowInfosListener>, kStaticCapacity> mWindowInfosListeners GUARDED_BY(mListenersMutex); std::mutex mMessagesMutex; uint32_t mActiveMessageCount GUARDED_BY(mMessagesMutex) = 0; std::function<void()> mWindowInfosChangedDelayed GUARDED_BY(mMessagesMutex); }; } // namespace android Loading
services/surfaceflinger/SurfaceFlinger.cpp +5 −2 Original line number Diff line number Diff line Loading @@ -3725,8 +3725,11 @@ void SurfaceFlinger::updateInputFlinger() { ATRACE_NAME("BackgroundExecutor::updateInputFlinger"); if (updateWindowInfo) { mWindowInfosListenerInvoker ->windowInfosChanged(windowInfos, displayInfos, inputWindowCommands.windowInfosReportedListeners); ->windowInfosChanged(std::move(windowInfos), std::move(displayInfos), std::move( inputWindowCommands.windowInfosReportedListeners), /* forceImmediateCall= */ !inputWindowCommands.focusRequests.empty()); } else { // If there are listeners but no changes to input windows, call the listeners // immediately. Loading
services/surfaceflinger/WindowInfosListenerInvoker.cpp +69 −39 Original line number Diff line number Diff line Loading @@ -25,20 +25,14 @@ using gui::DisplayInfo; using gui::IWindowInfosListener; using gui::WindowInfo; struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowInfosReportedListener, DeathRecipient { explicit WindowInfosReportedListener( size_t callbackCount, const std::unordered_set<sp<gui::IWindowInfosReportedListener>, SpHash<gui::IWindowInfosReportedListener>>& windowInfosReportedListeners) struct WindowInfosReportedListenerInvoker : gui::BnWindowInfosReportedListener, IBinder::DeathRecipient { WindowInfosReportedListenerInvoker(size_t callbackCount, WindowInfosReportedListenerSet windowInfosReportedListeners) : mCallbacksPending(callbackCount), mWindowInfosReportedListeners(windowInfosReportedListeners) {} mWindowInfosReportedListeners(std::move(windowInfosReportedListeners)) {} binder::Status onWindowInfosReported() override { // TODO(b/222421815) There could potentially be callbacks that we don't need to wait for // before calling the WindowInfosReportedListeners coming from InputWindowCommands. Filter // the list of callbacks down to those from system server. if (--mCallbacksPending == 0) { for (const auto& listener : mWindowInfosReportedListeners) { sp<IBinder> asBinder = IInterface::asBinder(listener); Loading @@ -54,9 +48,7 @@ struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowIn private: std::atomic<size_t> mCallbacksPending; std::unordered_set<sp<gui::IWindowInfosReportedListener>, SpHash<gui::IWindowInfosReportedListener>> mWindowInfosReportedListeners; WindowInfosReportedListenerSet mWindowInfosReportedListeners; }; void WindowInfosListenerInvoker::addWindowInfosListener(sp<IWindowInfosListener> listener) { Loading @@ -82,10 +74,12 @@ void WindowInfosListenerInvoker::binderDied(const wp<IBinder>& who) { } void WindowInfosListenerInvoker::windowInfosChanged( const std::vector<WindowInfo>& windowInfos, const std::vector<DisplayInfo>& displayInfos, const std::unordered_set<sp<gui::IWindowInfosReportedListener>, SpHash<gui::IWindowInfosReportedListener>>& windowInfosReportedListeners) { std::vector<WindowInfo> windowInfos, std::vector<DisplayInfo> displayInfos, WindowInfosReportedListenerSet reportedListeners, bool forceImmediateCall) { reportedListeners.insert(sp<WindowInfosListenerInvoker>::fromExisting(this)); auto callListeners = [this, windowInfos = std::move(windowInfos), displayInfos = std::move(displayInfos), reportedListeners = std::move(reportedListeners)]() mutable { ftl::SmallVector<const sp<IWindowInfosListener>, kStaticCapacity> windowInfosListeners; { std::scoped_lock lock(mListenersMutex); Loading @@ -94,26 +88,62 @@ void WindowInfosListenerInvoker::windowInfosChanged( } } auto windowInfosReportedListener = windowInfosReportedListeners.empty() ? nullptr : sp<WindowInfosReportedListener>::make(windowInfosListeners.size(), windowInfosReportedListeners); auto reportedInvoker = sp<WindowInfosReportedListenerInvoker>::make(windowInfosListeners.size(), std::move(reportedListeners)); for (const auto& listener : windowInfosListeners) { sp<IBinder> asBinder = IInterface::asBinder(listener); // linkToDeath is used here to ensure that the windowInfosReportedListeners // are called even if one of the windowInfosListeners dies before // calling onWindowInfosReported. if (windowInfosReportedListener) { asBinder->linkToDeath(windowInfosReportedListener); asBinder->linkToDeath(reportedInvoker); auto status = listener->onWindowInfosChanged(windowInfos, displayInfos, reportedInvoker); if (!status.isOk()) { reportedInvoker->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); return; } mWindowInfosChangedDelayed = nullptr; mActiveMessageCount++; } callListeners(); } auto status = listener->onWindowInfosChanged(windowInfos, displayInfos, windowInfosReportedListener); if (windowInfosReportedListener && !status.isOk()) { windowInfosReportedListener->onWindowInfosReported(); binder::Status WindowInfosListenerInvoker::onWindowInfosReported() { std::function<void()> callListeners; { std::scoped_lock lock{mMessagesMutex}; mActiveMessageCount--; if (!mWindowInfosChangedDelayed || mActiveMessageCount > 0) { return binder::Status::ok(); } mActiveMessageCount++; callListeners = std::move(mWindowInfosChangedDelayed); mWindowInfosChangedDelayed = nullptr; } callListeners(); return binder::Status::ok(); } } // namespace android
services/surfaceflinger/WindowInfosListenerInvoker.h +15 −9 Original line number Diff line number Diff line Loading @@ -23,34 +23,40 @@ #include <android/gui/IWindowInfosReportedListener.h> #include <binder/IBinder.h> #include <ftl/small_map.h> #include <gui/SpHash.h> #include <utils/Mutex.h> namespace android { class SurfaceFlinger; using WindowInfosReportedListenerSet = std::unordered_set<sp<gui::IWindowInfosReportedListener>, gui::SpHash<gui::IWindowInfosReportedListener>>; class WindowInfosListenerInvoker : public IBinder::DeathRecipient { class WindowInfosListenerInvoker : public gui::BnWindowInfosReportedListener, public IBinder::DeathRecipient { 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>&, const std::unordered_set<sp<gui::IWindowInfosReportedListener>, SpHash<gui::IWindowInfosReportedListener>>& windowInfosReportedListeners); void windowInfosChanged(std::vector<gui::WindowInfo>, std::vector<gui::DisplayInfo>, WindowInfosReportedListenerSet windowInfosReportedListeners, bool forceImmediateCall); binder::Status onWindowInfosReported() override; protected: void binderDied(const wp<IBinder>& who) override; private: struct WindowInfosReportedListener; std::mutex mListenersMutex; static constexpr size_t kStaticCapacity = 3; ftl::SmallMap<wp<IBinder>, const sp<gui::IWindowInfosListener>, kStaticCapacity> mWindowInfosListeners GUARDED_BY(mListenersMutex); std::mutex mMessagesMutex; uint32_t mActiveMessageCount GUARDED_BY(mMessagesMutex) = 0; std::function<void()> mWindowInfosChangedDelayed GUARDED_BY(mMessagesMutex); }; } // namespace android