Loading services/surfaceflinger/SurfaceFlinger.cpp +12 −12 Original line number Original line Diff line number Diff line Loading @@ -2730,12 +2730,12 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { } } const auto displayId = info->id; const auto displayId = info->id; const auto it = mPhysicalDisplayTokens.find(displayId); const auto token = mPhysicalDisplayTokens.get(displayId); if (event.connection == hal::Connection::CONNECTED) { if (event.connection == hal::Connection::CONNECTED) { auto [supportedModes, activeMode] = loadDisplayModes(displayId); auto [supportedModes, activeMode] = loadDisplayModes(displayId); if (it == mPhysicalDisplayTokens.end()) { if (!token) { ALOGV("Creating display %s", to_string(displayId).c_str()); ALOGV("Creating display %s", to_string(displayId).c_str()); DisplayDeviceState state; DisplayDeviceState state; Loading @@ -2750,14 +2750,13 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { sp<IBinder> token = new BBinder(); sp<IBinder> token = new BBinder(); mCurrentState.displays.add(token, state); mCurrentState.displays.add(token, state); mPhysicalDisplayTokens.emplace(displayId, std::move(token)); mPhysicalDisplayTokens.try_emplace(displayId, std::move(token)); mInterceptor->saveDisplayCreation(state); mInterceptor->saveDisplayCreation(state); } else { } else { ALOGV("Recreating display %s", to_string(displayId).c_str()); ALOGV("Recreating display %s", to_string(displayId).c_str()); const auto token = it->second; auto& state = mCurrentState.displays.editValueFor(token->get()); auto& state = mCurrentState.displays.editValueFor(token); state.sequenceId = DisplayDeviceState{}.sequenceId; // Generate new sequenceId. state.sequenceId = DisplayDeviceState{}.sequenceId; // Generate new sequenceId state.physical->supportedModes = std::move(supportedModes); state.physical->supportedModes = std::move(supportedModes); state.physical->activeMode = std::move(activeMode); state.physical->activeMode = std::move(activeMode); if (getHwComposer().updatesDeviceProductInfoOnHotplugReconnect()) { if (getHwComposer().updatesDeviceProductInfoOnHotplugReconnect()) { Loading @@ -2767,13 +2766,13 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { } else { } else { ALOGV("Removing display %s", to_string(displayId).c_str()); ALOGV("Removing display %s", to_string(displayId).c_str()); const ssize_t index = mCurrentState.displays.indexOfKey(it->second); if (const ssize_t index = mCurrentState.displays.indexOfKey(token->get()); index >= 0) { if (index >= 0) { const DisplayDeviceState& state = mCurrentState.displays.valueAt(index); const DisplayDeviceState& state = mCurrentState.displays.valueAt(index); mInterceptor->saveDisplayDeletion(state.sequenceId); mInterceptor->saveDisplayDeletion(state.sequenceId); mCurrentState.displays.removeItemsAt(index); mCurrentState.displays.removeItemsAt(index); } } mPhysicalDisplayTokens.erase(it); mPhysicalDisplayTokens.erase(displayId); } } processDisplayChangesLocked(); processDisplayChangesLocked(); Loading Loading @@ -2954,15 +2953,16 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, } } LOG_FATAL_IF(!displaySurface); LOG_FATAL_IF(!displaySurface); const auto display = setupNewDisplayDeviceInternal(displayToken, std::move(compositionDisplay), auto display = setupNewDisplayDeviceInternal(displayToken, std::move(compositionDisplay), state, state, displaySurface, producer); displaySurface, producer); mDisplays.emplace(displayToken, display); if (display->isPrimary()) { if (display->isPrimary()) { initScheduler(display); initScheduler(display); } } if (!state.isVirtual()) { if (!state.isVirtual()) { dispatchDisplayHotplugEvent(display->getPhysicalId(), true); dispatchDisplayHotplugEvent(display->getPhysicalId(), true); } } mDisplays.try_emplace(displayToken, std::move(display)); } } void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { Loading services/surfaceflinger/SurfaceFlinger.h +15 −12 Original line number Original line Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <android/gui/DisplayState.h> #include <android/gui/DisplayState.h> #include <cutils/atomic.h> #include <cutils/atomic.h> #include <cutils/compiler.h> #include <cutils/compiler.h> #include <ftl/small_map.h> #include <gui/BufferQueue.h> #include <gui/BufferQueue.h> #include <gui/FrameTimestamps.h> #include <gui/FrameTimestamps.h> #include <gui/ISurfaceComposer.h> #include <gui/ISurfaceComposer.h> Loading Loading @@ -905,8 +906,8 @@ private: } } sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) REQUIRES(mStateLock) { sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) REQUIRES(mStateLock) { const auto it = mDisplays.find(displayToken); const sp<DisplayDevice> nullDisplay; return it == mDisplays.end() ? nullptr : it->second; return mDisplays.get(displayToken).value_or(std::cref(nullDisplay)); } } sp<const DisplayDevice> getDisplayDeviceLocked(PhysicalDisplayId id) const sp<const DisplayDevice> getDisplayDeviceLocked(PhysicalDisplayId id) const Loading Loading @@ -1051,8 +1052,8 @@ private: */ */ sp<IBinder> getPhysicalDisplayTokenLocked(PhysicalDisplayId displayId) const sp<IBinder> getPhysicalDisplayTokenLocked(PhysicalDisplayId displayId) const REQUIRES(mStateLock) { REQUIRES(mStateLock) { const auto it = mPhysicalDisplayTokens.find(displayId); const sp<IBinder> nullToken; return it != mPhysicalDisplayTokens.end() ? it->second : nullptr; return mPhysicalDisplayTokens.get(displayId).value_or(std::cref(nullToken)); } } std::optional<PhysicalDisplayId> getPhysicalDisplayIdLocked( std::optional<PhysicalDisplayId> getPhysicalDisplayIdLocked( Loading Loading @@ -1247,10 +1248,14 @@ private: std::vector<HotplugEvent> mPendingHotplugEvents GUARDED_BY(mStateLock); std::vector<HotplugEvent> mPendingHotplugEvents GUARDED_BY(mStateLock); // this may only be written from the main thread with mStateLock held // Displays are composited in `mDisplays` order. Internal displays are inserted at boot and // it may be read from other threads with mStateLock held // never removed, so take precedence over external and virtual displays. std::map<wp<IBinder>, sp<DisplayDevice>> mDisplays GUARDED_BY(mStateLock); // std::unordered_map<PhysicalDisplayId, sp<IBinder>> mPhysicalDisplayTokens // The static capacities were chosen to exceed a typical number of physical/virtual displays. // // May be read from any thread, but must only be written from the main thread. ftl::SmallMap<wp<IBinder>, const sp<DisplayDevice>, 5> mDisplays GUARDED_BY(mStateLock); ftl::SmallMap<PhysicalDisplayId, const sp<IBinder>, 3> mPhysicalDisplayTokens GUARDED_BY(mStateLock); GUARDED_BY(mStateLock); struct { struct { Loading Loading @@ -1423,10 +1428,8 @@ private: std::atomic<ui::Transform::RotationFlags> mActiveDisplayTransformHint; std::atomic<ui::Transform::RotationFlags> mActiveDisplayTransformHint; bool isRefreshRateOverlayEnabled() const REQUIRES(mStateLock) { bool isRefreshRateOverlayEnabled() const REQUIRES(mStateLock) { return std::any_of(mDisplays.begin(), mDisplays.end(), return hasDisplay( [](std::pair<wp<IBinder>, sp<DisplayDevice>> display) { [](const auto& display) { return display.isRefreshRateOverlayEnabled(); }); return display.second->isRefreshRateOverlayEnabled(); }); } } wp<IBinder> mActiveDisplayToken GUARDED_BY(mStateLock); wp<IBinder> mActiveDisplayToken GUARDED_BY(mStateLock); Loading services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +19 −16 Original line number Original line Diff line number Diff line Loading @@ -165,36 +165,39 @@ sp<DisplayDevice> DisplayTransactionTest::injectDefaultInternalDisplay( return displayDevice; return displayDevice; } } bool DisplayTransactionTest::hasPhysicalHwcDisplay(HWDisplayId hwcDisplayId) { bool DisplayTransactionTest::hasPhysicalHwcDisplay(HWDisplayId hwcDisplayId) const { return mFlinger.mutableHwcPhysicalDisplayIdMap().count(hwcDisplayId) == 1; return mFlinger.hwcPhysicalDisplayIdMap().count(hwcDisplayId) == 1; } } bool DisplayTransactionTest::hasTransactionFlagSet(int flag) { bool DisplayTransactionTest::hasTransactionFlagSet(int32_t flag) const { return mFlinger.mutableTransactionFlags() & flag; return mFlinger.transactionFlags() & flag; } } bool DisplayTransactionTest::hasDisplayDevice(sp<IBinder> displayToken) { bool DisplayTransactionTest::hasDisplayDevice(const sp<IBinder>& displayToken) const { return mFlinger.mutableDisplays().count(displayToken) == 1; return mFlinger.displays().contains(displayToken); } } sp<DisplayDevice> DisplayTransactionTest::getDisplayDevice(sp<IBinder> displayToken) { const DisplayDevice& DisplayTransactionTest::getDisplayDevice( return mFlinger.mutableDisplays()[displayToken]; const sp<IBinder>& displayToken) const { return *mFlinger.displays().get(displayToken)->get(); } } bool DisplayTransactionTest::hasCurrentDisplayState(sp<IBinder> displayToken) { bool DisplayTransactionTest::hasCurrentDisplayState(const sp<IBinder>& displayToken) const { return mFlinger.mutableCurrentState().displays.indexOfKey(displayToken) >= 0; return mFlinger.currentState().displays.indexOfKey(displayToken) >= 0; } } const DisplayDeviceState& DisplayTransactionTest::getCurrentDisplayState(sp<IBinder> displayToken) { const DisplayDeviceState& DisplayTransactionTest::getCurrentDisplayState( return mFlinger.mutableCurrentState().displays.valueFor(displayToken); const sp<IBinder>& displayToken) const { return mFlinger.currentState().displays.valueFor(displayToken); } } bool DisplayTransactionTest::hasDrawingDisplayState(sp<IBinder> displayToken) { bool DisplayTransactionTest::hasDrawingDisplayState(const sp<IBinder>& displayToken) const { return mFlinger.mutableDrawingState().displays.indexOfKey(displayToken) >= 0; return mFlinger.drawingState().displays.indexOfKey(displayToken) >= 0; } } const DisplayDeviceState& DisplayTransactionTest::getDrawingDisplayState(sp<IBinder> displayToken) { const DisplayDeviceState& DisplayTransactionTest::getDrawingDisplayState( return mFlinger.mutableDrawingState().displays.valueFor(displayToken); const sp<IBinder>& displayToken) const { return mFlinger.drawingState().displays.valueFor(displayToken); } } } // namespace android } // namespace android services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h +11 −8 Original line number Original line Diff line number Diff line Loading @@ -95,14 +95,17 @@ public: // -------------------------------------------------------------------- // -------------------------------------------------------------------- // Postcondition helpers // Postcondition helpers bool hasPhysicalHwcDisplay(hal::HWDisplayId hwcDisplayId); bool hasPhysicalHwcDisplay(hal::HWDisplayId) const; bool hasTransactionFlagSet(int flag); bool hasTransactionFlagSet(int32_t flag) const; bool hasDisplayDevice(sp<IBinder> displayToken); sp<DisplayDevice> getDisplayDevice(sp<IBinder> displayToken); bool hasDisplayDevice(const sp<IBinder>& displayToken) const; bool hasCurrentDisplayState(sp<IBinder> displayToken); const DisplayDevice& getDisplayDevice(const sp<IBinder>& displayToken) const; const DisplayDeviceState& getCurrentDisplayState(sp<IBinder> displayToken); bool hasDrawingDisplayState(sp<IBinder> displayToken); bool hasCurrentDisplayState(const sp<IBinder>& displayToken) const; const DisplayDeviceState& getDrawingDisplayState(sp<IBinder> displayToken); const DisplayDeviceState& getCurrentDisplayState(const sp<IBinder>& displayToken) const; bool hasDrawingDisplayState(const sp<IBinder>& displayToken) const; const DisplayDeviceState& getDrawingDisplayState(const sp<IBinder>& displayToken) const; // -------------------------------------------------------------------- // -------------------------------------------------------------------- // Test instances // Test instances Loading services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp +16 −13 Original line number Original line Diff line number Diff line Loading @@ -107,9 +107,10 @@ template <typename Case> void DisplayTransactionCommitTest::verifyDisplayIsConnected(const sp<IBinder>& displayToken) { void DisplayTransactionCommitTest::verifyDisplayIsConnected(const sp<IBinder>& displayToken) { // The display device should have been set up in the list of displays. // The display device should have been set up in the list of displays. ASSERT_TRUE(hasDisplayDevice(displayToken)); ASSERT_TRUE(hasDisplayDevice(displayToken)); const auto& device = getDisplayDevice(displayToken); const auto& display = getDisplayDevice(displayToken); EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure()); EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary()); EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), display.isSecure()); EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), display.isPrimary()); std::optional<DisplayDeviceState::Physical> expectedPhysical; std::optional<DisplayDeviceState::Physical> expectedPhysical; if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) { if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) { Loading Loading @@ -143,10 +144,11 @@ void DisplayTransactionCommitTest::verifyPhysicalDisplayIsConnected() { // SF should have a display token. // SF should have a display token. const auto displayId = Case::Display::DISPLAY_ID::get(); const auto displayId = Case::Display::DISPLAY_ID::get(); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_EQ(mFlinger.mutablePhysicalDisplayTokens().count(displayId), 1); auto& displayToken = mFlinger.mutablePhysicalDisplayTokens()[displayId]; verifyDisplayIsConnected<Case>(displayToken); const auto displayTokenOpt = mFlinger.mutablePhysicalDisplayTokens().get(displayId); ASSERT_TRUE(displayTokenOpt); verifyDisplayIsConnected<Case>(displayTokenOpt->get()); } } void DisplayTransactionCommitTest::verifyDisplayIsNotConnected(const sp<IBinder>& displayToken) { void DisplayTransactionCommitTest::verifyDisplayIsNotConnected(const sp<IBinder>& displayToken) { Loading Loading @@ -248,9 +250,9 @@ void DisplayTransactionCommitTest::processesHotplugDisconnectCommon() { // SF should not have a display token. // SF should not have a display token. const auto displayId = Case::Display::DISPLAY_ID::get(); const auto displayId = Case::Display::DISPLAY_ID::get(); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(displayId) == 0); ASSERT_FALSE(mFlinger.mutablePhysicalDisplayTokens().contains(displayId)); // The existing token should have been removed // The existing token should have been removed. verifyDisplayIsNotConnected(existing.token()); verifyDisplayIsNotConnected(existing.token()); } } Loading Loading @@ -330,7 +332,7 @@ TEST_F(DisplayTransactionCommitTest, processesHotplugConnectThenDisconnectPrimar // SF should not have a display token. // SF should not have a display token. const auto displayId = Case::Display::DISPLAY_ID::get(); const auto displayId = Case::Display::DISPLAY_ID::get(); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(displayId) == 0); ASSERT_FALSE(mFlinger.mutablePhysicalDisplayTokens().contains(displayId)); }(), }(), testing::KilledBySignal(SIGABRT), "Primary display cannot be disconnected."); testing::KilledBySignal(SIGABRT), "Primary display cannot be disconnected."); } } Loading Loading @@ -369,15 +371,16 @@ TEST_F(DisplayTransactionCommitTest, processesHotplugDisconnectThenConnectPrimar // -------------------------------------------------------------------- // -------------------------------------------------------------------- // Postconditions // Postconditions // The existing token should have been removed // The existing token should have been removed. verifyDisplayIsNotConnected(existing.token()); verifyDisplayIsNotConnected(existing.token()); const auto displayId = Case::Display::DISPLAY_ID::get(); const auto displayId = Case::Display::DISPLAY_ID::get(); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(displayId) == 1); EXPECT_NE(existing.token(), mFlinger.mutablePhysicalDisplayTokens()[displayId]); // A new display should be connected in its place const auto displayTokenOpt = mFlinger.mutablePhysicalDisplayTokens().get(displayId); ASSERT_TRUE(displayTokenOpt); EXPECT_NE(existing.token(), displayTokenOpt->get()); // A new display should be connected in its place. verifyPhysicalDisplayIsConnected<Case>(); verifyPhysicalDisplayIsConnected<Case>(); // -------------------------------------------------------------------- // -------------------------------------------------------------------- Loading Loading
services/surfaceflinger/SurfaceFlinger.cpp +12 −12 Original line number Original line Diff line number Diff line Loading @@ -2730,12 +2730,12 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { } } const auto displayId = info->id; const auto displayId = info->id; const auto it = mPhysicalDisplayTokens.find(displayId); const auto token = mPhysicalDisplayTokens.get(displayId); if (event.connection == hal::Connection::CONNECTED) { if (event.connection == hal::Connection::CONNECTED) { auto [supportedModes, activeMode] = loadDisplayModes(displayId); auto [supportedModes, activeMode] = loadDisplayModes(displayId); if (it == mPhysicalDisplayTokens.end()) { if (!token) { ALOGV("Creating display %s", to_string(displayId).c_str()); ALOGV("Creating display %s", to_string(displayId).c_str()); DisplayDeviceState state; DisplayDeviceState state; Loading @@ -2750,14 +2750,13 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { sp<IBinder> token = new BBinder(); sp<IBinder> token = new BBinder(); mCurrentState.displays.add(token, state); mCurrentState.displays.add(token, state); mPhysicalDisplayTokens.emplace(displayId, std::move(token)); mPhysicalDisplayTokens.try_emplace(displayId, std::move(token)); mInterceptor->saveDisplayCreation(state); mInterceptor->saveDisplayCreation(state); } else { } else { ALOGV("Recreating display %s", to_string(displayId).c_str()); ALOGV("Recreating display %s", to_string(displayId).c_str()); const auto token = it->second; auto& state = mCurrentState.displays.editValueFor(token->get()); auto& state = mCurrentState.displays.editValueFor(token); state.sequenceId = DisplayDeviceState{}.sequenceId; // Generate new sequenceId. state.sequenceId = DisplayDeviceState{}.sequenceId; // Generate new sequenceId state.physical->supportedModes = std::move(supportedModes); state.physical->supportedModes = std::move(supportedModes); state.physical->activeMode = std::move(activeMode); state.physical->activeMode = std::move(activeMode); if (getHwComposer().updatesDeviceProductInfoOnHotplugReconnect()) { if (getHwComposer().updatesDeviceProductInfoOnHotplugReconnect()) { Loading @@ -2767,13 +2766,13 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { } else { } else { ALOGV("Removing display %s", to_string(displayId).c_str()); ALOGV("Removing display %s", to_string(displayId).c_str()); const ssize_t index = mCurrentState.displays.indexOfKey(it->second); if (const ssize_t index = mCurrentState.displays.indexOfKey(token->get()); index >= 0) { if (index >= 0) { const DisplayDeviceState& state = mCurrentState.displays.valueAt(index); const DisplayDeviceState& state = mCurrentState.displays.valueAt(index); mInterceptor->saveDisplayDeletion(state.sequenceId); mInterceptor->saveDisplayDeletion(state.sequenceId); mCurrentState.displays.removeItemsAt(index); mCurrentState.displays.removeItemsAt(index); } } mPhysicalDisplayTokens.erase(it); mPhysicalDisplayTokens.erase(displayId); } } processDisplayChangesLocked(); processDisplayChangesLocked(); Loading Loading @@ -2954,15 +2953,16 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, } } LOG_FATAL_IF(!displaySurface); LOG_FATAL_IF(!displaySurface); const auto display = setupNewDisplayDeviceInternal(displayToken, std::move(compositionDisplay), auto display = setupNewDisplayDeviceInternal(displayToken, std::move(compositionDisplay), state, state, displaySurface, producer); displaySurface, producer); mDisplays.emplace(displayToken, display); if (display->isPrimary()) { if (display->isPrimary()) { initScheduler(display); initScheduler(display); } } if (!state.isVirtual()) { if (!state.isVirtual()) { dispatchDisplayHotplugEvent(display->getPhysicalId(), true); dispatchDisplayHotplugEvent(display->getPhysicalId(), true); } } mDisplays.try_emplace(displayToken, std::move(display)); } } void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { Loading
services/surfaceflinger/SurfaceFlinger.h +15 −12 Original line number Original line Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <android/gui/DisplayState.h> #include <android/gui/DisplayState.h> #include <cutils/atomic.h> #include <cutils/atomic.h> #include <cutils/compiler.h> #include <cutils/compiler.h> #include <ftl/small_map.h> #include <gui/BufferQueue.h> #include <gui/BufferQueue.h> #include <gui/FrameTimestamps.h> #include <gui/FrameTimestamps.h> #include <gui/ISurfaceComposer.h> #include <gui/ISurfaceComposer.h> Loading Loading @@ -905,8 +906,8 @@ private: } } sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) REQUIRES(mStateLock) { sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) REQUIRES(mStateLock) { const auto it = mDisplays.find(displayToken); const sp<DisplayDevice> nullDisplay; return it == mDisplays.end() ? nullptr : it->second; return mDisplays.get(displayToken).value_or(std::cref(nullDisplay)); } } sp<const DisplayDevice> getDisplayDeviceLocked(PhysicalDisplayId id) const sp<const DisplayDevice> getDisplayDeviceLocked(PhysicalDisplayId id) const Loading Loading @@ -1051,8 +1052,8 @@ private: */ */ sp<IBinder> getPhysicalDisplayTokenLocked(PhysicalDisplayId displayId) const sp<IBinder> getPhysicalDisplayTokenLocked(PhysicalDisplayId displayId) const REQUIRES(mStateLock) { REQUIRES(mStateLock) { const auto it = mPhysicalDisplayTokens.find(displayId); const sp<IBinder> nullToken; return it != mPhysicalDisplayTokens.end() ? it->second : nullptr; return mPhysicalDisplayTokens.get(displayId).value_or(std::cref(nullToken)); } } std::optional<PhysicalDisplayId> getPhysicalDisplayIdLocked( std::optional<PhysicalDisplayId> getPhysicalDisplayIdLocked( Loading Loading @@ -1247,10 +1248,14 @@ private: std::vector<HotplugEvent> mPendingHotplugEvents GUARDED_BY(mStateLock); std::vector<HotplugEvent> mPendingHotplugEvents GUARDED_BY(mStateLock); // this may only be written from the main thread with mStateLock held // Displays are composited in `mDisplays` order. Internal displays are inserted at boot and // it may be read from other threads with mStateLock held // never removed, so take precedence over external and virtual displays. std::map<wp<IBinder>, sp<DisplayDevice>> mDisplays GUARDED_BY(mStateLock); // std::unordered_map<PhysicalDisplayId, sp<IBinder>> mPhysicalDisplayTokens // The static capacities were chosen to exceed a typical number of physical/virtual displays. // // May be read from any thread, but must only be written from the main thread. ftl::SmallMap<wp<IBinder>, const sp<DisplayDevice>, 5> mDisplays GUARDED_BY(mStateLock); ftl::SmallMap<PhysicalDisplayId, const sp<IBinder>, 3> mPhysicalDisplayTokens GUARDED_BY(mStateLock); GUARDED_BY(mStateLock); struct { struct { Loading Loading @@ -1423,10 +1428,8 @@ private: std::atomic<ui::Transform::RotationFlags> mActiveDisplayTransformHint; std::atomic<ui::Transform::RotationFlags> mActiveDisplayTransformHint; bool isRefreshRateOverlayEnabled() const REQUIRES(mStateLock) { bool isRefreshRateOverlayEnabled() const REQUIRES(mStateLock) { return std::any_of(mDisplays.begin(), mDisplays.end(), return hasDisplay( [](std::pair<wp<IBinder>, sp<DisplayDevice>> display) { [](const auto& display) { return display.isRefreshRateOverlayEnabled(); }); return display.second->isRefreshRateOverlayEnabled(); }); } } wp<IBinder> mActiveDisplayToken GUARDED_BY(mStateLock); wp<IBinder> mActiveDisplayToken GUARDED_BY(mStateLock); Loading
services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +19 −16 Original line number Original line Diff line number Diff line Loading @@ -165,36 +165,39 @@ sp<DisplayDevice> DisplayTransactionTest::injectDefaultInternalDisplay( return displayDevice; return displayDevice; } } bool DisplayTransactionTest::hasPhysicalHwcDisplay(HWDisplayId hwcDisplayId) { bool DisplayTransactionTest::hasPhysicalHwcDisplay(HWDisplayId hwcDisplayId) const { return mFlinger.mutableHwcPhysicalDisplayIdMap().count(hwcDisplayId) == 1; return mFlinger.hwcPhysicalDisplayIdMap().count(hwcDisplayId) == 1; } } bool DisplayTransactionTest::hasTransactionFlagSet(int flag) { bool DisplayTransactionTest::hasTransactionFlagSet(int32_t flag) const { return mFlinger.mutableTransactionFlags() & flag; return mFlinger.transactionFlags() & flag; } } bool DisplayTransactionTest::hasDisplayDevice(sp<IBinder> displayToken) { bool DisplayTransactionTest::hasDisplayDevice(const sp<IBinder>& displayToken) const { return mFlinger.mutableDisplays().count(displayToken) == 1; return mFlinger.displays().contains(displayToken); } } sp<DisplayDevice> DisplayTransactionTest::getDisplayDevice(sp<IBinder> displayToken) { const DisplayDevice& DisplayTransactionTest::getDisplayDevice( return mFlinger.mutableDisplays()[displayToken]; const sp<IBinder>& displayToken) const { return *mFlinger.displays().get(displayToken)->get(); } } bool DisplayTransactionTest::hasCurrentDisplayState(sp<IBinder> displayToken) { bool DisplayTransactionTest::hasCurrentDisplayState(const sp<IBinder>& displayToken) const { return mFlinger.mutableCurrentState().displays.indexOfKey(displayToken) >= 0; return mFlinger.currentState().displays.indexOfKey(displayToken) >= 0; } } const DisplayDeviceState& DisplayTransactionTest::getCurrentDisplayState(sp<IBinder> displayToken) { const DisplayDeviceState& DisplayTransactionTest::getCurrentDisplayState( return mFlinger.mutableCurrentState().displays.valueFor(displayToken); const sp<IBinder>& displayToken) const { return mFlinger.currentState().displays.valueFor(displayToken); } } bool DisplayTransactionTest::hasDrawingDisplayState(sp<IBinder> displayToken) { bool DisplayTransactionTest::hasDrawingDisplayState(const sp<IBinder>& displayToken) const { return mFlinger.mutableDrawingState().displays.indexOfKey(displayToken) >= 0; return mFlinger.drawingState().displays.indexOfKey(displayToken) >= 0; } } const DisplayDeviceState& DisplayTransactionTest::getDrawingDisplayState(sp<IBinder> displayToken) { const DisplayDeviceState& DisplayTransactionTest::getDrawingDisplayState( return mFlinger.mutableDrawingState().displays.valueFor(displayToken); const sp<IBinder>& displayToken) const { return mFlinger.drawingState().displays.valueFor(displayToken); } } } // namespace android } // namespace android
services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h +11 −8 Original line number Original line Diff line number Diff line Loading @@ -95,14 +95,17 @@ public: // -------------------------------------------------------------------- // -------------------------------------------------------------------- // Postcondition helpers // Postcondition helpers bool hasPhysicalHwcDisplay(hal::HWDisplayId hwcDisplayId); bool hasPhysicalHwcDisplay(hal::HWDisplayId) const; bool hasTransactionFlagSet(int flag); bool hasTransactionFlagSet(int32_t flag) const; bool hasDisplayDevice(sp<IBinder> displayToken); sp<DisplayDevice> getDisplayDevice(sp<IBinder> displayToken); bool hasDisplayDevice(const sp<IBinder>& displayToken) const; bool hasCurrentDisplayState(sp<IBinder> displayToken); const DisplayDevice& getDisplayDevice(const sp<IBinder>& displayToken) const; const DisplayDeviceState& getCurrentDisplayState(sp<IBinder> displayToken); bool hasDrawingDisplayState(sp<IBinder> displayToken); bool hasCurrentDisplayState(const sp<IBinder>& displayToken) const; const DisplayDeviceState& getDrawingDisplayState(sp<IBinder> displayToken); const DisplayDeviceState& getCurrentDisplayState(const sp<IBinder>& displayToken) const; bool hasDrawingDisplayState(const sp<IBinder>& displayToken) const; const DisplayDeviceState& getDrawingDisplayState(const sp<IBinder>& displayToken) const; // -------------------------------------------------------------------- // -------------------------------------------------------------------- // Test instances // Test instances Loading
services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp +16 −13 Original line number Original line Diff line number Diff line Loading @@ -107,9 +107,10 @@ template <typename Case> void DisplayTransactionCommitTest::verifyDisplayIsConnected(const sp<IBinder>& displayToken) { void DisplayTransactionCommitTest::verifyDisplayIsConnected(const sp<IBinder>& displayToken) { // The display device should have been set up in the list of displays. // The display device should have been set up in the list of displays. ASSERT_TRUE(hasDisplayDevice(displayToken)); ASSERT_TRUE(hasDisplayDevice(displayToken)); const auto& device = getDisplayDevice(displayToken); const auto& display = getDisplayDevice(displayToken); EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure()); EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), device->isPrimary()); EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), display.isSecure()); EXPECT_EQ(static_cast<bool>(Case::Display::PRIMARY), display.isPrimary()); std::optional<DisplayDeviceState::Physical> expectedPhysical; std::optional<DisplayDeviceState::Physical> expectedPhysical; if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) { if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) { Loading Loading @@ -143,10 +144,11 @@ void DisplayTransactionCommitTest::verifyPhysicalDisplayIsConnected() { // SF should have a display token. // SF should have a display token. const auto displayId = Case::Display::DISPLAY_ID::get(); const auto displayId = Case::Display::DISPLAY_ID::get(); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_EQ(mFlinger.mutablePhysicalDisplayTokens().count(displayId), 1); auto& displayToken = mFlinger.mutablePhysicalDisplayTokens()[displayId]; verifyDisplayIsConnected<Case>(displayToken); const auto displayTokenOpt = mFlinger.mutablePhysicalDisplayTokens().get(displayId); ASSERT_TRUE(displayTokenOpt); verifyDisplayIsConnected<Case>(displayTokenOpt->get()); } } void DisplayTransactionCommitTest::verifyDisplayIsNotConnected(const sp<IBinder>& displayToken) { void DisplayTransactionCommitTest::verifyDisplayIsNotConnected(const sp<IBinder>& displayToken) { Loading Loading @@ -248,9 +250,9 @@ void DisplayTransactionCommitTest::processesHotplugDisconnectCommon() { // SF should not have a display token. // SF should not have a display token. const auto displayId = Case::Display::DISPLAY_ID::get(); const auto displayId = Case::Display::DISPLAY_ID::get(); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(displayId) == 0); ASSERT_FALSE(mFlinger.mutablePhysicalDisplayTokens().contains(displayId)); // The existing token should have been removed // The existing token should have been removed. verifyDisplayIsNotConnected(existing.token()); verifyDisplayIsNotConnected(existing.token()); } } Loading Loading @@ -330,7 +332,7 @@ TEST_F(DisplayTransactionCommitTest, processesHotplugConnectThenDisconnectPrimar // SF should not have a display token. // SF should not have a display token. const auto displayId = Case::Display::DISPLAY_ID::get(); const auto displayId = Case::Display::DISPLAY_ID::get(); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(displayId) == 0); ASSERT_FALSE(mFlinger.mutablePhysicalDisplayTokens().contains(displayId)); }(), }(), testing::KilledBySignal(SIGABRT), "Primary display cannot be disconnected."); testing::KilledBySignal(SIGABRT), "Primary display cannot be disconnected."); } } Loading Loading @@ -369,15 +371,16 @@ TEST_F(DisplayTransactionCommitTest, processesHotplugDisconnectThenConnectPrimar // -------------------------------------------------------------------- // -------------------------------------------------------------------- // Postconditions // Postconditions // The existing token should have been removed // The existing token should have been removed. verifyDisplayIsNotConnected(existing.token()); verifyDisplayIsNotConnected(existing.token()); const auto displayId = Case::Display::DISPLAY_ID::get(); const auto displayId = Case::Display::DISPLAY_ID::get(); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_TRUE(PhysicalDisplayId::tryCast(displayId)); ASSERT_TRUE(mFlinger.mutablePhysicalDisplayTokens().count(displayId) == 1); EXPECT_NE(existing.token(), mFlinger.mutablePhysicalDisplayTokens()[displayId]); // A new display should be connected in its place const auto displayTokenOpt = mFlinger.mutablePhysicalDisplayTokens().get(displayId); ASSERT_TRUE(displayTokenOpt); EXPECT_NE(existing.token(), displayTokenOpt->get()); // A new display should be connected in its place. verifyPhysicalDisplayIsConnected<Case>(); verifyPhysicalDisplayIsConnected<Case>(); // -------------------------------------------------------------------- // -------------------------------------------------------------------- Loading