X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fsrc%2Fanbox%2Fcmds%2Fsession_manager.cpp;fp=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fsrc%2Fanbox%2Fcmds%2Fsession_manager.cpp;h=81452a56b37e5c819f394b78992c5b277d27625c;hb=e26c1ec581be598521517829adba8c8dd23a768f;hp=0000000000000000000000000000000000000000;hpb=6699c1aea74eeb0eb400e6299079f0c7576f716f;p=iec.git diff --git a/src/type3_AndroidCloud/anbox-master/src/anbox/cmds/session_manager.cpp b/src/type3_AndroidCloud/anbox-master/src/anbox/cmds/session_manager.cpp new file mode 100644 index 0000000..81452a5 --- /dev/null +++ b/src/type3_AndroidCloud/anbox-master/src/anbox/cmds/session_manager.cpp @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2016 Simon Fels + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + */ + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch-default" +#include + +#include "core/posix/signal.h" + +#include "anbox/application/launcher_storage.h" +#include "anbox/application/database.h" +#include "anbox/audio/server.h" +#include "anbox/bridge/android_api_stub.h" +#include "anbox/bridge/platform_api_skeleton.h" +#include "anbox/bridge/platform_message_processor.h" +#include "anbox/graphics/gl_renderer_server.h" + +#include "anbox/cmds/session_manager.h" +#include "anbox/common/dispatcher.h" +#include "anbox/system_configuration.h" +#include "anbox/container/client.h" +#include "anbox/dbus/bus.h" +#include "anbox/dbus/skeleton/service.h" +#include "anbox/input/manager.h" +#include "anbox/logger.h" +#include "anbox/network/published_socket_connector.h" +#include "anbox/qemu/pipe_connection_creator.h" +#include "anbox/rpc/channel.h" +#include "anbox/rpc/connection_creator.h" +#include "anbox/runtime.h" +#include "anbox/platform/base_platform.h" +#include "anbox/wm/multi_window_manager.h" +#include "anbox/wm/single_window_manager.h" + +#include "external/xdg/xdg.h" + +#include + +#pragma GCC diagnostic pop + +namespace fs = boost::filesystem; + +namespace { +constexpr const char *default_appmgr_package{"org.anbox.appmgr"}; +constexpr const char *default_appmgr_component{"org.anbox.appmgr.AppViewActivity"}; +const boost::posix_time::milliseconds default_appmgr_startup_delay{50}; +const anbox::graphics::Rect default_single_window_size{0, 0, 1024, 768}; + +class NullConnectionCreator : public anbox::network::ConnectionCreator< + boost::asio::local::stream_protocol> { + public: + void create_connection_for( + std::shared_ptr const + &socket) override { + WARNING("Not implemented"); + socket->close(); + } +}; +} + +void anbox::cmds::SessionManager::launch_appmgr_if_needed(const std::shared_ptr &android_api_stub) { + if (!single_window_) + return; + + android::Intent launch_intent; + launch_intent.package = default_appmgr_package; + launch_intent.component = default_appmgr_component; + // As this will only be executed in single window mode we don't have + // to specify and launch bounds. + android_api_stub->launch(launch_intent, graphics::Rect::Invalid, wm::Stack::Id::Default); +} + +anbox::cmds::SessionManager::SessionManager() + : CommandWithFlagsAndAction{cli::Name{"session-manager"}, cli::Usage{"session-manager"}, + cli::Description{"Run the the anbox session manager"}}, + window_size_(default_single_window_size) { + // Just for the purpose to allow QtMir (or unity8) to find this on our + // /proc/*/cmdline + // for proper confinement etc. + flag(cli::make_flag(cli::Name{"desktop_file_hint"}, + cli::Description{"Desktop file hint for QtMir/Unity8"}, + desktop_file_hint_)); + flag(cli::make_flag(cli::Name{"single-window"}, + cli::Description{"Start in single window mode."}, + single_window_)); + 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_)); + flag(cli::make_flag(cli::Name{"experimental"}, + cli::Description{"Allows users to use experimental features"}, + experimental_)); + flag(cli::make_flag(cli::Name{"use-system-dbus"}, + cli::Description{"Use system instead of session DBus"}, + use_system_dbus_)); + flag(cli::make_flag(cli::Name{"software-rendering"}, + cli::Description{"Use software rendering instead of hardware accelerated GL rendering"}, + use_software_rendering_)); + flag(cli::make_flag(cli::Name{"no-touch-emulation"}, + cli::Description{"Disable touch emulation applied on mouse inputs"}, + no_touch_emulation_)); + flag(cli::make_flag(cli::Name{"server-side-decoration"}, + cli::Description{"Prefer to use server-side decoration instead of client-side decoration"}, + server_side_decoration_)); + + action([this](const cli::Command::Context &) { + auto trap = core::posix::trap_signals_for_process( + {core::posix::Signal::sig_term, core::posix::Signal::sig_int}); + trap->signal_raised().connect([trap](const core::posix::Signal &signal) { + INFO("Signal %i received. Good night.", static_cast(signal)); + trap->stop(); + }); + + if (standalone_ && !experimental_) { + ERROR("Experimental features selected, but --experimental flag not set"); + return EXIT_FAILURE; + } + + if ((!fs::exists("/dev/binder") && !fs::exists(BINDERFS_PATH)) || !fs::exists("/dev/ashmem")) { + ERROR("Failed to start as either binder or ashmem kernel drivers are not loaded"); + return EXIT_FAILURE; + } + + utils::ensure_paths({ + SystemConfiguration::instance().socket_dir(), + SystemConfiguration::instance().input_device_dir(), + }); + + auto rt = Runtime::create(); + auto dispatcher = anbox::common::create_dispatcher_for_runtime(rt); + + if (!standalone_) { + container_ = std::make_shared(rt); + container_->register_terminate_handler([&]() { + WARNING("Lost connection to container manager, terminating."); + trap->stop(); + }); + } + + auto input_manager = std::make_shared(rt); + auto android_api_stub = std::make_shared(); + + auto display_frame = graphics::Rect::Invalid; + if (single_window_) + display_frame = window_size_; + + const auto should_enable_touch_emulation = utils::get_env_value("ANBOX_ENABLE_TOUCH_EMULATION", "true"); + if (should_enable_touch_emulation == "false" || no_touch_emulation_) + no_touch_emulation_ = true; + + const auto should_force_server_side_decoration = utils::get_env_value("ANBOX_FORCE_SERVER_SIDE_DECORATION", "false"); + if (should_force_server_side_decoration == "true") + server_side_decoration_ = true; + + platform::Configuration platform_config; + platform_config.single_window = single_window_; + platform_config.no_touch_emulation = no_touch_emulation_; + platform_config.display_frame = display_frame; + platform_config.server_side_decoration = server_side_decoration_; + + auto platform = platform::create(utils::get_env_value("ANBOX_PLATFORM", "sdl"), + input_manager, + platform_config); + if (!platform) + return EXIT_FAILURE; + + auto app_db = std::make_shared(); + + std::shared_ptr window_manager; + bool using_single_window = false; + if (platform->supports_multi_window() && !single_window_) + window_manager = std::make_shared(platform, android_api_stub, app_db); + else { + window_manager = std::make_shared(platform, display_frame, app_db); + using_single_window = true; + } + + const auto should_force_software_rendering = utils::get_env_value("ANBOX_FORCE_SOFTWARE_RENDERING", "false"); + auto gl_driver = graphics::GLRendererServer::Config::Driver::Host; + if (should_force_software_rendering == "true" || use_software_rendering_) + gl_driver = graphics::GLRendererServer::Config::Driver::Software; + + graphics::GLRendererServer::Config renderer_config { + gl_driver, + single_window_ + }; + auto gl_server = std::make_shared(renderer_config, window_manager); + + platform->set_window_manager(window_manager); + platform->set_renderer(gl_server->renderer()); + window_manager->setup(); + + auto app_manager = std::static_pointer_cast(android_api_stub); + if (!using_single_window) { + // When we're not running single window mode we need to restrict ourself to + // only launch applications in freeform mode as otherwise the window tracking + // doesn't work. + app_manager = std::make_shared( + android_api_stub, wm::Stack::Id::Freeform); + } + + auto audio_server = std::make_shared(rt, platform); + + const auto socket_path = SystemConfiguration::instance().socket_dir(); + + // The qemu pipe is used as a very fast communication channel between guest + // and host for things like the GLES emulation/translation, the RIL or ADB. + auto qemu_pipe_connector = + std::make_shared( + utils::string_format("%s/qemu_pipe", socket_path), rt, + std::make_shared(gl_server->renderer(), rt)); + + boost::asio::deadline_timer appmgr_start_timer(rt->service()); + + auto bridge_connector = std::make_shared( + utils::string_format("%s/anbox_bridge", socket_path), rt, + std::make_shared( + rt, [&](const std::shared_ptr &sender) { + auto pending_calls = std::make_shared(); + auto rpc_channel = + std::make_shared(pending_calls, sender); + // This is safe as long as we only support a single client. If we + // support + // more than one one day we need proper dispatching to the right + // one. + android_api_stub->set_rpc_channel(rpc_channel); + + auto server = std::make_shared( + pending_calls, platform, window_manager, app_db); + server->register_boot_finished_handler([&]() { + DEBUG("Android successfully booted"); + android_api_stub->ready().set(true); + appmgr_start_timer.expires_from_now(default_appmgr_startup_delay); + appmgr_start_timer.async_wait([&](const boost::system::error_code &err) { + if (err != boost::system::errc::success) + return; + launch_appmgr_if_needed(android_api_stub); + }); + }); + return std::make_shared( + sender, server, pending_calls); + })); + + container::Configuration container_configuration; + + // Instruct healthd to fake battery level as it may take it from other connected + // devices like mouse or keyboard and will incorrectly show a system popup to + // shutdown the Android system because of low battery. This prevents any kind of + // input as focus is bound to the system popup exclusively. + // + // See https://github.com/anbox/anbox/issues/780 for further details. + container_configuration.extra_properties.push_back("ro.boot.fake_battery=1"); + + if (server_side_decoration_) + container_configuration.extra_properties.push_back("ro.anbox.no_decorations=1"); + + 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"}, + {SystemConfiguration::instance().input_device_dir(), "/dev/input"}, + + }; + + container_configuration.devices = { + {"/dev/fuse", {0666}}, + }; + + dispatcher->dispatch([&]() { + container_->start(container_configuration); + }); + } + + auto bus_type = anbox::dbus::Bus::Type::Session; + if (use_system_dbus_) + bus_type = anbox::dbus::Bus::Type::System; + auto bus = std::make_shared(bus_type); + + auto skeleton = anbox::dbus::skeleton::Service::create_for_bus(bus, app_manager); + + bus->run_async(); + + rt->start(); + trap->run(); + + 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(); + + return EXIT_SUCCESS; + }); +}