Loading services/surfaceflinger/SurfaceFlinger.cpp +5 −2 Original line number Diff line number Diff line Loading @@ -3257,8 +3257,11 @@ void SurfaceFlinger::updateInputFlinger() { inputFlinger = mInputFlinger, this]() { ATRACE_NAME("BackgroundExecutor::updateInputFlinger"); if (updateWindowInfo) { mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos, inputWindowCommands.syncInputWindows); mWindowInfosListenerInvoker ->windowInfosChanged(std::move(windowInfos), std::move(displayInfos), /* shouldSync= */ inputWindowCommands.syncInputWindows, /* forceImmediateCall= */ !inputWindowCommands.focusRequests.empty()); } else if (inputWindowCommands.syncInputWindows) { // If the caller requested to sync input windows, but there are no // changes to input windows, notify immediately. Loading services/surfaceflinger/WindowInfosListenerInvoker.cpp +73 −20 Original line number Diff line number Diff line Loading @@ -28,19 +28,26 @@ using gui::WindowInfo; struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowInfosReportedListener { explicit WindowInfosReportedListener(WindowInfosListenerInvoker& invoker) : mInvoker(invoker) {} explicit WindowInfosReportedListener(WindowInfosListenerInvoker& invoker, size_t callbackCount, bool shouldSync) : mInvoker(invoker), mCallbacksPending(callbackCount), mShouldSync(shouldSync) {} binder::Status onWindowInfosReported() override { mInvoker.windowInfosReported(); mCallbacksPending--; if (mCallbacksPending == 0) { mInvoker.windowInfosReported(mShouldSync); } return binder::Status::ok(); } private: WindowInfosListenerInvoker& mInvoker; std::atomic<size_t> mCallbacksPending; bool mShouldSync; }; WindowInfosListenerInvoker::WindowInfosListenerInvoker(SurfaceFlinger& flinger) : mFlinger(flinger), mWindowInfosReportedListener(sp<WindowInfosReportedListener>::make(*this)) {} : mFlinger(flinger) {} void WindowInfosListenerInvoker::addWindowInfosListener(sp<IWindowInfosListener> listener) { sp<IBinder> asBinder = IInterface::asBinder(listener); Loading @@ -64,9 +71,11 @@ void WindowInfosListenerInvoker::binderDied(const wp<IBinder>& who) { mWindowInfosListeners.erase(who); } void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo>& windowInfos, const std::vector<DisplayInfo>& displayInfos, bool shouldSync) { void WindowInfosListenerInvoker::windowInfosChanged(std::vector<WindowInfo> windowInfos, std::vector<DisplayInfo> displayInfos, bool shouldSync, bool forceImmediateCall) { auto callListeners = [this, windowInfos = std::move(windowInfos), displayInfos = std::move(displayInfos)](bool shouldSync) mutable { ftl::SmallVector<const sp<IWindowInfosListener>, kStaticCapacity> windowInfosListeners; { std::scoped_lock lock(mListenersMutex); Loading @@ -75,19 +84,63 @@ void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo } } mCallbacksPending = windowInfosListeners.size(); auto reportedListener = sp<WindowInfosReportedListener>::make(*this, windowInfosListeners.size(), shouldSync); for (const auto& listener : windowInfosListeners) { listener->onWindowInfosChanged(windowInfos, displayInfos, shouldSync ? mWindowInfosReportedListener : nullptr); auto status = listener->onWindowInfosChanged(windowInfos, displayInfos, reportedListener); if (!status.isOk()) { reportedListener->onWindowInfosReported(); } } }; void WindowInfosListenerInvoker::windowInfosReported() { mCallbacksPending--; if (mCallbacksPending == 0) { { std::scoped_lock lock(mMessagesMutex); // If there are unacked messages and this isn't a forced call, then return immediately. // If a forced window infos change doesn't happen first, the update will be sent after // the WindowInfosReportedListeners are called. If a forced window infos change happens or // if there are subsequent delayed messages before this update is sent, then this message // will be dropped and the listeners will only be called with the latest info. This is done // to reduce the amount of binder memory used. if (mActiveMessageCount > 0 && !forceImmediateCall) { mWindowInfosChangedDelayed = std::move(callListeners); mShouldSyncDelayed |= shouldSync; return; } mWindowInfosChangedDelayed = nullptr; shouldSync |= mShouldSyncDelayed; mShouldSyncDelayed = false; mActiveMessageCount++; } callListeners(shouldSync); } void WindowInfosListenerInvoker::windowInfosReported(bool shouldSync) { if (shouldSync) { mFlinger.windowInfosReported(); } std::function<void(bool)> callListeners; bool shouldSyncDelayed; { std::scoped_lock lock{mMessagesMutex}; mActiveMessageCount--; if (!mWindowInfosChangedDelayed || mActiveMessageCount > 0) { return; } mActiveMessageCount++; callListeners = std::move(mWindowInfosChangedDelayed); mWindowInfosChangedDelayed = nullptr; shouldSyncDelayed = mShouldSyncDelayed; mShouldSyncDelayed = false; } callListeners(shouldSyncDelayed); } } // namespace android services/surfaceflinger/WindowInfosListenerInvoker.h +7 −5 Original line number Diff line number Diff line Loading @@ -34,15 +34,15 @@ public: void addWindowInfosListener(sp<gui::IWindowInfosListener>); void removeWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener); void windowInfosChanged(const std::vector<gui::WindowInfo>&, const std::vector<gui::DisplayInfo>&, bool shouldSync); void windowInfosChanged(std::vector<gui::WindowInfo>, std::vector<gui::DisplayInfo>, bool shouldSync, bool forceImmediateCall); protected: void binderDied(const wp<IBinder>& who) override; private: struct WindowInfosReportedListener; void windowInfosReported(); void windowInfosReported(bool shouldSync); SurfaceFlinger& mFlinger; std::mutex mListenersMutex; Loading @@ -51,8 +51,10 @@ private: ftl::SmallMap<wp<IBinder>, const sp<gui::IWindowInfosListener>, kStaticCapacity> mWindowInfosListeners GUARDED_BY(mListenersMutex); sp<gui::IWindowInfosReportedListener> mWindowInfosReportedListener; std::atomic<size_t> mCallbacksPending{0}; std::mutex mMessagesMutex; uint32_t mActiveMessageCount GUARDED_BY(mMessagesMutex) = 0; std::function<void(bool)> mWindowInfosChangedDelayed GUARDED_BY(mMessagesMutex); bool mShouldSyncDelayed; }; } // namespace android Loading
services/surfaceflinger/SurfaceFlinger.cpp +5 −2 Original line number Diff line number Diff line Loading @@ -3257,8 +3257,11 @@ void SurfaceFlinger::updateInputFlinger() { inputFlinger = mInputFlinger, this]() { ATRACE_NAME("BackgroundExecutor::updateInputFlinger"); if (updateWindowInfo) { mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos, inputWindowCommands.syncInputWindows); mWindowInfosListenerInvoker ->windowInfosChanged(std::move(windowInfos), std::move(displayInfos), /* shouldSync= */ inputWindowCommands.syncInputWindows, /* forceImmediateCall= */ !inputWindowCommands.focusRequests.empty()); } else if (inputWindowCommands.syncInputWindows) { // If the caller requested to sync input windows, but there are no // changes to input windows, notify immediately. Loading
services/surfaceflinger/WindowInfosListenerInvoker.cpp +73 −20 Original line number Diff line number Diff line Loading @@ -28,19 +28,26 @@ using gui::WindowInfo; struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowInfosReportedListener { explicit WindowInfosReportedListener(WindowInfosListenerInvoker& invoker) : mInvoker(invoker) {} explicit WindowInfosReportedListener(WindowInfosListenerInvoker& invoker, size_t callbackCount, bool shouldSync) : mInvoker(invoker), mCallbacksPending(callbackCount), mShouldSync(shouldSync) {} binder::Status onWindowInfosReported() override { mInvoker.windowInfosReported(); mCallbacksPending--; if (mCallbacksPending == 0) { mInvoker.windowInfosReported(mShouldSync); } return binder::Status::ok(); } private: WindowInfosListenerInvoker& mInvoker; std::atomic<size_t> mCallbacksPending; bool mShouldSync; }; WindowInfosListenerInvoker::WindowInfosListenerInvoker(SurfaceFlinger& flinger) : mFlinger(flinger), mWindowInfosReportedListener(sp<WindowInfosReportedListener>::make(*this)) {} : mFlinger(flinger) {} void WindowInfosListenerInvoker::addWindowInfosListener(sp<IWindowInfosListener> listener) { sp<IBinder> asBinder = IInterface::asBinder(listener); Loading @@ -64,9 +71,11 @@ void WindowInfosListenerInvoker::binderDied(const wp<IBinder>& who) { mWindowInfosListeners.erase(who); } void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo>& windowInfos, const std::vector<DisplayInfo>& displayInfos, bool shouldSync) { void WindowInfosListenerInvoker::windowInfosChanged(std::vector<WindowInfo> windowInfos, std::vector<DisplayInfo> displayInfos, bool shouldSync, bool forceImmediateCall) { auto callListeners = [this, windowInfos = std::move(windowInfos), displayInfos = std::move(displayInfos)](bool shouldSync) mutable { ftl::SmallVector<const sp<IWindowInfosListener>, kStaticCapacity> windowInfosListeners; { std::scoped_lock lock(mListenersMutex); Loading @@ -75,19 +84,63 @@ void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo } } mCallbacksPending = windowInfosListeners.size(); auto reportedListener = sp<WindowInfosReportedListener>::make(*this, windowInfosListeners.size(), shouldSync); for (const auto& listener : windowInfosListeners) { listener->onWindowInfosChanged(windowInfos, displayInfos, shouldSync ? mWindowInfosReportedListener : nullptr); auto status = listener->onWindowInfosChanged(windowInfos, displayInfos, reportedListener); if (!status.isOk()) { reportedListener->onWindowInfosReported(); } } }; void WindowInfosListenerInvoker::windowInfosReported() { mCallbacksPending--; if (mCallbacksPending == 0) { { std::scoped_lock lock(mMessagesMutex); // If there are unacked messages and this isn't a forced call, then return immediately. // If a forced window infos change doesn't happen first, the update will be sent after // the WindowInfosReportedListeners are called. If a forced window infos change happens or // if there are subsequent delayed messages before this update is sent, then this message // will be dropped and the listeners will only be called with the latest info. This is done // to reduce the amount of binder memory used. if (mActiveMessageCount > 0 && !forceImmediateCall) { mWindowInfosChangedDelayed = std::move(callListeners); mShouldSyncDelayed |= shouldSync; return; } mWindowInfosChangedDelayed = nullptr; shouldSync |= mShouldSyncDelayed; mShouldSyncDelayed = false; mActiveMessageCount++; } callListeners(shouldSync); } void WindowInfosListenerInvoker::windowInfosReported(bool shouldSync) { if (shouldSync) { mFlinger.windowInfosReported(); } std::function<void(bool)> callListeners; bool shouldSyncDelayed; { std::scoped_lock lock{mMessagesMutex}; mActiveMessageCount--; if (!mWindowInfosChangedDelayed || mActiveMessageCount > 0) { return; } mActiveMessageCount++; callListeners = std::move(mWindowInfosChangedDelayed); mWindowInfosChangedDelayed = nullptr; shouldSyncDelayed = mShouldSyncDelayed; mShouldSyncDelayed = false; } callListeners(shouldSyncDelayed); } } // namespace android
services/surfaceflinger/WindowInfosListenerInvoker.h +7 −5 Original line number Diff line number Diff line Loading @@ -34,15 +34,15 @@ public: void addWindowInfosListener(sp<gui::IWindowInfosListener>); void removeWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener); void windowInfosChanged(const std::vector<gui::WindowInfo>&, const std::vector<gui::DisplayInfo>&, bool shouldSync); void windowInfosChanged(std::vector<gui::WindowInfo>, std::vector<gui::DisplayInfo>, bool shouldSync, bool forceImmediateCall); protected: void binderDied(const wp<IBinder>& who) override; private: struct WindowInfosReportedListener; void windowInfosReported(); void windowInfosReported(bool shouldSync); SurfaceFlinger& mFlinger; std::mutex mListenersMutex; Loading @@ -51,8 +51,10 @@ private: ftl::SmallMap<wp<IBinder>, const sp<gui::IWindowInfosListener>, kStaticCapacity> mWindowInfosListeners GUARDED_BY(mListenersMutex); sp<gui::IWindowInfosReportedListener> mWindowInfosReportedListener; std::atomic<size_t> mCallbacksPending{0}; std::mutex mMessagesMutex; uint32_t mActiveMessageCount GUARDED_BY(mMessagesMutex) = 0; std::function<void(bool)> mWindowInfosChangedDelayed GUARDED_BY(mMessagesMutex); bool mShouldSyncDelayed; }; } // namespace android