Loading services/surfaceflinger/tests/end2end/test_framework/surfaceflinger/DisplayEventReceiver.cpp +45 −3 Original line number Diff line number Diff line Loading @@ -41,8 +41,10 @@ #include <ui/DisplayId.h> #include <utils/StrongPointer.h> #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/surfaceflinger/DisplayEventReceiver.h" #include "test_framework/surfaceflinger/PollFdThread.h" #include "test_framework/surfaceflinger/SFController.h" #include "test_framework/surfaceflinger/events/Hotplug.h" #include "test_framework/surfaceflinger/events/VSyncTiming.h" Loading @@ -50,7 +52,8 @@ namespace android::surfaceflinger::tests::end2end::test_framework::surfaceflinge struct DisplayEventReceiver::Passkey final {}; auto DisplayEventReceiver::make(const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, auto DisplayEventReceiver::make(std::weak_ptr<SFController> controller, const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, gui::ISurfaceComposer::VsyncSource source, const sp<IBinder>& layerHandle, const ftl::Flags<gui::ISurfaceComposer::EventRegistration>& events) Loading @@ -61,7 +64,9 @@ auto DisplayEventReceiver::make(const sp<gui::ISurfaceComposer>& client, PollFdT if (instance == nullptr) { return base::unexpected("Failed to construct a DisplayEventReceiver"s); } if (auto result = instance->init(client, pollFdThread, source, layerHandle, events); !result) { if (auto result = instance->init(std::move(controller), client, pollFdThread, source, layerHandle, events); !result) { return base::unexpected("Failed to init a DisplayEventReceiver: " + result.error()); } return std::move(instance); Loading @@ -72,7 +77,9 @@ DisplayEventReceiver::DisplayEventReceiver(Passkey passkey) { } [[nodiscard]] auto DisplayEventReceiver::init( const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, std::weak_ptr<SFController> controller, const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, gui::ISurfaceComposer::VsyncSource source, const sp<IBinder>& layerHandle, const ftl::Flags<gui::ISurfaceComposer::EventRegistration>& events) -> base::expected<void, std::string> { Loading @@ -92,6 +99,7 @@ DisplayEventReceiver::DisplayEventReceiver(Passkey passkey) { return base::unexpected("failed to steal the receive channel"s); } mController = std::move(controller); mPollFdThread = &pollFdThread; mDisplayEventConnection = std::move(displayEventConnection); mDataChannel = std::move(dataChannel); Loading Loading @@ -195,14 +203,38 @@ void DisplayEventReceiver::processReceivedEvents(std::span<Event> events) { } } auto DisplayEventReceiver::mapPhysicalDisplayIdToTestDisplayId(PhysicalDisplayId displayId) -> std::optional<core::DisplayConfiguration::Id> { auto controller = mController.lock(); if (!controller) { LOG(WARNING) << "Unable to map physical displayId " << displayId << " to a test display id. SFController gone."; return {}; } auto testDisplayId = controller->mapPhysicalDisplayIdToTestDisplayId(displayId); if (!testDisplayId) { LOG(WARNING) << "Unable to map physical displayId " << displayId << " to a test display id"; return {}; } return testDisplayId; } void DisplayEventReceiver::onVsync(DisplayId displayId, Timestamp timestamp, uint32_t count, VsyncEventData vsyncData) { ftl::ignore(displayId, timestamp, count, vsyncData); LOG(VERBOSE) << "onVsync() display " << displayId << " timestamp " << timestamp.time_since_epoch() << " count " << count; auto testDisplayId = mapPhysicalDisplayIdToTestDisplayId(displayId); if (!testDisplayId) { return; } mCallbacks.onVSyncTiming(events::VSyncTiming{ .receiver = this, .displayId = *testDisplayId, .sfEventAt = timestamp, .count = count, .data = vsyncData, Loading @@ -216,9 +248,19 @@ void DisplayEventReceiver::onHotplug(DisplayId displayId, Timestamp timestamp, b << timestamp.time_since_epoch() << " connected " << connected << " connectionError " << connectionError; if (auto controller = mController.lock()) { controller->onDisplayConnectionChanged(displayId, connected); } auto testDisplayId = mapPhysicalDisplayIdToTestDisplayId(displayId); if (!testDisplayId) { return; } if (connectionError == 0) { mCallbacks.onHotplug(events::Hotplug{ .receiver = this, .displayId = *testDisplayId, .sfEventAt = timestamp, .connected = connected, }); Loading services/surfaceflinger/tests/end2end/test_framework/surfaceflinger/DisplayEventReceiver.h +14 −3 Original line number Diff line number Diff line Loading @@ -30,17 +30,20 @@ #include <binder/IBinder.h> #include <ftl/finalizer.h> #include <ftl/flags.h> #include <ftl/function.h> #include <gui/DisplayEventReceiver.h> #include <gui/VsyncEventData.h> #include <ui/DisplayId.h> #include <utils/StrongPointer.h> #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/surfaceflinger/PollFdThread.h" #include "test_framework/surfaceflinger/events/Hotplug.h" #include "test_framework/surfaceflinger/events/VSyncTiming.h" namespace android::surfaceflinger::tests::end2end::test_framework::surfaceflinger { class SFController; class PollFdThread; class DisplayEventReceiver final { Loading @@ -58,9 +61,13 @@ class DisplayEventReceiver final { events::Hotplug::AsyncConnector onHotplug; }; using PhysicalIdToTestDisplayId = ftl::Function< auto(PhysicalDisplayId)->std::optional<test_framework::core::DisplayConfiguration::Id>>; [[nodiscard]] static auto make( const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, gui::ISurfaceComposer::VsyncSource source, const sp<IBinder>& layerHandle, std::weak_ptr<SFController> controller, const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, gui::ISurfaceComposer::VsyncSource source, const sp<IBinder>& layerHandle, const ftl::Flags<gui::ISurfaceComposer::EventRegistration>& events) -> base::expected<std::shared_ptr<DisplayEventReceiver>, std::string>; Loading @@ -86,7 +93,8 @@ class DisplayEventReceiver final { using Timestamp = std::chrono::steady_clock::time_point; using VsyncEventData = android::VsyncEventData; [[nodiscard]] auto init(const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, [[nodiscard]] auto init(std::weak_ptr<SFController> controller, const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, gui::ISurfaceComposer::VsyncSource source, const sp<IBinder>& layerHandle, const ftl::Flags<gui::ISurfaceComposer::EventRegistration>& events) Loading @@ -94,6 +102,8 @@ class DisplayEventReceiver final { void processReceivedEvents(); void processReceivedEvents(std::span<Event> events); auto mapPhysicalDisplayIdToTestDisplayId(PhysicalDisplayId displayId) -> std::optional<core::DisplayConfiguration::Id>; void onVsync(DisplayId displayId, Timestamp timestamp, uint32_t count, VsyncEventData vsyncData); void onHotplug(DisplayId displayId, Timestamp timestamp, bool connected, Loading @@ -105,6 +115,7 @@ class DisplayEventReceiver final { static void onHdcpLevelsChange(DisplayId displayId, Timestamp timestamp, int32_t connectedLevel, int32_t maxLevel); std::weak_ptr<SFController> mController; Callbacks mCallbacks; sp<gui::IDisplayEventConnection> mDisplayEventConnection; Loading services/surfaceflinger/tests/end2end/test_framework/surfaceflinger/SFController.cpp +82 −7 Original line number Diff line number Diff line Loading @@ -15,15 +15,20 @@ */ #include <chrono> #include <cstdint> #include <cstdlib> #include <memory> #include <mutex> #include <optional> #include <string> #include <string_view> #include <thread> #include <utility> #include <vector> #include <android-base/expected.h> #include <android-base/logging.h> #include <android-base/parseint.h> #include <android-base/properties.h> #include <android/gui/ISurfaceComposer.h> #include <binder/IBinder.h> Loading @@ -31,13 +36,16 @@ #include <binder/IServiceManager.h> #include <binder/Status.h> #include <ftl/finalizer.h> #include <ftl/flags.h> #include <ftl/ignore.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <ui/DisplayId.h> #include <utils/String16.h> #include <utils/String8.h> #include <utils/StrongPointer.h> #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/surfaceflinger/DisplayEventReceiver.h" #include "test_framework/surfaceflinger/PollFdThread.h" #include "test_framework/surfaceflinger/SFController.h" Loading Loading @@ -101,9 +109,9 @@ auto SFController::init() -> base::expected<void, std::string> { using namespace std::string_literals; LOG(INFO) << "Stopping everything to prepare for tests"; // NOLINTBEGIN(cert-env33-c) // NOLINTBEGIN(cert-env33-c, concurrency-mt-unsafe) system("stop"); // NOLINTEND(cert-env33-c) // NOLINTEND(cert-env33-c, concurrency-mt-unsafe) auto pollFdThreadResult = PollFdThread::make(); if (!pollFdThreadResult) { Loading Loading @@ -140,9 +148,21 @@ auto SFController::startAndConnect() -> base::expected<void, std::string> { "Failed to construct a surfaceComposerClient around the aidl interface."s); } // We need an internal display event receiver so we can listen for hotplug events. auto displayEventReceiverResult = DisplayEventReceiver::make( shared_from_this(), surfaceComposerAidl, *mPollFdThread, gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp, nullptr, {}); if (!displayEventReceiverResult) { return base::unexpected(std::move(displayEventReceiverResult).error()); } auto displayEventReceiver = *std::move(displayEventReceiverResult); mSurfaceComposerAidl = std::move(surfaceComposerAidl); mSurfaceComposerClientAidl = std::move(surfaceComposerClientAidl); mSurfaceComposerClient = std::move(surfaceComposerClient); mDisplayEventReceiver = std::move(displayEventReceiver); initializeDisplayIdMapping(); LOG(INFO) << "Connected to surfaceflinger"; return {}; Loading @@ -150,16 +170,16 @@ auto SFController::startAndConnect() -> base::expected<void, std::string> { void SFController::start() { LOG(INFO) << "Starting surfaceflinger"; // NOLINTBEGIN(cert-env33-c) // NOLINTBEGIN(cert-env33-c, concurrency-mt-unsafe) system("start surfaceflinger"); // NOLINTEND(cert-env33-c) // NOLINTEND(cert-env33-c, concurrency-mt-unsafe) } void SFController::stop() { LOG(INFO) << "Stopping surfaceflinger"; // NOLINTBEGIN(cert-env33-c) // NOLINTBEGIN(cert-env33-c, concurrency-mt-unsafe) system("stop surfaceflinger"); // NOLINTEND(cert-env33-c) // NOLINTEND(cert-env33-c, concurrency-mt-unsafe) if (mSurfaceComposerAidl != nullptr) { LOG(INFO) << "Waiting for SF AIDL interface to die"; Loading @@ -184,6 +204,7 @@ void SFController::stop() { std::this_thread::sleep_for(kShutdownWait); } mDisplayEventReceiver = nullptr; mSurfaceComposerClient = nullptr; mSurfaceComposerClientAidl = nullptr; mSurfaceComposerAidl = nullptr; Loading @@ -192,7 +213,7 @@ void SFController::stop() { auto SFController::makeDisplayEventReceiver() -> base::expected<std::shared_ptr<DisplayEventReceiver>, std::string> { CHECK(mSurfaceComposerAidl != nullptr); return DisplayEventReceiver::make(mSurfaceComposerAidl, *mPollFdThread, return DisplayEventReceiver::make(shared_from_this(), mSurfaceComposerAidl, *mPollFdThread, gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp, nullptr, {gui::ISurfaceComposer::EventRegistration::frameRateOverride, gui::ISurfaceComposer::EventRegistration::modeChanged}); Loading @@ -204,4 +225,58 @@ auto SFController::makeSurface(const Surface::CreationArgs& args) return Surface::make(mSurfaceComposerClient, args); } auto SFController::mapPhysicalDisplayIdToTestDisplayId(PhysicalDisplayId displayId) -> std::optional<core::DisplayConfiguration::Id> { const std::lock_guard lock(mMutex); auto iter = mPhysicalDisplayIdToTestDisplayId.find(displayId); return (iter != mPhysicalDisplayIdToTestDisplayId.end()) ? std::make_optional(iter->second) : std::nullopt; } void SFController::addDisplayIdToMapping(PhysicalDisplayId displayId) { gui::StaticDisplayInfo staticInfo; CHECK(mSurfaceComposerAidl->getStaticDisplayInfo(displayId.value, &staticInfo).isOk()); auto name = staticInfo.deviceProductInfo.and_then( [](const auto& info) -> std::optional<std::string> { return info.name; }); constexpr std::string kMagicPrefix = "fake"; if (!name || !name->starts_with(kMagicPrefix)) { LOG(ERROR) << "Unexpected: physical display id " << displayId << " is not a test fake display: " << name.value_or("<missing>"); return; } auto remainder = name->substr(kMagicPrefix.size()); uint32_t testId = 0; if (!android::base::ParseUint(remainder.c_str(), &testId)) { LOG(ERROR) << "Failed to parse as int: " << remainder; return; } const std::lock_guard lock(mMutex); mPhysicalDisplayIdToTestDisplayId[displayId] = testId; } void SFController::onDisplayConnectionChanged(PhysicalDisplayId displayId, bool connected) { if (connected) { addDisplayIdToMapping(displayId); } else { const std::lock_guard lock(mMutex); mPhysicalDisplayIdToTestDisplayId.erase(displayId); } } void SFController::initializeDisplayIdMapping() { CHECK(mSurfaceComposerAidl); std::vector<int64_t> rawDisplayIds; CHECK(mSurfaceComposerAidl->getPhysicalDisplayIds(&rawDisplayIds).isOk()); for (auto displayIdValue : rawDisplayIds) { addDisplayIdToMapping(PhysicalDisplayId::fromValue(displayIdValue)); } } } // namespace android::surfaceflinger::tests::end2end::test_framework::surfaceflinger services/surfaceflinger/tests/end2end/test_framework/surfaceflinger/SFController.h +19 −1 Original line number Diff line number Diff line Loading @@ -17,13 +17,20 @@ #pragma once #include <memory> #include <mutex> #include <optional> #include <string> #include <string_view> #include <unordered_map> #include <android-base/expected.h> #include <android-base/thread_annotations.h> #include <ftl/finalizer.h> #include <ui/DisplayId.h> #include <utils/Mutex.h> #include <utils/StrongPointer.h> #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/surfaceflinger/PollFdThread.h" #include "test_framework/surfaceflinger/Surface.h" Loading @@ -45,7 +52,7 @@ namespace android::surfaceflinger::tests::end2end::test_framework::surfaceflinge class DisplayEventReceiver; class PollFdThread; class SFController final { class SFController final : public std::enable_shared_from_this<SFController> { struct Passkey; // Uses the passkey idiom to restrict construction. public: Loading @@ -66,15 +73,26 @@ class SFController final { auto makeSurface(const Surface::CreationArgs& args) -> base::expected<std::shared_ptr<Surface>, std::string>; void onDisplayConnectionChanged(PhysicalDisplayId displayId, bool connected); auto mapPhysicalDisplayIdToTestDisplayId(PhysicalDisplayId displayId) -> std::optional<core::DisplayConfiguration::Id>; private: [[nodiscard]] auto init() -> base::expected<void, std::string>; static void start(); void stop(); void initializeDisplayIdMapping(); void addDisplayIdToMapping(PhysicalDisplayId displayId); std::shared_ptr<PollFdThread> mPollFdThread; sp<gui::ISurfaceComposer> mSurfaceComposerAidl; sp<gui::ISurfaceComposerClient> mSurfaceComposerClientAidl; sp<SurfaceComposerClient> mSurfaceComposerClient; std::shared_ptr<DisplayEventReceiver> mDisplayEventReceiver; mutable std::mutex mMutex; std::unordered_map<PhysicalDisplayId, core::DisplayConfiguration::Id> mPhysicalDisplayIdToTestDisplayId GUARDED_BY(mMutex); // Finalizers should be last so their destructors are invoked first. ftl::FinalizerFtl mCleanup; Loading Loading
services/surfaceflinger/tests/end2end/test_framework/surfaceflinger/DisplayEventReceiver.cpp +45 −3 Original line number Diff line number Diff line Loading @@ -41,8 +41,10 @@ #include <ui/DisplayId.h> #include <utils/StrongPointer.h> #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/surfaceflinger/DisplayEventReceiver.h" #include "test_framework/surfaceflinger/PollFdThread.h" #include "test_framework/surfaceflinger/SFController.h" #include "test_framework/surfaceflinger/events/Hotplug.h" #include "test_framework/surfaceflinger/events/VSyncTiming.h" Loading @@ -50,7 +52,8 @@ namespace android::surfaceflinger::tests::end2end::test_framework::surfaceflinge struct DisplayEventReceiver::Passkey final {}; auto DisplayEventReceiver::make(const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, auto DisplayEventReceiver::make(std::weak_ptr<SFController> controller, const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, gui::ISurfaceComposer::VsyncSource source, const sp<IBinder>& layerHandle, const ftl::Flags<gui::ISurfaceComposer::EventRegistration>& events) Loading @@ -61,7 +64,9 @@ auto DisplayEventReceiver::make(const sp<gui::ISurfaceComposer>& client, PollFdT if (instance == nullptr) { return base::unexpected("Failed to construct a DisplayEventReceiver"s); } if (auto result = instance->init(client, pollFdThread, source, layerHandle, events); !result) { if (auto result = instance->init(std::move(controller), client, pollFdThread, source, layerHandle, events); !result) { return base::unexpected("Failed to init a DisplayEventReceiver: " + result.error()); } return std::move(instance); Loading @@ -72,7 +77,9 @@ DisplayEventReceiver::DisplayEventReceiver(Passkey passkey) { } [[nodiscard]] auto DisplayEventReceiver::init( const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, std::weak_ptr<SFController> controller, const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, gui::ISurfaceComposer::VsyncSource source, const sp<IBinder>& layerHandle, const ftl::Flags<gui::ISurfaceComposer::EventRegistration>& events) -> base::expected<void, std::string> { Loading @@ -92,6 +99,7 @@ DisplayEventReceiver::DisplayEventReceiver(Passkey passkey) { return base::unexpected("failed to steal the receive channel"s); } mController = std::move(controller); mPollFdThread = &pollFdThread; mDisplayEventConnection = std::move(displayEventConnection); mDataChannel = std::move(dataChannel); Loading Loading @@ -195,14 +203,38 @@ void DisplayEventReceiver::processReceivedEvents(std::span<Event> events) { } } auto DisplayEventReceiver::mapPhysicalDisplayIdToTestDisplayId(PhysicalDisplayId displayId) -> std::optional<core::DisplayConfiguration::Id> { auto controller = mController.lock(); if (!controller) { LOG(WARNING) << "Unable to map physical displayId " << displayId << " to a test display id. SFController gone."; return {}; } auto testDisplayId = controller->mapPhysicalDisplayIdToTestDisplayId(displayId); if (!testDisplayId) { LOG(WARNING) << "Unable to map physical displayId " << displayId << " to a test display id"; return {}; } return testDisplayId; } void DisplayEventReceiver::onVsync(DisplayId displayId, Timestamp timestamp, uint32_t count, VsyncEventData vsyncData) { ftl::ignore(displayId, timestamp, count, vsyncData); LOG(VERBOSE) << "onVsync() display " << displayId << " timestamp " << timestamp.time_since_epoch() << " count " << count; auto testDisplayId = mapPhysicalDisplayIdToTestDisplayId(displayId); if (!testDisplayId) { return; } mCallbacks.onVSyncTiming(events::VSyncTiming{ .receiver = this, .displayId = *testDisplayId, .sfEventAt = timestamp, .count = count, .data = vsyncData, Loading @@ -216,9 +248,19 @@ void DisplayEventReceiver::onHotplug(DisplayId displayId, Timestamp timestamp, b << timestamp.time_since_epoch() << " connected " << connected << " connectionError " << connectionError; if (auto controller = mController.lock()) { controller->onDisplayConnectionChanged(displayId, connected); } auto testDisplayId = mapPhysicalDisplayIdToTestDisplayId(displayId); if (!testDisplayId) { return; } if (connectionError == 0) { mCallbacks.onHotplug(events::Hotplug{ .receiver = this, .displayId = *testDisplayId, .sfEventAt = timestamp, .connected = connected, }); Loading
services/surfaceflinger/tests/end2end/test_framework/surfaceflinger/DisplayEventReceiver.h +14 −3 Original line number Diff line number Diff line Loading @@ -30,17 +30,20 @@ #include <binder/IBinder.h> #include <ftl/finalizer.h> #include <ftl/flags.h> #include <ftl/function.h> #include <gui/DisplayEventReceiver.h> #include <gui/VsyncEventData.h> #include <ui/DisplayId.h> #include <utils/StrongPointer.h> #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/surfaceflinger/PollFdThread.h" #include "test_framework/surfaceflinger/events/Hotplug.h" #include "test_framework/surfaceflinger/events/VSyncTiming.h" namespace android::surfaceflinger::tests::end2end::test_framework::surfaceflinger { class SFController; class PollFdThread; class DisplayEventReceiver final { Loading @@ -58,9 +61,13 @@ class DisplayEventReceiver final { events::Hotplug::AsyncConnector onHotplug; }; using PhysicalIdToTestDisplayId = ftl::Function< auto(PhysicalDisplayId)->std::optional<test_framework::core::DisplayConfiguration::Id>>; [[nodiscard]] static auto make( const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, gui::ISurfaceComposer::VsyncSource source, const sp<IBinder>& layerHandle, std::weak_ptr<SFController> controller, const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, gui::ISurfaceComposer::VsyncSource source, const sp<IBinder>& layerHandle, const ftl::Flags<gui::ISurfaceComposer::EventRegistration>& events) -> base::expected<std::shared_ptr<DisplayEventReceiver>, std::string>; Loading @@ -86,7 +93,8 @@ class DisplayEventReceiver final { using Timestamp = std::chrono::steady_clock::time_point; using VsyncEventData = android::VsyncEventData; [[nodiscard]] auto init(const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, [[nodiscard]] auto init(std::weak_ptr<SFController> controller, const sp<gui::ISurfaceComposer>& client, PollFdThread& pollFdThread, gui::ISurfaceComposer::VsyncSource source, const sp<IBinder>& layerHandle, const ftl::Flags<gui::ISurfaceComposer::EventRegistration>& events) Loading @@ -94,6 +102,8 @@ class DisplayEventReceiver final { void processReceivedEvents(); void processReceivedEvents(std::span<Event> events); auto mapPhysicalDisplayIdToTestDisplayId(PhysicalDisplayId displayId) -> std::optional<core::DisplayConfiguration::Id>; void onVsync(DisplayId displayId, Timestamp timestamp, uint32_t count, VsyncEventData vsyncData); void onHotplug(DisplayId displayId, Timestamp timestamp, bool connected, Loading @@ -105,6 +115,7 @@ class DisplayEventReceiver final { static void onHdcpLevelsChange(DisplayId displayId, Timestamp timestamp, int32_t connectedLevel, int32_t maxLevel); std::weak_ptr<SFController> mController; Callbacks mCallbacks; sp<gui::IDisplayEventConnection> mDisplayEventConnection; Loading
services/surfaceflinger/tests/end2end/test_framework/surfaceflinger/SFController.cpp +82 −7 Original line number Diff line number Diff line Loading @@ -15,15 +15,20 @@ */ #include <chrono> #include <cstdint> #include <cstdlib> #include <memory> #include <mutex> #include <optional> #include <string> #include <string_view> #include <thread> #include <utility> #include <vector> #include <android-base/expected.h> #include <android-base/logging.h> #include <android-base/parseint.h> #include <android-base/properties.h> #include <android/gui/ISurfaceComposer.h> #include <binder/IBinder.h> Loading @@ -31,13 +36,16 @@ #include <binder/IServiceManager.h> #include <binder/Status.h> #include <ftl/finalizer.h> #include <ftl/flags.h> #include <ftl/ignore.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> #include <ui/DisplayId.h> #include <utils/String16.h> #include <utils/String8.h> #include <utils/StrongPointer.h> #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/surfaceflinger/DisplayEventReceiver.h" #include "test_framework/surfaceflinger/PollFdThread.h" #include "test_framework/surfaceflinger/SFController.h" Loading Loading @@ -101,9 +109,9 @@ auto SFController::init() -> base::expected<void, std::string> { using namespace std::string_literals; LOG(INFO) << "Stopping everything to prepare for tests"; // NOLINTBEGIN(cert-env33-c) // NOLINTBEGIN(cert-env33-c, concurrency-mt-unsafe) system("stop"); // NOLINTEND(cert-env33-c) // NOLINTEND(cert-env33-c, concurrency-mt-unsafe) auto pollFdThreadResult = PollFdThread::make(); if (!pollFdThreadResult) { Loading Loading @@ -140,9 +148,21 @@ auto SFController::startAndConnect() -> base::expected<void, std::string> { "Failed to construct a surfaceComposerClient around the aidl interface."s); } // We need an internal display event receiver so we can listen for hotplug events. auto displayEventReceiverResult = DisplayEventReceiver::make( shared_from_this(), surfaceComposerAidl, *mPollFdThread, gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp, nullptr, {}); if (!displayEventReceiverResult) { return base::unexpected(std::move(displayEventReceiverResult).error()); } auto displayEventReceiver = *std::move(displayEventReceiverResult); mSurfaceComposerAidl = std::move(surfaceComposerAidl); mSurfaceComposerClientAidl = std::move(surfaceComposerClientAidl); mSurfaceComposerClient = std::move(surfaceComposerClient); mDisplayEventReceiver = std::move(displayEventReceiver); initializeDisplayIdMapping(); LOG(INFO) << "Connected to surfaceflinger"; return {}; Loading @@ -150,16 +170,16 @@ auto SFController::startAndConnect() -> base::expected<void, std::string> { void SFController::start() { LOG(INFO) << "Starting surfaceflinger"; // NOLINTBEGIN(cert-env33-c) // NOLINTBEGIN(cert-env33-c, concurrency-mt-unsafe) system("start surfaceflinger"); // NOLINTEND(cert-env33-c) // NOLINTEND(cert-env33-c, concurrency-mt-unsafe) } void SFController::stop() { LOG(INFO) << "Stopping surfaceflinger"; // NOLINTBEGIN(cert-env33-c) // NOLINTBEGIN(cert-env33-c, concurrency-mt-unsafe) system("stop surfaceflinger"); // NOLINTEND(cert-env33-c) // NOLINTEND(cert-env33-c, concurrency-mt-unsafe) if (mSurfaceComposerAidl != nullptr) { LOG(INFO) << "Waiting for SF AIDL interface to die"; Loading @@ -184,6 +204,7 @@ void SFController::stop() { std::this_thread::sleep_for(kShutdownWait); } mDisplayEventReceiver = nullptr; mSurfaceComposerClient = nullptr; mSurfaceComposerClientAidl = nullptr; mSurfaceComposerAidl = nullptr; Loading @@ -192,7 +213,7 @@ void SFController::stop() { auto SFController::makeDisplayEventReceiver() -> base::expected<std::shared_ptr<DisplayEventReceiver>, std::string> { CHECK(mSurfaceComposerAidl != nullptr); return DisplayEventReceiver::make(mSurfaceComposerAidl, *mPollFdThread, return DisplayEventReceiver::make(shared_from_this(), mSurfaceComposerAidl, *mPollFdThread, gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp, nullptr, {gui::ISurfaceComposer::EventRegistration::frameRateOverride, gui::ISurfaceComposer::EventRegistration::modeChanged}); Loading @@ -204,4 +225,58 @@ auto SFController::makeSurface(const Surface::CreationArgs& args) return Surface::make(mSurfaceComposerClient, args); } auto SFController::mapPhysicalDisplayIdToTestDisplayId(PhysicalDisplayId displayId) -> std::optional<core::DisplayConfiguration::Id> { const std::lock_guard lock(mMutex); auto iter = mPhysicalDisplayIdToTestDisplayId.find(displayId); return (iter != mPhysicalDisplayIdToTestDisplayId.end()) ? std::make_optional(iter->second) : std::nullopt; } void SFController::addDisplayIdToMapping(PhysicalDisplayId displayId) { gui::StaticDisplayInfo staticInfo; CHECK(mSurfaceComposerAidl->getStaticDisplayInfo(displayId.value, &staticInfo).isOk()); auto name = staticInfo.deviceProductInfo.and_then( [](const auto& info) -> std::optional<std::string> { return info.name; }); constexpr std::string kMagicPrefix = "fake"; if (!name || !name->starts_with(kMagicPrefix)) { LOG(ERROR) << "Unexpected: physical display id " << displayId << " is not a test fake display: " << name.value_or("<missing>"); return; } auto remainder = name->substr(kMagicPrefix.size()); uint32_t testId = 0; if (!android::base::ParseUint(remainder.c_str(), &testId)) { LOG(ERROR) << "Failed to parse as int: " << remainder; return; } const std::lock_guard lock(mMutex); mPhysicalDisplayIdToTestDisplayId[displayId] = testId; } void SFController::onDisplayConnectionChanged(PhysicalDisplayId displayId, bool connected) { if (connected) { addDisplayIdToMapping(displayId); } else { const std::lock_guard lock(mMutex); mPhysicalDisplayIdToTestDisplayId.erase(displayId); } } void SFController::initializeDisplayIdMapping() { CHECK(mSurfaceComposerAidl); std::vector<int64_t> rawDisplayIds; CHECK(mSurfaceComposerAidl->getPhysicalDisplayIds(&rawDisplayIds).isOk()); for (auto displayIdValue : rawDisplayIds) { addDisplayIdToMapping(PhysicalDisplayId::fromValue(displayIdValue)); } } } // namespace android::surfaceflinger::tests::end2end::test_framework::surfaceflinger
services/surfaceflinger/tests/end2end/test_framework/surfaceflinger/SFController.h +19 −1 Original line number Diff line number Diff line Loading @@ -17,13 +17,20 @@ #pragma once #include <memory> #include <mutex> #include <optional> #include <string> #include <string_view> #include <unordered_map> #include <android-base/expected.h> #include <android-base/thread_annotations.h> #include <ftl/finalizer.h> #include <ui/DisplayId.h> #include <utils/Mutex.h> #include <utils/StrongPointer.h> #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/surfaceflinger/PollFdThread.h" #include "test_framework/surfaceflinger/Surface.h" Loading @@ -45,7 +52,7 @@ namespace android::surfaceflinger::tests::end2end::test_framework::surfaceflinge class DisplayEventReceiver; class PollFdThread; class SFController final { class SFController final : public std::enable_shared_from_this<SFController> { struct Passkey; // Uses the passkey idiom to restrict construction. public: Loading @@ -66,15 +73,26 @@ class SFController final { auto makeSurface(const Surface::CreationArgs& args) -> base::expected<std::shared_ptr<Surface>, std::string>; void onDisplayConnectionChanged(PhysicalDisplayId displayId, bool connected); auto mapPhysicalDisplayIdToTestDisplayId(PhysicalDisplayId displayId) -> std::optional<core::DisplayConfiguration::Id>; private: [[nodiscard]] auto init() -> base::expected<void, std::string>; static void start(); void stop(); void initializeDisplayIdMapping(); void addDisplayIdToMapping(PhysicalDisplayId displayId); std::shared_ptr<PollFdThread> mPollFdThread; sp<gui::ISurfaceComposer> mSurfaceComposerAidl; sp<gui::ISurfaceComposerClient> mSurfaceComposerClientAidl; sp<SurfaceComposerClient> mSurfaceComposerClient; std::shared_ptr<DisplayEventReceiver> mDisplayEventReceiver; mutable std::mutex mMutex; std::unordered_map<PhysicalDisplayId, core::DisplayConfiguration::Id> mPhysicalDisplayIdToTestDisplayId GUARDED_BY(mMutex); // Finalizers should be last so their destructors are invoked first. ftl::FinalizerFtl mCleanup; Loading