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

Commit 2102afa1 authored by Lloyd Pique's avatar Lloyd Pique
Browse files

end2end: Allow tests to create surfaces with buffers [7/N]

Flag: TEST_ONLY
Bug: 372735083
Test: atest surfaceflinger_end2end_tests
Change-Id: I6967722a19f1716bda1ecf438be0511a82497f9a
parent e65f95f7
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@ cc_test {
        "test_framework/hwc3/SingleDisplayRefreshSchedule.cpp",
        "test_framework/hwc3/TimeKeeperThread.cpp",
        "test_framework/surfaceflinger/SFController.cpp",
        "test_framework/surfaceflinger/SimpleBufferPool.cpp",
        "test_framework/surfaceflinger/Surface.cpp",

        // Internal tests
        "tests/internal/AsyncFunction_test.cpp",
+7 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include <utils/StrongPointer.h>

#include "test_framework/surfaceflinger/SFController.h"
#include "test_framework/surfaceflinger/Surface.h"

namespace android::surfaceflinger::tests::end2end::test_framework::surfaceflinger {

@@ -178,4 +179,10 @@ void SFController::stop() {
    mSurfaceComposerAidl = nullptr;
}

auto SFController::makeSurface(const Surface::CreationArgs& args)
        -> base::expected<std::shared_ptr<Surface>, std::string> {
    CHECK(mSurfaceComposerClient != nullptr);
    return Surface::make(mSurfaceComposerClient, args);
}

}  // namespace android::surfaceflinger::tests::end2end::test_framework::surfaceflinger
+5 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@
#include <ftl/finalizer.h>
#include <utils/StrongPointer.h>

#include "test_framework/surfaceflinger/Surface.h"

namespace android::gui {

class ISurfaceComposer;
@@ -54,6 +56,9 @@ class SFController final {
    // Starts SurfaceFlinger and establishes the AIDL interface connections.
    [[nodiscard]] auto startAndConnect() -> base::expected<void, std::string>;

    auto makeSurface(const Surface::CreationArgs& args)
            -> base::expected<std::shared_ptr<Surface>, std::string>;

  private:
    [[nodiscard]] auto init() -> base::expected<void, std::string>;
    static void start();
+101 −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 <bit>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>

#include <android-base/expected.h>
#include <android-base/logging.h>
#include <ftl/ignore.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/PixelFormat.h>
#include <ui/Size.h>
#include <utils/StrongPointer.h>

#include "test_framework/core/GuardedSharedState.h"
#include "test_framework/surfaceflinger/SimpleBufferPool.h"

namespace android::surfaceflinger::tests::end2end::test_framework::surfaceflinger {

struct SimpleBufferPool::Passkey final {};

auto SimpleBufferPool::make(size_t count, ui::Size size, PixelFormat format)
        -> base::expected<std::shared_ptr<SimpleBufferPool>, std::string> {
    using namespace std::string_literals;

    auto instance = std::make_unique<SimpleBufferPool>(Passkey{});
    if (instance == nullptr) {
        return base::unexpected("Failed to construct a SimpleBufferPool"s);
    }
    if (auto result = instance->init(count, size, format); !result) {
        return base::unexpected("Failed to init a SimpleBufferPool: " + result.error());
    }
    return std::move(instance);
}

SimpleBufferPool::SimpleBufferPool(Passkey passkey) {
    ftl::ignore(passkey);
}

auto SimpleBufferPool::init(size_t count, ui::Size size,
                            PixelFormat format) -> base::expected<void, std::string> {
    return mState.withExclusiveLock(
            [count, size, format](auto& state) -> base::expected<void, std::string> {
                for (size_t i = 0; i < count; i++) {
                    constexpr auto kLayers = 1;
                    constexpr auto kUsage = GraphicBuffer::USAGE_HW_COMPOSER;
                    const GraphicBufferAllocator::AllocationRequest request{
                            .importBuffer = false,
                            .width = std::bit_cast<uint32_t>(size.width),
                            .height = std::bit_cast<uint32_t>(size.height),
                            .format = format,
                            .layerCount = kLayers,
                            .usage = kUsage,
                            .requestorName = "test",
                            .extras = {},
                    };
                    state.pool.push_back(sp<GraphicBuffer>::make(request));
                    CHECK(state.pool.back() != nullptr);
                }
                return {};
            });
}

auto SimpleBufferPool::dequeue() -> sp<GraphicBuffer> {
    return mState.withExclusiveLock([](auto& state) -> sp<GraphicBuffer> {
        if (state.pool.empty()) {
            return nullptr;
        }
        auto buffer = state.pool.front();
        CHECK(buffer != nullptr);
        state.pool.pop_front();
        return buffer;
    });
};

void SimpleBufferPool::enqueue(sp<GraphicBuffer> buffer) {
    CHECK(buffer != nullptr);
    mState.withExclusiveLock([buffer = std::move(buffer)](auto& state) mutable {
        state.pool.push_back(std::move(buffer));
    });
};

}  // namespace android::surfaceflinger::tests::end2end::test_framework::surfaceflinger
+57 −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 <cstddef>
#include <deque>
#include <memory>
#include <string>

#include <android-base/expected.h>
#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>
#include <ui/Size.h>
#include <utils/Mutex.h>
#include <utils/StrongPointer.h>

#include "test_framework/core/GuardedSharedState.h"

namespace android::surfaceflinger::tests::end2end::test_framework::surfaceflinger {

class SimpleBufferPool final {
    struct Passkey;  // Uses the passkey idiom to restrict construction.

  public:
    [[nodiscard]] static auto make(size_t count, ui::Size size, PixelFormat format)
            -> base::expected<std::shared_ptr<SimpleBufferPool>, std::string>;

    explicit SimpleBufferPool(Passkey passkey);

    auto dequeue() -> sp<GraphicBuffer>;
    void enqueue(sp<GraphicBuffer> buffer);

  private:
    [[nodiscard]] auto init(size_t count, ui::Size size,
                            PixelFormat format) -> base::expected<void, std::string>;

    struct State {
        std::deque<sp<GraphicBuffer>> pool;
    };
    core::GuardedSharedState<State> mState;
};

}  // namespace android::surfaceflinger::tests::end2end::test_framework::surfaceflinger
Loading