blob: 33dc16dde7e60c5b3f4f7a82f9d14ce60b1da59a [file] [log] [blame] [edit]
// Copyright 2025 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/graphics/display/lib/fake-display-stack/fake-coordinator-harness.h"
#include <fidl/fuchsia.hardware.display.engine/cpp/wire.h>
#include <fidl/fuchsia.hardware.display/cpp/wire.h>
#include <zircon/assert.h>
#include <zircon/status.h>
#include <memory>
#include <utility>
#include "src/graphics/display/drivers/coordinator/controller.h"
#include "src/graphics/display/drivers/coordinator/engine-driver-client-fidl.h"
namespace fake_display {
FakeCoordinatorHarness::FakeCoordinatorHarness(
fdf_testing::DriverRuntime* driver_runtime,
fdf::ClientEnd<fuchsia_hardware_display_engine::Engine> engine_client)
: driver_runtime_(*driver_runtime),
coordinator_driver_dispatcher_(driver_runtime_.StartBackgroundDispatcher()),
coordinator_controller_(coordinator_driver_dispatcher_->async_dispatcher(), std::in_place),
outgoing_(coordinator_driver_dispatcher_->async_dispatcher(), std::in_place,
async_patterns::PassDispatcher) {
ZX_ASSERT(driver_runtime != nullptr);
coordinator_controller_.SyncCall(
[&](std::unique_ptr<display_coordinator::Controller>* controller) {
auto engine_driver_client =
std::make_unique<display_coordinator::EngineDriverClientFidl>(std::move(engine_client));
zx::result<std::unique_ptr<display_coordinator::Controller>> create_result =
display_coordinator::Controller::Create(std::move(engine_driver_client),
coordinator_driver_dispatcher_->borrow());
ZX_ASSERT_MSG(create_result.is_ok(),
"Failed to create display coordinator Controller device: %s",
create_result.status_string());
*controller = std::move(create_result).value();
});
fidl::ProtocolHandler<fuchsia_hardware_display::Provider> provider_handler =
coordinator_controller_.SyncCall(
[&](std::unique_ptr<display_coordinator::Controller>* controller) {
return (*controller)->bind_handler(coordinator_driver_dispatcher_->async_dispatcher());
});
fuchsia_hardware_display::Service::InstanceHandler service_handler({
.provider = std::move(provider_handler),
});
zx::result<> add_service_result = outgoing_.SyncCall([&](component::OutgoingDirectory* outgoing) {
return outgoing->AddService<fuchsia_hardware_display::Service>(std::move(service_handler));
});
ZX_ASSERT_MSG(add_service_result.is_ok(), "Failed to add display service: %s",
add_service_result.status_string());
}
FakeCoordinatorHarness::~FakeCoordinatorHarness() {
ZX_ASSERT_MSG(shutdown_, "SyncShutdown() not called before FakeCoordinatorHarness destruction");
}
void FakeCoordinatorHarness::SyncShutdown() {
if (shutdown_) {
// SyncShutdown() was already called.
return;
}
shutdown_ = true;
outgoing_.reset();
coordinator_controller_.SyncCall(
[&](std::unique_ptr<display_coordinator::Controller>* controller) {
(*controller)->PrepareStop();
});
std::unique_ptr<display_coordinator::Controller> controller_to_reset =
coordinator_controller_.SyncCall(
[&](std::unique_ptr<display_coordinator::Controller>* controller) {
return std::move(*controller);
});
libsync::Completion coordinator_is_shut_down;
driver_runtime_.ShutdownBackgroundDispatcher(coordinator_driver_dispatcher_->get(), [&] {
controller_to_reset.reset();
coordinator_is_shut_down.Signal();
});
coordinator_is_shut_down.Wait();
}
fidl::ClientEnd<fuchsia_io::Directory> FakeCoordinatorHarness::Serve() {
ZX_ASSERT_MSG(!shutdown_, "Serve() called after SyncShutdown()");
auto [directory_client_end, directory_server_end] =
fidl::Endpoints<fuchsia_io::Directory>::Create();
zx::result<> serve_result =
outgoing_.SyncCall(&component::OutgoingDirectory::Serve, std::move(directory_server_end));
ZX_ASSERT_MSG(serve_result.is_ok(), "Failed to serve to outgoing directory: %s",
serve_result.status_string());
return std::move(directory_client_end);
}
void FakeCoordinatorHarness::ServeToProcessOutgoingDirectory() {
ZX_ASSERT_MSG(!shutdown_, "ServeToProcessOutgoingDirectory() called after SyncShutdown()");
zx::result<> serve_result =
outgoing_.SyncCall(&component::OutgoingDirectory::ServeFromStartupInfo);
ZX_ASSERT_MSG(serve_result.is_ok(), "Failed to serve to process outgoing directory: %s",
serve_result.status_string());
}
} // namespace fake_display