Loading services/surfaceflinger/SurfaceFlinger.cpp +6 −1 Original line number Diff line number Diff line Loading @@ -3570,6 +3570,10 @@ void SurfaceFlinger::commitTransactionsLocked(uint32_t transactionFlags) { }); } if (transactionFlags & eInputInfoUpdateNeeded) { mUpdateInputInfo = true; } doCommitTransactions(); } Loading Loading @@ -7561,8 +7565,9 @@ void SurfaceFlinger::onActiveDisplayChangedLocked(const DisplayDevice* inactiveD } status_t SurfaceFlinger::addWindowInfosListener( const sp<IWindowInfosListener>& windowInfosListener) const { const sp<IWindowInfosListener>& windowInfosListener) { mWindowInfosListenerInvoker->addWindowInfosListener(windowInfosListener); setTransactionFlags(eInputInfoUpdateNeeded); return NO_ERROR; } Loading services/surfaceflinger/SurfaceFlinger.h +3 −2 Original line number Diff line number Diff line Loading @@ -162,7 +162,8 @@ enum { eDisplayTransactionNeeded = 0x04, eTransformHintUpdateNeeded = 0x08, eTransactionFlushNeeded = 0x10, eTransactionMask = 0x1f, eInputInfoUpdateNeeded = 0x20, eTransactionMask = 0x3f, }; // Latch Unsignaled buffer behaviours Loading Loading @@ -618,7 +619,7 @@ private: status_t getMaxAcquiredBufferCount(int* buffers) const; status_t addWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener) const; status_t addWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener); status_t removeWindowInfosListener( const sp<gui::IWindowInfosListener>& windowInfosListener) const; Loading services/surfaceflinger/WindowInfosListenerInvoker.cpp +0 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ #include <ftl/small_vector.h> #include <gui/ISurfaceComposer.h> #include "SurfaceFlinger.h" #include "WindowInfosListenerInvoker.h" namespace android { Loading services/surfaceflinger/WindowInfosListenerInvoker.h +2 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #pragma once #include <unordered_set> #include <android/gui/BnWindowInfosReportedListener.h> #include <android/gui/IWindowInfosListener.h> #include <android/gui/IWindowInfosReportedListener.h> Loading Loading @@ -49,8 +51,6 @@ private: static constexpr size_t kStaticCapacity = 3; ftl::SmallMap<wp<IBinder>, const sp<gui::IWindowInfosListener>, kStaticCapacity> mWindowInfosListeners GUARDED_BY(mListenersMutex); sp<gui::IWindowInfosReportedListener> mWindowInfosReportedListener; }; } // namespace android services/surfaceflinger/tests/WindowInfosListener_test.cpp +49 −38 Original line number Diff line number Diff line Loading @@ -18,61 +18,61 @@ #include <gui/SurfaceComposerClient.h> #include <private/android_filesystem_config.h> #include <future> #include "utils/TransactionUtils.h" namespace android { using Transaction = SurfaceComposerClient::Transaction; using gui::DisplayInfo; using gui::WindowInfo; using WindowInfosPredicate = std::function<bool(const std::vector<WindowInfo>&)>; class WindowInfosListenerTest : public ::testing::Test { protected: void SetUp() override { seteuid(AID_SYSTEM); mClient = sp<SurfaceComposerClient>::make(); mWindowInfosListener = sp<SyncWindowInfosListener>::make(); mClient->addWindowInfosListener(mWindowInfosListener); } void TearDown() override { mClient->removeWindowInfosListener(mWindowInfosListener); seteuid(AID_ROOT); } void TearDown() override { seteuid(AID_ROOT); } struct SyncWindowInfosListener : public gui::WindowInfosListener { struct WindowInfosListener : public gui::WindowInfosListener { public: WindowInfosListener(WindowInfosPredicate predicate, std::promise<void>& promise) : mPredicate(std::move(predicate)), mPromise(promise) {} void onWindowInfosChanged(const std::vector<WindowInfo>& windowInfos, const std::vector<DisplayInfo>&) override { windowInfosPromise.set_value(windowInfos); if (mPredicate(windowInfos)) { mPromise.set_value(); } std::vector<WindowInfo> waitForWindowInfos() { std::future<std::vector<WindowInfo>> windowInfosFuture = windowInfosPromise.get_future(); std::vector<WindowInfo> windowInfos = windowInfosFuture.get(); windowInfosPromise = std::promise<std::vector<WindowInfo>>(); return windowInfos; } private: std::promise<std::vector<WindowInfo>> windowInfosPromise; WindowInfosPredicate mPredicate; std::promise<void>& mPromise; }; sp<SurfaceComposerClient> mClient; sp<SyncWindowInfosListener> mWindowInfosListener; bool waitForWindowInfosPredicate(WindowInfosPredicate predicate) { std::promise<void> promise; auto listener = sp<WindowInfosListener>::make(std::move(predicate), promise); mClient->addWindowInfosListener(listener); auto future = promise.get_future(); bool satisfied = future.wait_for(std::chrono::seconds{1}) == std::future_status::ready; mClient->removeWindowInfosListener(listener); return satisfied; } }; std::optional<WindowInfo> findMatchingWindowInfo(WindowInfo targetWindowInfo, std::vector<WindowInfo> windowInfos) { std::optional<WindowInfo> foundWindowInfo = std::nullopt; for (WindowInfo windowInfo : windowInfos) { if (windowInfo.token == targetWindowInfo.token) { foundWindowInfo = std::make_optional<>(windowInfo); break; return windowInfo; } } return foundWindowInfo; return std::nullopt; } TEST_F(WindowInfosListenerTest, WindowInfoAddedAndRemoved) { Loading @@ -92,15 +92,17 @@ TEST_F(WindowInfosListenerTest, WindowInfoAddedAndRemoved) { .setInputWindowInfo(surfaceControl, windowInfo) .apply(); std::vector<WindowInfo> windowInfos = mWindowInfosListener->waitForWindowInfos(); std::optional<WindowInfo> foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos); ASSERT_NE(std::nullopt, foundWindowInfo); auto windowPresent = [&](const std::vector<WindowInfo>& windowInfos) { return findMatchingWindowInfo(windowInfo, windowInfos).has_value(); }; ASSERT_TRUE(waitForWindowInfosPredicate(windowPresent)); Transaction().reparent(surfaceControl, nullptr).apply(); windowInfos = mWindowInfosListener->waitForWindowInfos(); foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos); ASSERT_EQ(std::nullopt, foundWindowInfo); auto windowNotPresent = [&](const std::vector<WindowInfo>& windowInfos) { return !findMatchingWindowInfo(windowInfo, windowInfos).has_value(); }; ASSERT_TRUE(waitForWindowInfosPredicate(windowNotPresent)); } TEST_F(WindowInfosListenerTest, WindowInfoChanged) { Loading @@ -121,19 +123,28 @@ TEST_F(WindowInfosListenerTest, WindowInfoChanged) { .setInputWindowInfo(surfaceControl, windowInfo) .apply(); std::vector<WindowInfo> windowInfos = mWindowInfosListener->waitForWindowInfos(); std::optional<WindowInfo> foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos); ASSERT_NE(std::nullopt, foundWindowInfo); ASSERT_TRUE(foundWindowInfo->touchableRegion.isEmpty()); auto windowIsPresentAndTouchableRegionEmpty = [&](const std::vector<WindowInfo>& windowInfos) { auto foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos); if (!foundWindowInfo) { return false; } return foundWindowInfo->touchableRegion.isEmpty(); }; ASSERT_TRUE(waitForWindowInfosPredicate(windowIsPresentAndTouchableRegionEmpty)); Rect touchableRegions(0, 0, 50, 50); windowInfo.addTouchableRegion(Rect(0, 0, 50, 50)); Transaction().setInputWindowInfo(surfaceControl, windowInfo).apply(); windowInfos = mWindowInfosListener->waitForWindowInfos(); foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos); ASSERT_NE(std::nullopt, foundWindowInfo); ASSERT_TRUE(foundWindowInfo->touchableRegion.hasSameRects(windowInfo.touchableRegion)); auto windowIsPresentAndTouchableRegionMatches = [&](const std::vector<WindowInfo>& windowInfos) { auto foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos); if (!foundWindowInfo) { return false; } return foundWindowInfo->touchableRegion.hasSameRects(windowInfo.touchableRegion); }; ASSERT_TRUE(waitForWindowInfosPredicate(windowIsPresentAndTouchableRegionMatches)); } } // namespace android Loading
services/surfaceflinger/SurfaceFlinger.cpp +6 −1 Original line number Diff line number Diff line Loading @@ -3570,6 +3570,10 @@ void SurfaceFlinger::commitTransactionsLocked(uint32_t transactionFlags) { }); } if (transactionFlags & eInputInfoUpdateNeeded) { mUpdateInputInfo = true; } doCommitTransactions(); } Loading Loading @@ -7561,8 +7565,9 @@ void SurfaceFlinger::onActiveDisplayChangedLocked(const DisplayDevice* inactiveD } status_t SurfaceFlinger::addWindowInfosListener( const sp<IWindowInfosListener>& windowInfosListener) const { const sp<IWindowInfosListener>& windowInfosListener) { mWindowInfosListenerInvoker->addWindowInfosListener(windowInfosListener); setTransactionFlags(eInputInfoUpdateNeeded); return NO_ERROR; } Loading
services/surfaceflinger/SurfaceFlinger.h +3 −2 Original line number Diff line number Diff line Loading @@ -162,7 +162,8 @@ enum { eDisplayTransactionNeeded = 0x04, eTransformHintUpdateNeeded = 0x08, eTransactionFlushNeeded = 0x10, eTransactionMask = 0x1f, eInputInfoUpdateNeeded = 0x20, eTransactionMask = 0x3f, }; // Latch Unsignaled buffer behaviours Loading Loading @@ -618,7 +619,7 @@ private: status_t getMaxAcquiredBufferCount(int* buffers) const; status_t addWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener) const; status_t addWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener); status_t removeWindowInfosListener( const sp<gui::IWindowInfosListener>& windowInfosListener) const; Loading
services/surfaceflinger/WindowInfosListenerInvoker.cpp +0 −1 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ #include <ftl/small_vector.h> #include <gui/ISurfaceComposer.h> #include "SurfaceFlinger.h" #include "WindowInfosListenerInvoker.h" namespace android { Loading
services/surfaceflinger/WindowInfosListenerInvoker.h +2 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #pragma once #include <unordered_set> #include <android/gui/BnWindowInfosReportedListener.h> #include <android/gui/IWindowInfosListener.h> #include <android/gui/IWindowInfosReportedListener.h> Loading Loading @@ -49,8 +51,6 @@ private: static constexpr size_t kStaticCapacity = 3; ftl::SmallMap<wp<IBinder>, const sp<gui::IWindowInfosListener>, kStaticCapacity> mWindowInfosListeners GUARDED_BY(mListenersMutex); sp<gui::IWindowInfosReportedListener> mWindowInfosReportedListener; }; } // namespace android
services/surfaceflinger/tests/WindowInfosListener_test.cpp +49 −38 Original line number Diff line number Diff line Loading @@ -18,61 +18,61 @@ #include <gui/SurfaceComposerClient.h> #include <private/android_filesystem_config.h> #include <future> #include "utils/TransactionUtils.h" namespace android { using Transaction = SurfaceComposerClient::Transaction; using gui::DisplayInfo; using gui::WindowInfo; using WindowInfosPredicate = std::function<bool(const std::vector<WindowInfo>&)>; class WindowInfosListenerTest : public ::testing::Test { protected: void SetUp() override { seteuid(AID_SYSTEM); mClient = sp<SurfaceComposerClient>::make(); mWindowInfosListener = sp<SyncWindowInfosListener>::make(); mClient->addWindowInfosListener(mWindowInfosListener); } void TearDown() override { mClient->removeWindowInfosListener(mWindowInfosListener); seteuid(AID_ROOT); } void TearDown() override { seteuid(AID_ROOT); } struct SyncWindowInfosListener : public gui::WindowInfosListener { struct WindowInfosListener : public gui::WindowInfosListener { public: WindowInfosListener(WindowInfosPredicate predicate, std::promise<void>& promise) : mPredicate(std::move(predicate)), mPromise(promise) {} void onWindowInfosChanged(const std::vector<WindowInfo>& windowInfos, const std::vector<DisplayInfo>&) override { windowInfosPromise.set_value(windowInfos); if (mPredicate(windowInfos)) { mPromise.set_value(); } std::vector<WindowInfo> waitForWindowInfos() { std::future<std::vector<WindowInfo>> windowInfosFuture = windowInfosPromise.get_future(); std::vector<WindowInfo> windowInfos = windowInfosFuture.get(); windowInfosPromise = std::promise<std::vector<WindowInfo>>(); return windowInfos; } private: std::promise<std::vector<WindowInfo>> windowInfosPromise; WindowInfosPredicate mPredicate; std::promise<void>& mPromise; }; sp<SurfaceComposerClient> mClient; sp<SyncWindowInfosListener> mWindowInfosListener; bool waitForWindowInfosPredicate(WindowInfosPredicate predicate) { std::promise<void> promise; auto listener = sp<WindowInfosListener>::make(std::move(predicate), promise); mClient->addWindowInfosListener(listener); auto future = promise.get_future(); bool satisfied = future.wait_for(std::chrono::seconds{1}) == std::future_status::ready; mClient->removeWindowInfosListener(listener); return satisfied; } }; std::optional<WindowInfo> findMatchingWindowInfo(WindowInfo targetWindowInfo, std::vector<WindowInfo> windowInfos) { std::optional<WindowInfo> foundWindowInfo = std::nullopt; for (WindowInfo windowInfo : windowInfos) { if (windowInfo.token == targetWindowInfo.token) { foundWindowInfo = std::make_optional<>(windowInfo); break; return windowInfo; } } return foundWindowInfo; return std::nullopt; } TEST_F(WindowInfosListenerTest, WindowInfoAddedAndRemoved) { Loading @@ -92,15 +92,17 @@ TEST_F(WindowInfosListenerTest, WindowInfoAddedAndRemoved) { .setInputWindowInfo(surfaceControl, windowInfo) .apply(); std::vector<WindowInfo> windowInfos = mWindowInfosListener->waitForWindowInfos(); std::optional<WindowInfo> foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos); ASSERT_NE(std::nullopt, foundWindowInfo); auto windowPresent = [&](const std::vector<WindowInfo>& windowInfos) { return findMatchingWindowInfo(windowInfo, windowInfos).has_value(); }; ASSERT_TRUE(waitForWindowInfosPredicate(windowPresent)); Transaction().reparent(surfaceControl, nullptr).apply(); windowInfos = mWindowInfosListener->waitForWindowInfos(); foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos); ASSERT_EQ(std::nullopt, foundWindowInfo); auto windowNotPresent = [&](const std::vector<WindowInfo>& windowInfos) { return !findMatchingWindowInfo(windowInfo, windowInfos).has_value(); }; ASSERT_TRUE(waitForWindowInfosPredicate(windowNotPresent)); } TEST_F(WindowInfosListenerTest, WindowInfoChanged) { Loading @@ -121,19 +123,28 @@ TEST_F(WindowInfosListenerTest, WindowInfoChanged) { .setInputWindowInfo(surfaceControl, windowInfo) .apply(); std::vector<WindowInfo> windowInfos = mWindowInfosListener->waitForWindowInfos(); std::optional<WindowInfo> foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos); ASSERT_NE(std::nullopt, foundWindowInfo); ASSERT_TRUE(foundWindowInfo->touchableRegion.isEmpty()); auto windowIsPresentAndTouchableRegionEmpty = [&](const std::vector<WindowInfo>& windowInfos) { auto foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos); if (!foundWindowInfo) { return false; } return foundWindowInfo->touchableRegion.isEmpty(); }; ASSERT_TRUE(waitForWindowInfosPredicate(windowIsPresentAndTouchableRegionEmpty)); Rect touchableRegions(0, 0, 50, 50); windowInfo.addTouchableRegion(Rect(0, 0, 50, 50)); Transaction().setInputWindowInfo(surfaceControl, windowInfo).apply(); windowInfos = mWindowInfosListener->waitForWindowInfos(); foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos); ASSERT_NE(std::nullopt, foundWindowInfo); ASSERT_TRUE(foundWindowInfo->touchableRegion.hasSameRects(windowInfo.touchableRegion)); auto windowIsPresentAndTouchableRegionMatches = [&](const std::vector<WindowInfo>& windowInfos) { auto foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos); if (!foundWindowInfo) { return false; } return foundWindowInfo->touchableRegion.hasSameRects(windowInfo.touchableRegion); }; ASSERT_TRUE(waitForWindowInfosPredicate(windowIsPresentAndTouchableRegionMatches)); } } // namespace android