Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 59168917 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "end2end: Implement a fake IComposerClient [4/N]" into main

parents 4cff1c71 585e3f87
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -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
+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
+3 −3
Original line number Diff line number Diff line
@@ -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 {
@@ -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());
    }
@@ -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());
+4 −4
Original line number Diff line number Diff line
@@ -34,11 +34,11 @@ class SFController;

}  // namespace surfaceflinger

namespace fake_hwc3 {
namespace hwc3 {

class Hwc3Controller;

}  // namespace fake_hwc3
}  // namespace hwc3

namespace core {

@@ -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;
    }
@@ -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;
};

+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