Loading services/surfaceflinger/Layer.cpp +1 −10 Original line number Diff line number Diff line Loading @@ -2442,16 +2442,7 @@ WindowInfo Layer::fillInputInfo(const InputDisplayArgs& displayArgs) { info.inputConfig |= WindowInfo::InputConfig::NOT_TOUCHABLE; } // For compatibility reasons we let layers which can receive input // receive input before they have actually submitted a buffer. Because // of this we use canReceiveInput instead of isVisible to check the // policy-visibility, ignoring the buffer state. However for layers with // hasInputInfo()==false we can use the real visibility state. // We are just using these layers for occlusion detection in // InputDispatcher, and obviously if they aren't visible they can't occlude // anything. const bool visible = hasInputInfo() ? canReceiveInput() : isVisible(); info.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible); info.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !isVisibleForInput()); info.alpha = getAlpha(); fillTouchOcclusionMode(info); Loading services/surfaceflinger/Layer.h +15 −0 Original line number Diff line number Diff line Loading @@ -371,6 +371,21 @@ public: */ bool canReceiveInput() const; /* * Whether or not the layer should be considered visible for input calculations. */ virtual bool isVisibleForInput() const { // For compatibility reasons we let layers which can receive input // receive input before they have actually submitted a buffer. Because // of this we use canReceiveInput instead of isVisible to check the // policy-visibility, ignoring the buffer state. However for layers with // hasInputInfo()==false we can use the real visibility state. // We are just using these layers for occlusion detection in // InputDispatcher, and obviously if they aren't visible they can't occlude // anything. return hasInputInfo() ? canReceiveInput() : isVisible(); } /* * isProtected - true if the layer may contain protected contents in the * GRALLOC_USAGE_PROTECTED sense. Loading services/surfaceflinger/SurfaceFlinger.cpp +19 −3 Original line number Diff line number Diff line Loading @@ -3715,17 +3715,33 @@ void SurfaceFlinger::updateInputFlinger() { return; } std::unordered_set<Layer*> visibleLayers; mDrawingState.traverse([&visibleLayers](Layer* layer) { if (layer->isVisibleForInput()) { visibleLayers.insert(layer); } }); bool visibleLayersChanged = false; if (visibleLayers != mVisibleLayers) { visibleLayersChanged = true; mVisibleLayers = std::move(visibleLayers); } BackgroundExecutor::getInstance().sendCallbacks({[updateWindowInfo, windowInfos = std::move(windowInfos), displayInfos = std::move(displayInfos), inputWindowCommands = std::move(mInputWindowCommands), inputFlinger = mInputFlinger, this]() { inputFlinger = mInputFlinger, this, visibleLayersChanged]() { ATRACE_NAME("BackgroundExecutor::updateInputFlinger"); if (updateWindowInfo) { mWindowInfosListenerInvoker ->windowInfosChanged(windowInfos, displayInfos, inputWindowCommands.windowInfosReportedListeners); ->windowInfosChanged(std::move(windowInfos), std::move(displayInfos), std::move( inputWindowCommands.windowInfosReportedListeners), /* forceImmediateCall= */ visibleLayersChanged || !inputWindowCommands.focusRequests.empty()); } else { // If there are listeners but no changes to input windows, call the listeners // immediately. Loading services/surfaceflinger/SurfaceFlinger.h +5 −0 Original line number Diff line number Diff line Loading @@ -1424,6 +1424,11 @@ private: TransactionHandler mTransactionHandler; display::DisplayMap<ui::LayerStack, frontend::DisplayInfo> mFrontEndDisplayInfos; bool mFrontEndDisplayInfosChanged = false; // Layers visible during the last commit. This set should only be used for testing set equality // and membership. The pointers should not be dereferenced as it's possible the set contains // pointers to freed layers. std::unordered_set<Layer*> mVisibleLayers; }; class SurfaceComposerAIDL : public gui::BnSurfaceComposer { Loading services/surfaceflinger/WindowInfosListenerInvoker.cpp +86 −40 Original line number Diff line number Diff line Loading @@ -25,20 +25,17 @@ 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) : mCallbacksPending(callbackCount), mWindowInfosReportedListeners(windowInfosReportedListeners) {} using WindowInfosListenerVector = ftl::SmallVector<const sp<IWindowInfosListener>, 3>; struct WindowInfosReportedListenerInvoker : gui::BnWindowInfosReportedListener, IBinder::DeathRecipient { WindowInfosReportedListenerInvoker(WindowInfosListenerVector windowInfosListeners, WindowInfosReportedListenerSet windowInfosReportedListeners) : mCallbacksPending(windowInfosListeners.size()), mWindowInfosListeners(std::move(windowInfosListeners)), 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 @@ -46,6 +43,12 @@ struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowIn 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(); } Loading @@ -54,9 +57,9 @@ struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowIn private: std::atomic<size_t> mCallbacksPending; std::unordered_set<sp<gui::IWindowInfosReportedListener>, SpHash<gui::IWindowInfosReportedListener>> mWindowInfosReportedListeners; static constexpr size_t kStaticCapacity = 3; const WindowInfosListenerVector mWindowInfosListeners; WindowInfosReportedListenerSet mWindowInfosReportedListeners; }; void WindowInfosListenerInvoker::addWindowInfosListener(sp<IWindowInfosListener> listener) { Loading @@ -82,11 +85,13 @@ 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) { ftl::SmallVector<const sp<IWindowInfosListener>, kStaticCapacity> windowInfosListeners; 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)]( WindowInfosReportedListenerSet reportedListeners) mutable { WindowInfosListenerVector windowInfosListeners; { std::scoped_lock lock(mListenersMutex); for (const auto& [_, listener] : mWindowInfosListeners) { Loading @@ -94,26 +99,67 @@ void WindowInfosListenerInvoker::windowInfosChanged( } } auto windowInfosReportedListener = windowInfosReportedListeners.empty() ? nullptr : sp<WindowInfosReportedListener>::make(windowInfosListeners.size(), windowInfosReportedListeners); auto reportedInvoker = sp<WindowInfosReportedListenerInvoker>::make(windowInfosListeners, 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); mReportedListenersDelayed.merge(reportedListeners); return; } auto status = listener->onWindowInfosChanged(windowInfos, displayInfos, windowInfosReportedListener); if (windowInfosReportedListener && !status.isOk()) { windowInfosReportedListener->onWindowInfosReported(); mWindowInfosChangedDelayed = nullptr; reportedListeners.merge(mReportedListenersDelayed); mActiveMessageCount++; } callListeners(std::move(reportedListeners)); } binder::Status WindowInfosListenerInvoker::onWindowInfosReported() { std::function<void(WindowInfosReportedListenerSet)> callListeners; WindowInfosReportedListenerSet reportedListeners; { std::scoped_lock lock{mMessagesMutex}; mActiveMessageCount--; if (!mWindowInfosChangedDelayed || mActiveMessageCount > 0) { return binder::Status::ok(); } mActiveMessageCount++; callListeners = std::move(mWindowInfosChangedDelayed); mWindowInfosChangedDelayed = nullptr; reportedListeners = std::move(mReportedListenersDelayed); mReportedListenersDelayed.clear(); } callListeners(std::move(reportedListeners)); return binder::Status::ok(); } } // namespace android Loading
services/surfaceflinger/Layer.cpp +1 −10 Original line number Diff line number Diff line Loading @@ -2442,16 +2442,7 @@ WindowInfo Layer::fillInputInfo(const InputDisplayArgs& displayArgs) { info.inputConfig |= WindowInfo::InputConfig::NOT_TOUCHABLE; } // For compatibility reasons we let layers which can receive input // receive input before they have actually submitted a buffer. Because // of this we use canReceiveInput instead of isVisible to check the // policy-visibility, ignoring the buffer state. However for layers with // hasInputInfo()==false we can use the real visibility state. // We are just using these layers for occlusion detection in // InputDispatcher, and obviously if they aren't visible they can't occlude // anything. const bool visible = hasInputInfo() ? canReceiveInput() : isVisible(); info.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible); info.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !isVisibleForInput()); info.alpha = getAlpha(); fillTouchOcclusionMode(info); Loading
services/surfaceflinger/Layer.h +15 −0 Original line number Diff line number Diff line Loading @@ -371,6 +371,21 @@ public: */ bool canReceiveInput() const; /* * Whether or not the layer should be considered visible for input calculations. */ virtual bool isVisibleForInput() const { // For compatibility reasons we let layers which can receive input // receive input before they have actually submitted a buffer. Because // of this we use canReceiveInput instead of isVisible to check the // policy-visibility, ignoring the buffer state. However for layers with // hasInputInfo()==false we can use the real visibility state. // We are just using these layers for occlusion detection in // InputDispatcher, and obviously if they aren't visible they can't occlude // anything. return hasInputInfo() ? canReceiveInput() : isVisible(); } /* * isProtected - true if the layer may contain protected contents in the * GRALLOC_USAGE_PROTECTED sense. Loading
services/surfaceflinger/SurfaceFlinger.cpp +19 −3 Original line number Diff line number Diff line Loading @@ -3715,17 +3715,33 @@ void SurfaceFlinger::updateInputFlinger() { return; } std::unordered_set<Layer*> visibleLayers; mDrawingState.traverse([&visibleLayers](Layer* layer) { if (layer->isVisibleForInput()) { visibleLayers.insert(layer); } }); bool visibleLayersChanged = false; if (visibleLayers != mVisibleLayers) { visibleLayersChanged = true; mVisibleLayers = std::move(visibleLayers); } BackgroundExecutor::getInstance().sendCallbacks({[updateWindowInfo, windowInfos = std::move(windowInfos), displayInfos = std::move(displayInfos), inputWindowCommands = std::move(mInputWindowCommands), inputFlinger = mInputFlinger, this]() { inputFlinger = mInputFlinger, this, visibleLayersChanged]() { ATRACE_NAME("BackgroundExecutor::updateInputFlinger"); if (updateWindowInfo) { mWindowInfosListenerInvoker ->windowInfosChanged(windowInfos, displayInfos, inputWindowCommands.windowInfosReportedListeners); ->windowInfosChanged(std::move(windowInfos), std::move(displayInfos), std::move( inputWindowCommands.windowInfosReportedListeners), /* forceImmediateCall= */ visibleLayersChanged || !inputWindowCommands.focusRequests.empty()); } else { // If there are listeners but no changes to input windows, call the listeners // immediately. Loading
services/surfaceflinger/SurfaceFlinger.h +5 −0 Original line number Diff line number Diff line Loading @@ -1424,6 +1424,11 @@ private: TransactionHandler mTransactionHandler; display::DisplayMap<ui::LayerStack, frontend::DisplayInfo> mFrontEndDisplayInfos; bool mFrontEndDisplayInfosChanged = false; // Layers visible during the last commit. This set should only be used for testing set equality // and membership. The pointers should not be dereferenced as it's possible the set contains // pointers to freed layers. std::unordered_set<Layer*> mVisibleLayers; }; class SurfaceComposerAIDL : public gui::BnSurfaceComposer { Loading
services/surfaceflinger/WindowInfosListenerInvoker.cpp +86 −40 Original line number Diff line number Diff line Loading @@ -25,20 +25,17 @@ 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) : mCallbacksPending(callbackCount), mWindowInfosReportedListeners(windowInfosReportedListeners) {} using WindowInfosListenerVector = ftl::SmallVector<const sp<IWindowInfosListener>, 3>; struct WindowInfosReportedListenerInvoker : gui::BnWindowInfosReportedListener, IBinder::DeathRecipient { WindowInfosReportedListenerInvoker(WindowInfosListenerVector windowInfosListeners, WindowInfosReportedListenerSet windowInfosReportedListeners) : mCallbacksPending(windowInfosListeners.size()), mWindowInfosListeners(std::move(windowInfosListeners)), 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 @@ -46,6 +43,12 @@ struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowIn 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(); } Loading @@ -54,9 +57,9 @@ struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowIn private: std::atomic<size_t> mCallbacksPending; std::unordered_set<sp<gui::IWindowInfosReportedListener>, SpHash<gui::IWindowInfosReportedListener>> mWindowInfosReportedListeners; static constexpr size_t kStaticCapacity = 3; const WindowInfosListenerVector mWindowInfosListeners; WindowInfosReportedListenerSet mWindowInfosReportedListeners; }; void WindowInfosListenerInvoker::addWindowInfosListener(sp<IWindowInfosListener> listener) { Loading @@ -82,11 +85,13 @@ 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) { ftl::SmallVector<const sp<IWindowInfosListener>, kStaticCapacity> windowInfosListeners; 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)]( WindowInfosReportedListenerSet reportedListeners) mutable { WindowInfosListenerVector windowInfosListeners; { std::scoped_lock lock(mListenersMutex); for (const auto& [_, listener] : mWindowInfosListeners) { Loading @@ -94,26 +99,67 @@ void WindowInfosListenerInvoker::windowInfosChanged( } } auto windowInfosReportedListener = windowInfosReportedListeners.empty() ? nullptr : sp<WindowInfosReportedListener>::make(windowInfosListeners.size(), windowInfosReportedListeners); auto reportedInvoker = sp<WindowInfosReportedListenerInvoker>::make(windowInfosListeners, 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); mReportedListenersDelayed.merge(reportedListeners); return; } auto status = listener->onWindowInfosChanged(windowInfos, displayInfos, windowInfosReportedListener); if (windowInfosReportedListener && !status.isOk()) { windowInfosReportedListener->onWindowInfosReported(); mWindowInfosChangedDelayed = nullptr; reportedListeners.merge(mReportedListenersDelayed); mActiveMessageCount++; } callListeners(std::move(reportedListeners)); } binder::Status WindowInfosListenerInvoker::onWindowInfosReported() { std::function<void(WindowInfosReportedListenerSet)> callListeners; WindowInfosReportedListenerSet reportedListeners; { std::scoped_lock lock{mMessagesMutex}; mActiveMessageCount--; if (!mWindowInfosChangedDelayed || mActiveMessageCount > 0) { return binder::Status::ok(); } mActiveMessageCount++; callListeners = std::move(mWindowInfosChangedDelayed); mWindowInfosChangedDelayed = nullptr; reportedListeners = std::move(mReportedListenersDelayed); mReportedListenersDelayed.clear(); } callListeners(std::move(reportedListeners)); return binder::Status::ok(); } } // namespace android