Loading services/surfaceflinger/tests/end2end/Android.bp +2 −3 Original line number Diff line number Diff line Loading @@ -32,11 +32,10 @@ cc_test { ], srcs: [ "main.cpp", "test_framework/core/EdidBuilder.cpp", "test_framework/core/TestService.cpp", "test_framework/fake_hwc3/Hwc3Composer.cpp", "test_framework/fake_hwc3/Hwc3Controller.cpp", "test_framework/hwc3/FakeComposer.cpp", "test_framework/hwc3/Hwc3Controller.cpp", "test_framework/surfaceflinger/SFController.cpp", // Internal tests Loading services/surfaceflinger/tests/end2end/test_framework/core/GuardedSharedState.h 0 → 100644 +55 −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 <functional> #include <mutex> #include <shared_mutex> #include <type_traits> namespace android::surfaceflinger::tests::end2end::test_framework::core { // Ensures all access to a state structure `SharedState` is done while holding an appropriate // `std::shared_mutex` lock. // // This works around limitations with Clang thread safety analysis when using `std::shared_lock`, as // there will be a compiler diagnostic despite acquiring the lock. template <typename SharedState> class GuardedSharedState final { public: // Allows shared read-only access to the state. The lambda is invoked with a `const // SharedState&` first argument referencing the state. template <typename F> auto withSharedLock(F&& continuation) const -> std::invoke_result_t<F, const SharedState&> { const std::shared_lock lock(mMutex); return std::invoke(std::forward<F>(continuation), mState); } // Allows exclusive read/write access to the state. The lambda is invoked with a `SharedState&` // first argument referencing the state. template <typename F> auto withExclusiveLock(F&& continuation) -> std::invoke_result_t<F, SharedState&> { const std::lock_guard lock(mMutex); return std::invoke(std::forward<F>(continuation), mState); } private: mutable std::shared_mutex mMutex; SharedState mState; }; } // namespace android::surfaceflinger::tests::end2end::test_framework::core services/surfaceflinger/tests/end2end/test_framework/core/TestService.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/core/TestService.h" #include "test_framework/fake_hwc3/Hwc3Controller.h" #include "test_framework/hwc3/Hwc3Controller.h" #include "test_framework/surfaceflinger/SFController.h" namespace android::surfaceflinger::tests::end2end::test_framework::core { Loading Loading @@ -56,7 +56,7 @@ auto TestService::init(std::span<const DisplayConfiguration> displays) -> base::expected<void, std::string> { using namespace std::string_literals; auto hwcResult = fake_hwc3::Hwc3Controller::make(displays); auto hwcResult = hwc3::Hwc3Controller::make(displays); if (!hwcResult) { return base::unexpected(std::move(hwcResult).error()); } Loading @@ -68,7 +68,7 @@ auto TestService::init(std::span<const DisplayConfiguration> displays) } auto flinger = *std::move(flingerResult); surfaceflinger::SFController::useHwcService(fake_hwc3::Hwc3Controller::getServiceName()); surfaceflinger::SFController::useHwcService(hwc3::Hwc3Controller::getServiceName()); if (auto result = flinger->startAndConnect(); !result) { return base::unexpected(std::move(result).error()); Loading services/surfaceflinger/tests/end2end/test_framework/core/TestService.h +4 −4 Original line number Diff line number Diff line Loading @@ -34,11 +34,11 @@ class SFController; } // namespace surfaceflinger namespace fake_hwc3 { namespace hwc3 { class Hwc3Controller; } // namespace fake_hwc3 } // namespace hwc3 namespace core { Loading @@ -53,7 +53,7 @@ class TestService final { explicit TestService(Passkey passkey); // Obtains the HWC3 back-end controller [[nodiscard]] auto hwc() -> fake_hwc3::Hwc3Controller& { [[nodiscard]] auto hwc() -> hwc3::Hwc3Controller& { CHECK(mHwc); return *mHwc; } Loading @@ -68,7 +68,7 @@ class TestService final { [[nodiscard]] auto init(std::span<const DisplayConfiguration> displays) -> base::expected<void, std::string>; std::shared_ptr<fake_hwc3::Hwc3Controller> mHwc; std::shared_ptr<hwc3::Hwc3Controller> mHwc; std::shared_ptr<surfaceflinger::SFController> mFlinger; }; Loading services/surfaceflinger/tests/end2end/test_framework/fake_hwc3/Hwc3Composer.cppdeleted 100644 → 0 +0 −123 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 <memory> #include <string> #include <string_view> #include <utility> #include <vector> #include <aidl/android/hardware/graphics/composer3/BnComposer.h> #include <aidl/android/hardware/graphics/composer3/Capability.h> #include <aidl/android/hardware/graphics/composer3/IComposer.h> #include <aidl/android/hardware/graphics/composer3/PowerMode.h> #include <android-base/expected.h> #include <android-base/logging.h> #include <android/binder_auto_utils.h> #include <android/binder_interface_utils.h> #include <android/binder_status.h> #include <ftl/ignore.h> #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/fake_hwc3/Hwc3Composer.h" namespace android::surfaceflinger::tests::end2end::test_framework::fake_hwc3 { class Hwc3Composer::Hwc3ComposerImpl final : public aidl::android::hardware::graphics::composer3::BnComposer { using Capability = aidl::android::hardware::graphics::composer3::Capability; using IComposerClient = aidl::android::hardware::graphics::composer3::IComposerClient; using Hwc3PowerMode = aidl::android::hardware::graphics::composer3::PowerMode; // begin IComposer overrides auto dump(int dumpFd, const char** args, uint32_t num_args) -> binder_status_t override { UNIMPLEMENTED(WARNING); ftl::ignore(dumpFd, args, num_args); return static_cast<binder_status_t>(STATUS_NO_MEMORY); } auto createClient(std::shared_ptr<IComposerClient>* out_client) -> ndk::ScopedAStatus override { UNIMPLEMENTED(WARNING); ftl::ignore(out_client); return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage( IComposer::EX_NO_RESOURCES, "Client failed to initialize"); } auto getCapabilities(std::vector<Capability>* out_capabilities) -> ndk::ScopedAStatus override { UNIMPLEMENTED(WARNING); ftl::ignore(out_capabilities); return ndk::ScopedAStatus::ok(); } // end IComposer overrides }; struct Hwc3Composer::Passkey final {}; auto Hwc3Composer::getServiceName(std::string_view baseServiceName) -> std::string { return Hwc3ComposerImpl::makeServiceName(baseServiceName); } auto Hwc3Composer::make() -> base::expected<std::shared_ptr<Hwc3Composer>, std::string> { using namespace std::string_literals; auto composer = std::make_shared<Hwc3Composer>(Passkey{}); if (composer == nullptr) { return base::unexpected("Failed to construct the Hwc3Composer instance."s); } if (auto result = composer->init(); !result) { return base::unexpected("Failed to init the Hwc3Composer instance: "s + result.error()); } return composer; } Hwc3Composer::Hwc3Composer(Hwc3Composer::Passkey passkey) { ftl::ignore(passkey); } auto Hwc3Composer::init() -> base::expected<void, std::string> { using namespace std::string_literals; auto impl = ndk::SharedRefBase::make<Hwc3ComposerImpl>(); if (!impl) { return base::unexpected("Failed to construct the Hwc3ComposerImpl instance."s); } mImpl = std::move(impl); return {}; } auto Hwc3Composer::getComposer() -> std::shared_ptr<Hwc3IComposer> { return mImpl; } void Hwc3Composer::addDisplay(const core::DisplayConfiguration& display) { UNIMPLEMENTED(WARNING); ftl::ignore(display, mImpl); } void Hwc3Composer::removeDisplay(core::DisplayConfiguration::Id displayId) { UNIMPLEMENTED(WARNING); ftl::ignore(displayId, mImpl); } } // namespace android::surfaceflinger::tests::end2end::test_framework::fake_hwc3 Loading
services/surfaceflinger/tests/end2end/Android.bp +2 −3 Original line number Diff line number Diff line Loading @@ -32,11 +32,10 @@ cc_test { ], srcs: [ "main.cpp", "test_framework/core/EdidBuilder.cpp", "test_framework/core/TestService.cpp", "test_framework/fake_hwc3/Hwc3Composer.cpp", "test_framework/fake_hwc3/Hwc3Controller.cpp", "test_framework/hwc3/FakeComposer.cpp", "test_framework/hwc3/Hwc3Controller.cpp", "test_framework/surfaceflinger/SFController.cpp", // Internal tests Loading
services/surfaceflinger/tests/end2end/test_framework/core/GuardedSharedState.h 0 → 100644 +55 −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 <functional> #include <mutex> #include <shared_mutex> #include <type_traits> namespace android::surfaceflinger::tests::end2end::test_framework::core { // Ensures all access to a state structure `SharedState` is done while holding an appropriate // `std::shared_mutex` lock. // // This works around limitations with Clang thread safety analysis when using `std::shared_lock`, as // there will be a compiler diagnostic despite acquiring the lock. template <typename SharedState> class GuardedSharedState final { public: // Allows shared read-only access to the state. The lambda is invoked with a `const // SharedState&` first argument referencing the state. template <typename F> auto withSharedLock(F&& continuation) const -> std::invoke_result_t<F, const SharedState&> { const std::shared_lock lock(mMutex); return std::invoke(std::forward<F>(continuation), mState); } // Allows exclusive read/write access to the state. The lambda is invoked with a `SharedState&` // first argument referencing the state. template <typename F> auto withExclusiveLock(F&& continuation) -> std::invoke_result_t<F, SharedState&> { const std::lock_guard lock(mMutex); return std::invoke(std::forward<F>(continuation), mState); } private: mutable std::shared_mutex mMutex; SharedState mState; }; } // namespace android::surfaceflinger::tests::end2end::test_framework::core
services/surfaceflinger/tests/end2end/test_framework/core/TestService.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/core/TestService.h" #include "test_framework/fake_hwc3/Hwc3Controller.h" #include "test_framework/hwc3/Hwc3Controller.h" #include "test_framework/surfaceflinger/SFController.h" namespace android::surfaceflinger::tests::end2end::test_framework::core { Loading Loading @@ -56,7 +56,7 @@ auto TestService::init(std::span<const DisplayConfiguration> displays) -> base::expected<void, std::string> { using namespace std::string_literals; auto hwcResult = fake_hwc3::Hwc3Controller::make(displays); auto hwcResult = hwc3::Hwc3Controller::make(displays); if (!hwcResult) { return base::unexpected(std::move(hwcResult).error()); } Loading @@ -68,7 +68,7 @@ auto TestService::init(std::span<const DisplayConfiguration> displays) } auto flinger = *std::move(flingerResult); surfaceflinger::SFController::useHwcService(fake_hwc3::Hwc3Controller::getServiceName()); surfaceflinger::SFController::useHwcService(hwc3::Hwc3Controller::getServiceName()); if (auto result = flinger->startAndConnect(); !result) { return base::unexpected(std::move(result).error()); Loading
services/surfaceflinger/tests/end2end/test_framework/core/TestService.h +4 −4 Original line number Diff line number Diff line Loading @@ -34,11 +34,11 @@ class SFController; } // namespace surfaceflinger namespace fake_hwc3 { namespace hwc3 { class Hwc3Controller; } // namespace fake_hwc3 } // namespace hwc3 namespace core { Loading @@ -53,7 +53,7 @@ class TestService final { explicit TestService(Passkey passkey); // Obtains the HWC3 back-end controller [[nodiscard]] auto hwc() -> fake_hwc3::Hwc3Controller& { [[nodiscard]] auto hwc() -> hwc3::Hwc3Controller& { CHECK(mHwc); return *mHwc; } Loading @@ -68,7 +68,7 @@ class TestService final { [[nodiscard]] auto init(std::span<const DisplayConfiguration> displays) -> base::expected<void, std::string>; std::shared_ptr<fake_hwc3::Hwc3Controller> mHwc; std::shared_ptr<hwc3::Hwc3Controller> mHwc; std::shared_ptr<surfaceflinger::SFController> mFlinger; }; Loading
services/surfaceflinger/tests/end2end/test_framework/fake_hwc3/Hwc3Composer.cppdeleted 100644 → 0 +0 −123 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 <memory> #include <string> #include <string_view> #include <utility> #include <vector> #include <aidl/android/hardware/graphics/composer3/BnComposer.h> #include <aidl/android/hardware/graphics/composer3/Capability.h> #include <aidl/android/hardware/graphics/composer3/IComposer.h> #include <aidl/android/hardware/graphics/composer3/PowerMode.h> #include <android-base/expected.h> #include <android-base/logging.h> #include <android/binder_auto_utils.h> #include <android/binder_interface_utils.h> #include <android/binder_status.h> #include <ftl/ignore.h> #include "test_framework/core/DisplayConfiguration.h" #include "test_framework/fake_hwc3/Hwc3Composer.h" namespace android::surfaceflinger::tests::end2end::test_framework::fake_hwc3 { class Hwc3Composer::Hwc3ComposerImpl final : public aidl::android::hardware::graphics::composer3::BnComposer { using Capability = aidl::android::hardware::graphics::composer3::Capability; using IComposerClient = aidl::android::hardware::graphics::composer3::IComposerClient; using Hwc3PowerMode = aidl::android::hardware::graphics::composer3::PowerMode; // begin IComposer overrides auto dump(int dumpFd, const char** args, uint32_t num_args) -> binder_status_t override { UNIMPLEMENTED(WARNING); ftl::ignore(dumpFd, args, num_args); return static_cast<binder_status_t>(STATUS_NO_MEMORY); } auto createClient(std::shared_ptr<IComposerClient>* out_client) -> ndk::ScopedAStatus override { UNIMPLEMENTED(WARNING); ftl::ignore(out_client); return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage( IComposer::EX_NO_RESOURCES, "Client failed to initialize"); } auto getCapabilities(std::vector<Capability>* out_capabilities) -> ndk::ScopedAStatus override { UNIMPLEMENTED(WARNING); ftl::ignore(out_capabilities); return ndk::ScopedAStatus::ok(); } // end IComposer overrides }; struct Hwc3Composer::Passkey final {}; auto Hwc3Composer::getServiceName(std::string_view baseServiceName) -> std::string { return Hwc3ComposerImpl::makeServiceName(baseServiceName); } auto Hwc3Composer::make() -> base::expected<std::shared_ptr<Hwc3Composer>, std::string> { using namespace std::string_literals; auto composer = std::make_shared<Hwc3Composer>(Passkey{}); if (composer == nullptr) { return base::unexpected("Failed to construct the Hwc3Composer instance."s); } if (auto result = composer->init(); !result) { return base::unexpected("Failed to init the Hwc3Composer instance: "s + result.error()); } return composer; } Hwc3Composer::Hwc3Composer(Hwc3Composer::Passkey passkey) { ftl::ignore(passkey); } auto Hwc3Composer::init() -> base::expected<void, std::string> { using namespace std::string_literals; auto impl = ndk::SharedRefBase::make<Hwc3ComposerImpl>(); if (!impl) { return base::unexpected("Failed to construct the Hwc3ComposerImpl instance."s); } mImpl = std::move(impl); return {}; } auto Hwc3Composer::getComposer() -> std::shared_ptr<Hwc3IComposer> { return mImpl; } void Hwc3Composer::addDisplay(const core::DisplayConfiguration& display) { UNIMPLEMENTED(WARNING); ftl::ignore(display, mImpl); } void Hwc3Composer::removeDisplay(core::DisplayConfiguration::Id displayId) { UNIMPLEMENTED(WARNING); ftl::ignore(displayId, mImpl); } } // namespace android::surfaceflinger::tests::end2end::test_framework::fake_hwc3