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

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

Merge "end2end: Introduce Hwc3 observer [6/N]" into main

parents a883a62f e65f95f7
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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",
+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
+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
+20 −4
Original line number Diff line number Diff line
@@ -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 {

@@ -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);
    }
@@ -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());
@@ -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.
@@ -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);
}
+36 −3
Original line number Diff line number Diff line
@@ -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;

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

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