From c0393a6713c8e49357821ed4c4f85e62a6101d42 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 8 May 2017 11:00:47 +0100 Subject: [PATCH 1/3] cmds: session_manager: Provide an option to use any container Normally Anbox will use the default container provided by the Anbox Container Manager, but some users may wish to run their own container. Here we're adding a --standalone flag which tells the Session Manager not to interact (configure/start) the Container Manager. This allows the user to utilise any other bespoke container of their choosing. For instance, this new feature was tested using a Docker container running the android.img provided by Anbox. Signed-off-by: Lee Jones --- src/anbox/cmds/session_manager.cpp | 29 +++++++++++++++++++---------- src/anbox/cmds/session_manager.h | 1 + 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/anbox/cmds/session_manager.cpp b/src/anbox/cmds/session_manager.cpp index 5c294d0..924eadf 100644 --- a/src/anbox/cmds/session_manager.cpp +++ b/src/anbox/cmds/session_manager.cpp @@ -106,6 +106,9 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory) flag(cli::make_flag(cli::Name{"window-size"}, cli::Description{"Size of the window in single window mode, e.g. --window-size=1024,768"}, window_size_)); + flag(cli::make_flag(cli::Name{"standalone"}, + cli::Description{"Prevents the Container Manager from starting the default container (Experimental)"}, + standalone_)); action([this](const cli::Command::Context &) { auto trap = core::posix::trap_signals_for_process( @@ -136,10 +139,12 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory) auto dispatcher = anbox::common::create_dispatcher_for_runtime(rt); container::Client container(rt); - container.register_terminate_handler([&]() { - WARNING("Lost connection to container manager, terminating."); - trap->stop(); - }); + if (!standalone_) { + container.register_terminate_handler([&]() { + WARNING("Lost connection to container manager, terminating."); + trap->stop(); + }); + } auto input_manager = std::make_shared(rt); @@ -213,7 +218,8 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory) })); container::Configuration container_configuration; - container_configuration.bind_mounts = { + if (!standalone_) { + container_configuration.bind_mounts = { {qemu_pipe_connector->socket_file(), "/dev/qemu_pipe"}, {bridge_connector->socket_file(), "/dev/anbox_bridge"}, {audio_server->socket_file(), "/dev/anbox_audio"}, @@ -221,9 +227,10 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory) {"/dev/binder", "/dev/binder"}, {"/dev/ashmem", "/dev/ashmem"}, {"/dev/fuse", "/dev/fuse"}, - }; + }; - dispatcher->dispatch([&]() { container.start(container_configuration); }); + dispatcher->dispatch([&]() { container.start(container_configuration); }); + } auto bus = bus_factory_(); bus->install_executor(core::dbus::asio::make_executor(bus, rt->service())); @@ -233,9 +240,11 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory) rt->start(); trap->run(); - // Stop the container which should close all open connections we have on - // our side and should terminate all services. - container.stop(); + if (!standalone_) { + // Stop the container which should close all open connections we have on + // our side and should terminate all services. + container.stop(); + } rt->stop(); diff --git a/src/anbox/cmds/session_manager.h b/src/anbox/cmds/session_manager.h index 9ffb419..60c3d42 100644 --- a/src/anbox/cmds/session_manager.h +++ b/src/anbox/cmds/session_manager.h @@ -45,6 +45,7 @@ class SessionManager : public cli::CommandWithFlagsAndAction { graphics::GLRendererServer::Config::Driver gles_driver_; bool single_window_ = false; graphics::Rect window_size_; + bool standalone_ = false; }; } // namespace cmds } // namespace anbox From 157a2f9c1351e02ad369b3cee66d6ecab9f9be06 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 12 May 2017 11:47:24 +0100 Subject: [PATCH 2/3] cmds: session_manager: Introduce an Experimental Mode flag Some features which Anbox offer may be useful to users, but can not be officially supported. For example, the recently added Stand-Alone Mode can be utilised to make use of different types of independent containers where Anbox does not control the complete life cycle, but since these types of setups can be widely varying and complex, it would not be impossible to provide support. Thus, when running in these modes, it's important for the user to show knowledge that they are operating in an experimental way. This functionality provided by issuing the --experimental flag when starting the Session Manager. Signed-off-by: Lee Jones --- src/anbox/cmds/session_manager.cpp | 8 ++++++++ src/anbox/cmds/session_manager.h | 1 + 2 files changed, 9 insertions(+) diff --git a/src/anbox/cmds/session_manager.cpp b/src/anbox/cmds/session_manager.cpp index 924eadf..d0ce924 100644 --- a/src/anbox/cmds/session_manager.cpp +++ b/src/anbox/cmds/session_manager.cpp @@ -109,6 +109,9 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory) flag(cli::make_flag(cli::Name{"standalone"}, cli::Description{"Prevents the Container Manager from starting the default container (Experimental)"}, standalone_)); + flag(cli::make_flag(cli::Name{"experimental"}, + cli::Description{"Allows users to use experimental features"}, + experimental_)); action([this](const cli::Command::Context &) { auto trap = core::posix::trap_signals_for_process( @@ -118,6 +121,11 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory) trap->stop(); }); + if (standalone_ && !experimental_) { + ERROR("Experimental features selected, but --experimental flag not set"); + return EXIT_FAILURE; + } + if (!fs::exists("/dev/binder") || !fs::exists("/dev/ashmem")) { ERROR("Failed to start as either binder or ashmem kernel drivers are not loaded"); return EXIT_FAILURE; diff --git a/src/anbox/cmds/session_manager.h b/src/anbox/cmds/session_manager.h index 60c3d42..498f5a5 100644 --- a/src/anbox/cmds/session_manager.h +++ b/src/anbox/cmds/session_manager.h @@ -46,6 +46,7 @@ class SessionManager : public cli::CommandWithFlagsAndAction { bool single_window_ = false; graphics::Rect window_size_; bool standalone_ = false; + bool experimental_ = false; }; } // namespace cmds } // namespace anbox From e492cd1af8870cc7ef5ffdeea0dca69231f93c79 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 12 May 2017 14:00:36 +0100 Subject: [PATCH 3/3] cmds: session_manager: Handle the Container Client class using pointers We can now start the Session Manager in Stand Alone Mode. This means that the Container Manager is not required, since the assumption is that the user will provide their own container. The issue is that the container related calls are spread throughout the Session Manager's code base. So if we attempt to take an instance of the Container Client class in one if-ed out area, by the time we reach the next, it will be out of scope. One solution is to take the instance of the Container Client class globally, then only make use of it if it's required. This works great if the Container Manager is running in the background. However, since a connection is made to the Container Manager during the constructor, if the Container Manager is not running, the side-effect is the following error: Failed to connect to socket /run/anbox-container.socket: Connection refused To solve this problem we will use a global (actually private to the Session Manager) pointer which will always be in scope. It will only be initialised and used when required though. Signed-off-by: Lee Jones --- src/anbox/cmds/session_manager.cpp | 8 ++++---- src/anbox/cmds/session_manager.h | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/anbox/cmds/session_manager.cpp b/src/anbox/cmds/session_manager.cpp index d0ce924..5a46566 100644 --- a/src/anbox/cmds/session_manager.cpp +++ b/src/anbox/cmds/session_manager.cpp @@ -146,9 +146,9 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory) auto rt = Runtime::create(); auto dispatcher = anbox::common::create_dispatcher_for_runtime(rt); - container::Client container(rt); if (!standalone_) { - container.register_terminate_handler([&]() { + container_ = std::make_shared(rt); + container_->register_terminate_handler([&]() { WARNING("Lost connection to container manager, terminating."); trap->stop(); }); @@ -237,7 +237,7 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory) {"/dev/fuse", "/dev/fuse"}, }; - dispatcher->dispatch([&]() { container.start(container_configuration); }); + dispatcher->dispatch([&]() { container_->start(container_configuration); }); } auto bus = bus_factory_(); @@ -251,7 +251,7 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory) if (!standalone_) { // Stop the container which should close all open connections we have on // our side and should terminate all services. - container.stop(); + container_->stop(); } rt->stop(); diff --git a/src/anbox/cmds/session_manager.h b/src/anbox/cmds/session_manager.h index 498f5a5..25185ac 100644 --- a/src/anbox/cmds/session_manager.h +++ b/src/anbox/cmds/session_manager.h @@ -30,6 +30,9 @@ #include "anbox/graphics/rect.h" namespace anbox { +namespace container { +class Client; +} // namespace container namespace cmds { class SessionManager : public cli::CommandWithFlagsAndAction { public: @@ -40,6 +43,7 @@ class SessionManager : public cli::CommandWithFlagsAndAction { SessionManager(const BusFactory& bus_factory = session_bus_factory()); private: + std::shared_ptr container_; BusFactory bus_factory_; std::string desktop_file_hint_; graphics::GLRendererServer::Config::Driver gles_driver_;