blob: cee631f2e12d7d4afc33bfa9a522013ae975bb37 [file] [log] [blame]
// Copyright 2020 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 <fidl/fuchsia.appmgr/cpp/wire.h>
#include <fidl/fuchsia.sessionmanager/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/directory.h>
#include <lib/fidl-async/cpp/bind.h>
#include <lib/fit/function.h>
#include <fbl/string.h>
/*
* The startup component exists to start the `appmgr` component that exists
* inside the `core` realm. This arrangement solves the problem that in some
* builds `appmgr` is not included. It would be more straightforward to have
* `appmgr` in a direct `eager` lineage from the root component, but that would
* cause the system to crash in product configurations that don't include
* `appmgr` because failure to start an `eager` child is fatal to a parent.
* startup is not a child of the `core` component because that component is
* itself stored in pkgfs, which may not be included in the build.
*
* NOTE: this component also starts `session_manager` for the same reasons
* stated above.
*
* startup works by using a capability routed to it from `appmgr`. startup
* connects to this capability, tries to send a request, and exits. Success or
* failure of the request is irrelevant, startup is just making the component
* manager resolve and start `appmgr`, if it is present.
*/
namespace {
void start_core() {
async::Loop loop((async::Loop(&kAsyncLoopConfigAttachToCurrentThread)));
zx::channel remote;
zx::channel local;
zx_status_t status = zx::channel::create(0, &local, &remote);
if (status != ZX_OK) {
exit(-1);
}
auto path = fbl::String("/svc/fuchsia.component.CoreBinder");
status = fdio_service_connect(path.data(), remote.release());
if (status != ZX_OK) {
// This failed, presumably because core is not available.
return;
}
}
void start_appmgr() {
zx::channel remote;
zx::channel local;
zx_status_t status = zx::channel::create(0, &local, &remote);
if (status != ZX_OK) {
exit(-1);
}
auto path = fbl::String("/svc/fuchsia.appmgr.Startup");
status = fdio_service_connect(path.data(), remote.release());
if (status != ZX_OK) {
// This failed, presumably because appmgr is not available.
return;
}
fidl::WireSyncClient<fuchsia_appmgr::Startup> client(std::move(local));
// TODO(fxbug.dev/97955) Consider handling the error instead of ignoring it.
(void)client->LaunchAppmgr();
}
void start_session_manager() {
zx::channel remote;
zx::channel local;
zx_status_t status = zx::channel::create(0, &local, &remote);
if (status != ZX_OK) {
exit(-1);
}
auto path = fbl::String("/svc/fuchsia.sessionmanager.Startup");
status = fdio_service_connect(path.data(), remote.release());
if (status != ZX_OK) {
// This failed, presumably because session_manager is not available.
return;
}
fidl::WireSyncClient<fuchsia_sessionmanager::Startup> client(std::move(local));
// TODO(fxbug.dev/97955) Consider handling the error instead of ignoring it.
(void)client->LaunchSessionManager();
}
} // namespace
int main() {
start_core();
start_appmgr();
start_session_manager();
// We ignore the result here. A failure probably indicates we're running on a
// config that doesn't include appmgr.
//
// In the future we may want to wait indefinitely without exiting if
// components are required to have an active client to keep them running. As
// of this writing components are not actively halted if they have no
// clients, but this may change.
}