| // 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" |
| #include "garnet/bin/appmgr/storage_watchdog.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; |
| }))); |
| |
| 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()); |
| } |
| |
| // If any of these services aren't in additional_services or the parent |
| // namespace, add them here directly. (AddService skips duplicate services) |
| 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; |
| }))); |
| services_->AddService( |
| CacheControl::Name_, |
| fbl::AdoptRef(new fs::Service([this](zx::channel channel) { |
| test_cache_bindings_.AddBinding( |
| this, fidl::InterfaceRequest<CacheControl>(std::move(channel))); |
| return ZX_OK; |
| }))); |
| } |
| |
| 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); |
| }); |
| } |
| |
| void Namespace::Clear(ClearCallback callback) { |
| auto cc_trace_id = TRACE_NONCE(); |
| TRACE_ASYNC_BEGIN("appmgr", "Namespace::Clear", cc_trace_id); |
| |
| StorageWatchdog storage_watchdog = StorageWatchdog("/data", "/data/cache"); |
| storage_watchdog.PurgeCache(); |
| |
| callback(); |
| } |
| |
| 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 |