blob: 05b1844afcf3465953eb17b31d7b8d88926b77bc [file] [log] [blame]
// Copyright 2022 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.
use anyhow::Error;
use fidl::endpoints::ControlHandle;
use fidl_fuchsia_logger::LogSinkMarker;
use fidl_fuchsia_scheduler::RoleManagerMarker;
use fidl_fuchsia_tracing_provider::RegistryMarker;
use fidl_fuchsia_ui_composition::FlatlandMarker;
use fidl_fuchsia_ui_display_singleton::InfoMarker;
use fidl_fuchsia_ui_focus::FocusChainListenerRegistryMarker;
use fidl_fuchsia_ui_input3::KeyboardMarker;
use fidl_fuchsia_ui_policy::DeviceListenerRegistryMarker;
use fidl_fuchsia_vulkan_loader::LoaderMarker;
use fuchsia_component::server::ServiceFs;
use fuchsia_component_test::{Capability, ChildOptions, RealmBuilder, RealmInstance, Ref, Route};
use futures::{StreamExt, TryStreamExt};
use {
fidl_fuchsia_sysmem as fsysmem, fidl_fuchsia_sysmem2 as fsysmem2,
fidl_fuchsia_ui_test_context as ui_test_context, fidl_fuchsia_ui_test_input as ui_input,
fidl_fuchsia_ui_test_scene as test_scene, fuchsia_async as fasync,
fuchsia_zircon_status as zx_status,
};
// TODO(https://fxbug.dev/42069041): Use subpackages here.
const TEST_UI_STACK: &str = "ui";
const TEST_UI_STACK_URL: &str = "#meta/test-ui-stack.cm";
/// All FIDL services that are exposed by this component's ServiceFs.
enum Service {
RealmFactoryServer(ui_test_context::RealmFactoryRequestStream),
}
#[fuchsia::main(logging_tags = ["ui_launcher"])]
async fn main() -> Result<(), Error> {
let mut fs = ServiceFs::new_local();
fs.dir("svc").add_fidl_service(Service::RealmFactoryServer);
fs.take_and_serve_directory_handle()?;
fs.for_each_concurrent(None, |conn| async move {
match conn {
Service::RealmFactoryServer(stream) => run_realm_factory_server(stream).await,
}
})
.await;
Ok(())
}
async fn run_realm_factory_server(stream: ui_test_context::RealmFactoryRequestStream) {
stream
.try_for_each_concurrent(None, |request| async {
tracing::debug!("received a request: {:?}", &request);
let mut task_group = fasync::TaskGroup::new();
match request {
ui_test_context::RealmFactoryRequest::CreateRealm { payload, responder } => {
let realm_server = payload.realm_server.expect("missing realm_server");
// Create the puppet + ui stack for this test context.
let realm =
assemble_puppet_realm(payload.display_rotation, payload.device_pixel_ratio)
.await;
let request_stream = realm_server.into_stream().expect("into stream");
task_group.spawn(async move {
realm_proxy::service::serve(realm, request_stream)
.await
.expect("invalid realm proxy server");
});
responder.send(Ok(())).expect("failed to response");
}
ui_test_context::RealmFactoryRequest::_UnknownMethod { control_handle, .. } => {
tracing::warn!("realm factory receive an unknown request");
control_handle.shutdown_with_epitaph(zx_status::Status::NOT_SUPPORTED);
unimplemented!();
}
}
task_group.join().await;
Ok(())
})
.await
.expect("failed to serve test realm factory request stream");
}
async fn assemble_puppet_realm(
display_rotation: Option<u32>,
device_pixel_ratio: Option<f32>,
) -> RealmInstance {
let builder = RealmBuilder::new().await.expect("Failed to create RealmBuilder.");
// Add test UI stack component.
let ui_stack = builder
.add_child(TEST_UI_STACK, TEST_UI_STACK_URL, ChildOptions::new())
.await
.expect("Failed to add UI realm.");
builder
.init_mutable_config_from_package(&ui_stack)
.await
.expect("Failed to init config for ui_stack");
match display_rotation {
Some(display_rotation) => {
builder
.set_config_value(&ui_stack, "display_rotation", display_rotation.into())
.await
.expect("Failed to set display_rotation.");
}
None => {}
}
match device_pixel_ratio {
Some(device_pixel_ratio) => {
builder
.set_config_value(
&ui_stack,
"device_pixel_ratio",
device_pixel_ratio.to_string().into(),
)
.await
.expect("Failed to set device_pixel_ratio.");
}
None => {}
}
// Route capabilities to the test UI stack.
builder
.add_route(
Route::new()
.capability(Capability::protocol::<LogSinkMarker>())
.capability(Capability::protocol::<RoleManagerMarker>())
.capability(Capability::protocol::<fsysmem::AllocatorMarker>())
.capability(Capability::protocol::<fsysmem2::AllocatorMarker>())
.capability(Capability::protocol::<LoaderMarker>())
.capability(Capability::protocol::<RegistryMarker>())
.from(Ref::parent())
.to(Ref::child(TEST_UI_STACK)),
)
.await
.expect("Failed to route capabilities.");
// Expose UI capabilities.
builder
.add_route(
Route::new()
.capability(Capability::protocol::<test_scene::ControllerMarker>())
.capability(Capability::protocol::<FlatlandMarker>())
.capability(Capability::protocol::<KeyboardMarker>())
.capability(Capability::protocol::<InfoMarker>())
.capability(Capability::protocol::<FocusChainListenerRegistryMarker>())
.capability(Capability::protocol::<ui_input::RegistryMarker>())
.capability(Capability::protocol::<DeviceListenerRegistryMarker>())
.from(Ref::child(TEST_UI_STACK))
.to(Ref::parent()),
)
.await
.expect("Failed to route capabilities.");
builder
.add_route(
Route::new()
.capability(Capability::storage("tmp"))
.from(Ref::parent())
.to(Ref::child(TEST_UI_STACK)),
)
.await
.expect("Failed to route capabilities.");
// Create the test realm.
builder.build().await.expect("Failed to create test realm.")
}