Loading services/surfaceflinger/tests/end2end/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -32,12 +32,14 @@ cc_test { ], srcs: [ "main.cpp", "test_framework/core/BufferId.cpp", "test_framework/core/EdidBuilder.cpp", "test_framework/core/TestService.cpp", "test_framework/hwc3/DisplayVSyncEventService.cpp", "test_framework/hwc3/FakeComposer.cpp", "test_framework/hwc3/Hwc3Controller.cpp", "test_framework/hwc3/MultiDisplayRefreshEventGenerator.cpp", "test_framework/hwc3/ObservingComposer.cpp", "test_framework/hwc3/SingleDisplayRefreshEventGenerator.cpp", "test_framework/hwc3/SingleDisplayRefreshSchedule.cpp", "test_framework/hwc3/TimeKeeperThread.cpp", Loading services/surfaceflinger/tests/end2end/test_framework/core/BufferId.cpp 0 → 100644 +67 −0 Original line number Diff line number Diff line /* * Copyright 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <cstdint> #include <string> #include <sys/stat.h> #include <aidl/android/hardware/common/NativeHandle.h> #include <android-base/logging.h> #include <cutils/native_handle.h> #include <fmt/format.h> #include <ftl/cast.h> #include <ui/GraphicBuffer.h> #include <utils/StrongPointer.h> #include "test_framework/core/BufferId.h" namespace android::surfaceflinger::tests::end2end::test_framework::core { namespace { auto bufferFdToBufferId(int rawFd) -> BufferId { struct stat stat{}; const int result = fstat(rawFd, &stat); CHECK(result == 0); CHECK(ftl::cast_safety<uint64_t>(stat.st_ino) == ftl::CastSafety::kSafe); CHECK(ftl::cast_safety<uint64_t>(stat.st_dev) == ftl::CastSafety::kSafe); return {.inode = static_cast<uint64_t>(stat.st_ino), .device = static_cast<uint64_t>(stat.st_dev)}; } } // namespace auto toBufferId(const aidl::android::hardware::common::NativeHandle& handle) -> BufferId { CHECK(!handle.fds.empty()); return bufferFdToBufferId(handle.fds[0].get()); } auto toBufferId(const native_handle_t* handle) -> BufferId { CHECK(handle != nullptr); CHECK(handle->numFds > 0); return bufferFdToBufferId(handle->data[0]); } auto toBufferId(const sp<GraphicBuffer>& buffer) -> BufferId { CHECK(buffer != nullptr); return toBufferId(buffer->getNativeBuffer()->handle); } auto toString(const BufferId& value) -> std::string { return fmt::format("BufferId{{inode: {}, device: {}}}", value.inode, value.device); } } // namespace android::surfaceflinger::tests::end2end::test_framework::core No newline at end of file services/surfaceflinger/tests/end2end/test_framework/core/BufferId.h 0 → 100644 +46 −0 Original line number Diff line number Diff line /* * Copyright 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <cstdint> #include <string> #include <aidl/android/hardware/common/NativeHandle.h> #include <cutils/native_handle.h> #include <ui/GraphicBuffer.h> #include <utils/StrongPointer.h> namespace android::surfaceflinger::tests::end2end::test_framework::core { struct BufferId final { uint64_t inode; uint64_t device; friend auto operator==(const BufferId&, const BufferId&) -> bool = default; }; auto toBufferId(const native_handle_t* handle) -> BufferId; auto toBufferId(const sp<GraphicBuffer>& buffer) -> BufferId; auto toBufferId(const aidl::android::hardware::common::NativeHandle& handle) -> BufferId; auto toString(const BufferId& value) -> std::string; inline auto format_as(const BufferId& event) -> std::string { return toString(event); } } // namespace android::surfaceflinger::tests::end2end::test_framework::core services/surfaceflinger/tests/end2end/test_framework/hwc3/Hwc3Controller.cpp +20 −4 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/hwc3/FakeComposer.h" #include "test_framework/hwc3/Hwc3Controller.h" #include "test_framework/hwc3/ObservingComposer.h" namespace android::surfaceflinger::tests::end2end::test_framework::hwc3 { Loading @@ -39,7 +40,7 @@ auto Hwc3Controller::make(std::span<const core::DisplayConfiguration> displays) -> base::expected<std::shared_ptr<hwc3::Hwc3Controller>, std::string> { using namespace std::string_literals; auto controller = std::make_unique<Hwc3Controller>(Passkey{}); auto controller = std::make_shared<Hwc3Controller>(Passkey{}); if (controller == nullptr) { return base::unexpected("Failed to construct the Hwc3Controller instance"s); } Loading @@ -60,8 +61,6 @@ auto Hwc3Controller::init(const std::span<const core::DisplayConfiguration> disp -> base::expected<void, std::string> { using namespace std::string_literals; auto qualifiedServiceName = FakeComposer::getServiceName(baseServiceName); auto fakeComposerResult = FakeComposer::make(); if (!fakeComposerResult) { return base::unexpected(std::move(fakeComposerResult).error()); Loading @@ -72,7 +71,15 @@ auto Hwc3Controller::init(const std::span<const core::DisplayConfiguration> disp fakeComposer->addDisplay(display); } auto binder = fakeComposer->getComposer()->asBinder(); auto observingComposerResult = ObservingComposer::make(shared_from_this(), fakeComposer->getComposer()); if (!observingComposerResult) { return base::unexpected(std::move(observingComposerResult).error()); } auto observingComposer = *std::move(observingComposerResult); const auto qualifiedServiceName = ObservingComposer::getServiceName(baseServiceName); auto binder = observingComposer->getComposer()->asBinder(); // This downgrade allows us to use the fake service name without it being defined in the // VINTF manifest. Loading @@ -86,9 +93,18 @@ auto Hwc3Controller::init(const std::span<const core::DisplayConfiguration> disp LOG(INFO) << "Registered service " << qualifiedServiceName << ". Error: " << status; mFakeComposer = std::move(fakeComposer); mObservingComposer = std::move(observingComposer); return {}; } auto Hwc3Controller::editCallbacks() -> Callbacks& { return mCallbacks; } auto Hwc3Controller::callbacks() const -> const Callbacks& { return mCallbacks; } auto Hwc3Controller::getServiceName() -> std::string { return FakeComposer::getServiceName(baseServiceName); } Loading services/surfaceflinger/tests/end2end/test_framework/hwc3/Hwc3Controller.h +36 −3 Original line number Diff line number Diff line Loading @@ -22,18 +22,43 @@ #include <android-base/expected.h> #include <aidl/android/hardware/graphics/composer3/PowerMode.h> #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/hwc3/events/ClientDestroyed.h" #include "test_framework/hwc3/events/DisplayPresented.h" #include "test_framework/hwc3/events/PendingBufferSwap.h" #include "test_framework/hwc3/events/PowerMode.h" #include "test_framework/hwc3/events/VSync.h" #include "test_framework/hwc3/events/VSyncEnabled.h" namespace android::surfaceflinger::tests::end2end::test_framework::hwc3 { class FakeComposer; class ObservingComposer; class Hwc3Controller final { class Hwc3Controller final : public std::enable_shared_from_this<Hwc3Controller> { struct Passkey; // Uses the passkey idiom to restrict construction. public: struct Callbacks final { // Invoked when SF destroys its HWC client connection. events::ClientDestroyed::AsyncConnector onClientDestroyed; // Invoked when SF configures the power mode for a display. events::PowerMode::AsyncConnector onPowerModeChanged; // Invoked when SF enables or disables vsync callbacks for a display. events::VSyncEnabled::AsyncConnector onVsyncEnabledChanged; // Invoked when SF presents a display. events::DisplayPresented::AsyncConnector onDisplayPresented; // Invoked when SF is swapping the buffer content of a hardware overlay. events::PendingBufferSwap::AsyncConnector onPendingBufferSwap; // Invoked when the client sends SF a vsync callback. events::VSync::AsyncConnector onVSyncCallbackSent; }; // Gets the service name for the HWC3 instance that will be created and registered [[nodiscard]] static auto getServiceName() -> std::string; Loading @@ -43,6 +68,12 @@ class Hwc3Controller final { explicit Hwc3Controller(Passkey passkey); // Allows the callbacks to be routed. [[nodiscard]] auto editCallbacks() -> Callbacks&; // Allows the callbacks to be sent. [[nodiscard]] auto callbacks() const -> const Callbacks&; // Adds a new display to the HWC3, which will become a hotplug connect event. void addDisplay(const core::DisplayConfiguration& config); Loading @@ -56,6 +87,8 @@ class Hwc3Controller final { -> base::expected<void, std::string>; std::shared_ptr<FakeComposer> mFakeComposer; std::shared_ptr<ObservingComposer> mObservingComposer; Callbacks mCallbacks; }; } // namespace android::surfaceflinger::tests::end2end::test_framework::hwc3 Loading
services/surfaceflinger/tests/end2end/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -32,12 +32,14 @@ cc_test { ], srcs: [ "main.cpp", "test_framework/core/BufferId.cpp", "test_framework/core/EdidBuilder.cpp", "test_framework/core/TestService.cpp", "test_framework/hwc3/DisplayVSyncEventService.cpp", "test_framework/hwc3/FakeComposer.cpp", "test_framework/hwc3/Hwc3Controller.cpp", "test_framework/hwc3/MultiDisplayRefreshEventGenerator.cpp", "test_framework/hwc3/ObservingComposer.cpp", "test_framework/hwc3/SingleDisplayRefreshEventGenerator.cpp", "test_framework/hwc3/SingleDisplayRefreshSchedule.cpp", "test_framework/hwc3/TimeKeeperThread.cpp", Loading
services/surfaceflinger/tests/end2end/test_framework/core/BufferId.cpp 0 → 100644 +67 −0 Original line number Diff line number Diff line /* * Copyright 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <cstdint> #include <string> #include <sys/stat.h> #include <aidl/android/hardware/common/NativeHandle.h> #include <android-base/logging.h> #include <cutils/native_handle.h> #include <fmt/format.h> #include <ftl/cast.h> #include <ui/GraphicBuffer.h> #include <utils/StrongPointer.h> #include "test_framework/core/BufferId.h" namespace android::surfaceflinger::tests::end2end::test_framework::core { namespace { auto bufferFdToBufferId(int rawFd) -> BufferId { struct stat stat{}; const int result = fstat(rawFd, &stat); CHECK(result == 0); CHECK(ftl::cast_safety<uint64_t>(stat.st_ino) == ftl::CastSafety::kSafe); CHECK(ftl::cast_safety<uint64_t>(stat.st_dev) == ftl::CastSafety::kSafe); return {.inode = static_cast<uint64_t>(stat.st_ino), .device = static_cast<uint64_t>(stat.st_dev)}; } } // namespace auto toBufferId(const aidl::android::hardware::common::NativeHandle& handle) -> BufferId { CHECK(!handle.fds.empty()); return bufferFdToBufferId(handle.fds[0].get()); } auto toBufferId(const native_handle_t* handle) -> BufferId { CHECK(handle != nullptr); CHECK(handle->numFds > 0); return bufferFdToBufferId(handle->data[0]); } auto toBufferId(const sp<GraphicBuffer>& buffer) -> BufferId { CHECK(buffer != nullptr); return toBufferId(buffer->getNativeBuffer()->handle); } auto toString(const BufferId& value) -> std::string { return fmt::format("BufferId{{inode: {}, device: {}}}", value.inode, value.device); } } // namespace android::surfaceflinger::tests::end2end::test_framework::core No newline at end of file
services/surfaceflinger/tests/end2end/test_framework/core/BufferId.h 0 → 100644 +46 −0 Original line number Diff line number Diff line /* * Copyright 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <cstdint> #include <string> #include <aidl/android/hardware/common/NativeHandle.h> #include <cutils/native_handle.h> #include <ui/GraphicBuffer.h> #include <utils/StrongPointer.h> namespace android::surfaceflinger::tests::end2end::test_framework::core { struct BufferId final { uint64_t inode; uint64_t device; friend auto operator==(const BufferId&, const BufferId&) -> bool = default; }; auto toBufferId(const native_handle_t* handle) -> BufferId; auto toBufferId(const sp<GraphicBuffer>& buffer) -> BufferId; auto toBufferId(const aidl::android::hardware::common::NativeHandle& handle) -> BufferId; auto toString(const BufferId& value) -> std::string; inline auto format_as(const BufferId& event) -> std::string { return toString(event); } } // namespace android::surfaceflinger::tests::end2end::test_framework::core
services/surfaceflinger/tests/end2end/test_framework/hwc3/Hwc3Controller.cpp +20 −4 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/hwc3/FakeComposer.h" #include "test_framework/hwc3/Hwc3Controller.h" #include "test_framework/hwc3/ObservingComposer.h" namespace android::surfaceflinger::tests::end2end::test_framework::hwc3 { Loading @@ -39,7 +40,7 @@ auto Hwc3Controller::make(std::span<const core::DisplayConfiguration> displays) -> base::expected<std::shared_ptr<hwc3::Hwc3Controller>, std::string> { using namespace std::string_literals; auto controller = std::make_unique<Hwc3Controller>(Passkey{}); auto controller = std::make_shared<Hwc3Controller>(Passkey{}); if (controller == nullptr) { return base::unexpected("Failed to construct the Hwc3Controller instance"s); } Loading @@ -60,8 +61,6 @@ auto Hwc3Controller::init(const std::span<const core::DisplayConfiguration> disp -> base::expected<void, std::string> { using namespace std::string_literals; auto qualifiedServiceName = FakeComposer::getServiceName(baseServiceName); auto fakeComposerResult = FakeComposer::make(); if (!fakeComposerResult) { return base::unexpected(std::move(fakeComposerResult).error()); Loading @@ -72,7 +71,15 @@ auto Hwc3Controller::init(const std::span<const core::DisplayConfiguration> disp fakeComposer->addDisplay(display); } auto binder = fakeComposer->getComposer()->asBinder(); auto observingComposerResult = ObservingComposer::make(shared_from_this(), fakeComposer->getComposer()); if (!observingComposerResult) { return base::unexpected(std::move(observingComposerResult).error()); } auto observingComposer = *std::move(observingComposerResult); const auto qualifiedServiceName = ObservingComposer::getServiceName(baseServiceName); auto binder = observingComposer->getComposer()->asBinder(); // This downgrade allows us to use the fake service name without it being defined in the // VINTF manifest. Loading @@ -86,9 +93,18 @@ auto Hwc3Controller::init(const std::span<const core::DisplayConfiguration> disp LOG(INFO) << "Registered service " << qualifiedServiceName << ". Error: " << status; mFakeComposer = std::move(fakeComposer); mObservingComposer = std::move(observingComposer); return {}; } auto Hwc3Controller::editCallbacks() -> Callbacks& { return mCallbacks; } auto Hwc3Controller::callbacks() const -> const Callbacks& { return mCallbacks; } auto Hwc3Controller::getServiceName() -> std::string { return FakeComposer::getServiceName(baseServiceName); } Loading
services/surfaceflinger/tests/end2end/test_framework/hwc3/Hwc3Controller.h +36 −3 Original line number Diff line number Diff line Loading @@ -22,18 +22,43 @@ #include <android-base/expected.h> #include <aidl/android/hardware/graphics/composer3/PowerMode.h> #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/hwc3/events/ClientDestroyed.h" #include "test_framework/hwc3/events/DisplayPresented.h" #include "test_framework/hwc3/events/PendingBufferSwap.h" #include "test_framework/hwc3/events/PowerMode.h" #include "test_framework/hwc3/events/VSync.h" #include "test_framework/hwc3/events/VSyncEnabled.h" namespace android::surfaceflinger::tests::end2end::test_framework::hwc3 { class FakeComposer; class ObservingComposer; class Hwc3Controller final { class Hwc3Controller final : public std::enable_shared_from_this<Hwc3Controller> { struct Passkey; // Uses the passkey idiom to restrict construction. public: struct Callbacks final { // Invoked when SF destroys its HWC client connection. events::ClientDestroyed::AsyncConnector onClientDestroyed; // Invoked when SF configures the power mode for a display. events::PowerMode::AsyncConnector onPowerModeChanged; // Invoked when SF enables or disables vsync callbacks for a display. events::VSyncEnabled::AsyncConnector onVsyncEnabledChanged; // Invoked when SF presents a display. events::DisplayPresented::AsyncConnector onDisplayPresented; // Invoked when SF is swapping the buffer content of a hardware overlay. events::PendingBufferSwap::AsyncConnector onPendingBufferSwap; // Invoked when the client sends SF a vsync callback. events::VSync::AsyncConnector onVSyncCallbackSent; }; // Gets the service name for the HWC3 instance that will be created and registered [[nodiscard]] static auto getServiceName() -> std::string; Loading @@ -43,6 +68,12 @@ class Hwc3Controller final { explicit Hwc3Controller(Passkey passkey); // Allows the callbacks to be routed. [[nodiscard]] auto editCallbacks() -> Callbacks&; // Allows the callbacks to be sent. [[nodiscard]] auto callbacks() const -> const Callbacks&; // Adds a new display to the HWC3, which will become a hotplug connect event. void addDisplay(const core::DisplayConfiguration& config); Loading @@ -56,6 +87,8 @@ class Hwc3Controller final { -> base::expected<void, std::string>; std::shared_ptr<FakeComposer> mFakeComposer; std::shared_ptr<ObservingComposer> mObservingComposer; Callbacks mCallbacks; }; } // namespace android::surfaceflinger::tests::end2end::test_framework::hwc3