blob: 929a300e84ba06d5aab6f6ea1edc06889d803e50 [file] [log] [blame]
// Copyright 2016 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 "garnet/bin/appmgr/namespace.h"
#include <fuchsia/device/manager/cpp/fidl.h>
#include <fuchsia/kernel/cpp/fidl.h>
#include <fuchsia/process/cpp/fidl.h>
#include <fuchsia/scheduler/cpp/fidl.h>
#include <fuchsia/virtualconsole/cpp/fidl.h>
#include <lib/async/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <trace/event.h>
#include <utility>
#include "garnet/bin/appmgr/job_provider_impl.h"
#include "garnet/bin/appmgr/realm.h"
#include "garnet/bin/appmgr/util.h"
namespace component {
Namespace::Namespace(fxl::RefPtr<Namespace> parent, Realm* realm,
fuchsia::sys::ServiceListPtr additional_services,
const std::vector<std::string>* service_whitelist)
: vfs_(async_get_default_dispatcher()),
services_(fbl::AdoptRef(new ServiceProviderDirImpl(service_whitelist))),
job_provider_(fbl::AdoptRef(new JobProviderImpl(realm))),
realm_(realm) {
services_->AddService(
fuchsia::sys::Environment::Name_,
fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
environment_bindings_.AddBinding(
this, fidl::InterfaceRequest<fuchsia::sys::Environment>(
std::move(channel)));
return ZX_OK;
})));
services_->AddService(
Launcher::Name_,
fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
launcher_bindings_.AddBinding(
this, fidl::InterfaceRequest<Launcher>(std::move(channel)));
return ZX_OK;
})));
services_->AddService(
fuchsia::process::Launcher::Name_,
fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
realm_->environment_services()->Connect(
fidl::InterfaceRequest<fuchsia::process::Launcher>(
std::move(channel)));
return ZX_OK;
})));
services_->AddService(
fuchsia::process::Resolver::Name_,
fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
resolver_bindings_.AddBinding(
this, fidl::InterfaceRequest<fuchsia::process::Resolver>(
std::move(channel)));
return ZX_OK;
})));
services_->AddService(
fuchsia::scheduler::ProfileProvider::Name_,
fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
realm_->environment_services()->Connect(
fidl::InterfaceRequest<fuchsia::scheduler::ProfileProvider>(
std::move(channel)));
return ZX_OK;
})));
services_->AddService(
fuchsia::kernel::DebugBroker::Name_,
fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
realm_->environment_services()->Connect(
fidl::InterfaceRequest<fuchsia::kernel::DebugBroker>(
std::move(channel)));
return ZX_OK;
})));
services_->AddService(
fuchsia::device::manager::DebugDumper::Name_,
fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
realm_->environment_services()->Connect(
fidl::InterfaceRequest<fuchsia::device::manager::DebugDumper>(
std::move(channel)));
return ZX_OK;
})));
services_->AddService(
fuchsia::device::manager::Administrator::Name_,
fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
realm_->environment_services()->Connect(
fidl::InterfaceRequest<fuchsia::device::manager::Administrator>(
std::move(channel)));
return ZX_OK;
})));
services_->AddService(
fuchsia::virtualconsole::SessionManager::Name_,
fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
realm_->environment_services()->Connect(
fidl::InterfaceRequest<fuchsia::virtualconsole::SessionManager>(
std::move(channel)));
return ZX_OK;
})));
if (additional_services) {
auto& names = additional_services->names;
service_provider_ = additional_services->provider.Bind();
service_host_directory_ = std::move(additional_services->host_directory);
for (auto& name : names) {
if (service_host_directory_) {
services_->AddService(
name,
fbl::AdoptRef(new fs::Service([this, name](zx::channel channel) {
fdio_service_connect_at(service_host_directory_.get(),
name.c_str(), channel.release());
return ZX_OK;
})));
} else {
services_->AddService(
name,
fbl::AdoptRef(new fs::Service([this, name](zx::channel channel) {
service_provider_->ConnectToService(name, std::move(channel));
return ZX_OK;
})));
}
}
}
// If any services in |parent| share a name with |additional_services|,
// |additional_services| takes priority.
if (parent) {
services_->set_parent(parent->services());
}
}
Namespace::~Namespace() {}
void Namespace::AddBinding(
fidl::InterfaceRequest<fuchsia::sys::Environment> environment) {
environment_bindings_.AddBinding(this, std::move(environment));
}
void Namespace::CreateNestedEnvironment(
fidl::InterfaceRequest<fuchsia::sys::Environment> environment,
fidl::InterfaceRequest<fuchsia::sys::EnvironmentController> controller,
std::string label, fuchsia::sys::ServiceListPtr additional_services,
fuchsia::sys::EnvironmentOptions options) {
realm_->CreateNestedEnvironment(std::move(environment), std::move(controller),
std::move(label),
std::move(additional_services), options);
}
void Namespace::GetLauncher(fidl::InterfaceRequest<Launcher> launcher) {
launcher_bindings_.AddBinding(this, std::move(launcher));
}
void Namespace::GetServices(
fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> services) {
services_->AddBinding(std::move(services));
}
zx_status_t Namespace::ServeServiceDirectory(zx::channel directory_request) {
return vfs_.ServeDirectory(services_, std::move(directory_request));
}
void Namespace::CreateComponent(
fuchsia::sys::LaunchInfo launch_info,
fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
auto cc_trace_id = TRACE_NONCE();
TRACE_ASYNC_BEGIN("appmgr", "Namespace::CreateComponent", cc_trace_id,
"launch_info.url", launch_info.url);
realm_->CreateComponent(
std::move(launch_info), std::move(controller),
[cc_trace_id](std::weak_ptr<ComponentControllerImpl> component) {
TRACE_ASYNC_END("appmgr", "Namespace::CreateComponent", cc_trace_id);
});
}
zx::channel Namespace::OpenServicesAsDirectory() {
return Util::OpenAsDirectory(&vfs_, services_);
}
void Namespace::Resolve(std::string name,
fuchsia::process::Resolver::ResolveCallback callback) {
realm_->Resolve(name, std::move(callback));
}
} // namespace component