From ed23744a175bdc81697ca29c0f20a80ff0a00350 Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Tue, 28 Jun 2016 19:45:14 +0200 Subject: [PATCH] Implement first RPC commands to install/launch apps --- CMakeLists.txt | 3 + android/service/daemon.cpp | 1 + android/service/message_processor.cpp | 2 + src/CMakeLists.txt | 12 ++ src/anbox/application_manager.h | 33 +++++ src/anbox/bridge/platform_api_proxy.cpp | 120 ++++++++++++++++++ src/anbox/bridge/platform_api_proxy.h | 67 ++++++++++ src/anbox/cmds/install_app.cpp | 46 +++++++ src/anbox/cmds/install_app.h | 39 ++++++ src/anbox/cmds/launch_app.cpp | 44 +++++++ src/anbox/cmds/launch_app.h | 40 ++++++ src/anbox/cmds/run.cpp | 34 ++++- src/anbox/cmds/run.h | 11 +- src/anbox/config.cpp | 25 +++- src/anbox/config.h | 4 +- src/anbox/daemon.cpp | 9 +- src/anbox/dbus/interface.h | 67 ++++++++++ .../dbus/skeleton/application_manager.cpp | 96 ++++++++++++++ src/anbox/dbus/skeleton/application_manager.h | 50 ++++++++ src/anbox/dbus/skeleton/service.cpp | 46 +++++++ src/anbox/dbus/skeleton/service.h | 53 ++++++++ src/anbox/dbus/stub/application_manager.cpp | 65 ++++++++++ src/anbox/dbus/stub/application_manager.h | 51 ++++++++ src/anbox/input/device.cpp | 4 +- src/anbox/protobuf/anbox_bridge.proto | 9 +- src/anbox/ubuntu/platform_server.cpp | 2 +- 26 files changed, 921 insertions(+), 12 deletions(-) create mode 100644 src/anbox/application_manager.h create mode 100644 src/anbox/bridge/platform_api_proxy.cpp create mode 100644 src/anbox/bridge/platform_api_proxy.h create mode 100644 src/anbox/cmds/install_app.cpp create mode 100644 src/anbox/cmds/install_app.h create mode 100644 src/anbox/cmds/launch_app.cpp create mode 100644 src/anbox/cmds/launch_app.h create mode 100644 src/anbox/dbus/interface.h create mode 100644 src/anbox/dbus/skeleton/application_manager.cpp create mode 100644 src/anbox/dbus/skeleton/application_manager.h create mode 100644 src/anbox/dbus/skeleton/service.cpp create mode 100644 src/anbox/dbus/skeleton/service.h create mode 100644 src/anbox/dbus/stub/application_manager.cpp create mode 100644 src/anbox/dbus/stub/application_manager.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 484f293..676a233 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,9 @@ find_package(Protobuf REQUIRED) # for X11, wayland, ... at a later point if needed. pkg_check_modules(MIRCLIENT REQUIRED mirclient) +pkg_check_modules(DBUS_CPP dbus-cpp REQUIRED) +pkg_check_modules(DBUS dbus-1 REQUIRED) + ##################################################################### # Enable code coverage calculation with gcov/gcovr/lcov # Usage: diff --git a/android/service/daemon.cpp b/android/service/daemon.cpp index 012b3ab..8a2e627 100644 --- a/android/service/daemon.cpp +++ b/android/service/daemon.cpp @@ -40,6 +40,7 @@ int Daemon::run() { }); auto host_connector = std::make_shared(); + host_connector->start(); trap->run(); diff --git a/android/service/message_processor.cpp b/android/service/message_processor.cpp index b89fb7b..cf403a8 100644 --- a/android/service/message_processor.cpp +++ b/android/service/message_processor.cpp @@ -37,6 +37,8 @@ void MessageProcessor::dispatch(bridge::Invocation const& invocation) { invoke(this, server_.get(), &Server::install_application, invocation); else if (invocation.method_name() == "launch_application") invoke(this, server_.get(), &Server::launch_application, invocation); + else if (invocation.method_name() == "set_dns_servers") + invoke(this, server_.get(), &Server::set_dns_servers, invocation); } void MessageProcessor::process_event_sequence(const std::string&) { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1e4db51..ecfb119 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,6 +4,8 @@ include_directories( ${GIO_INCLUDE_DIRS} ${GIO-UNIX_INCLUDE_DIRS} ${MIRCLIENT_INCLUDE_DIRS} + ${DBUS_CPP_INCLUDE_DIRS} + ${DBUS_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/external/process-cpp-minimal/include @@ -37,6 +39,7 @@ set(SOURCES anbox/namespace_attacher.cpp anbox/container.cpp anbox/container_connector.cpp + anbox/application_manager.h anbox/common/fd.cpp anbox/common/fd_sets.h @@ -81,15 +84,23 @@ set(SOURCES anbox/bridge/platform_message_processor.cpp anbox/bridge/platform_server.cpp anbox/bridge/rpc_channel.cpp + anbox/bridge/platform_api_proxy.cpp anbox/ubuntu/platform_server.cpp anbox/ubuntu/mir_display_connection.cpp anbox/ubuntu/window_creator.cpp anbox/ubuntu/window.cpp + anbox/dbus/interface.h + anbox/dbus/skeleton/service.cpp + anbox/dbus/skeleton/application_manager.cpp + anbox/dbus/stub/application_manager.cpp + anbox/cmds/version.cpp anbox/cmds/run.cpp anbox/cmds/shell.cpp + anbox/cmds/install_app.cpp + anbox/cmds/launch_app.cpp anbox/do_not_copy_or_move.h anbox/optional.h @@ -101,6 +112,7 @@ target_link_libraries(anbox-core ${Boost_LIBRARIES} ${MIRCLIENT_LDFLAGS} ${MIRCLIENT_LIBRARIES} + ${DBUS_CPP_LIBRARIES} pthread process-cpp OpenglRender) diff --git a/src/anbox/application_manager.h b/src/anbox/application_manager.h new file mode 100644 index 0000000..2d06b9c --- /dev/null +++ b/src/anbox/application_manager.h @@ -0,0 +1,33 @@ +/* + * 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 . + * + */ + +#ifndef ANBOX_APPLICATION_MANAGER_H_ +#define ANBOX_APPLICATION_MANAGER_H_ + +#include "anbox/do_not_copy_or_move.h" + +#include + +namespace anbox { +class ApplicationManager : public DoNotCopyOrMove { +public: + virtual void install(const std::string &path) = 0; + virtual void launch(const std::string &package, const std::string &activity) = 0; +}; +} // namespace anbox + +#endif diff --git a/src/anbox/bridge/platform_api_proxy.cpp b/src/anbox/bridge/platform_api_proxy.cpp new file mode 100644 index 0000000..c239fdc --- /dev/null +++ b/src/anbox/bridge/platform_api_proxy.cpp @@ -0,0 +1,120 @@ +/* + * 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 . + * + */ + +#include "anbox/bridge/platform_api_proxy.h" +#include "anbox/bridge/rpc_channel.h" +#include "anbox/utils.h" +#include "anbox/config.h" +#include "anbox/logger.h" + +#include "anbox_bridge.pb.h" + +#include + +namespace fs = boost::filesystem; + +namespace anbox { +namespace bridge { +PlatformApiProxy::PlatformApiProxy() { +} + +PlatformApiProxy::~PlatformApiProxy() { +} + +void PlatformApiProxy::set_rpc_channel(const std::shared_ptr &channel) { + channel_ = channel; +} + +void PlatformApiProxy::reset_rpc_channel() { + channel_.reset(); +} + +void PlatformApiProxy::ensure_rpc_channel() { + if (!channel_) + throw std::runtime_error("No remote client connected"); +} + +void PlatformApiProxy::install(const std::string &path) { + ensure_rpc_channel(); + + const auto target_path = utils::string_format("%s/%s", + config::host_share_path(), fs::path(path).filename().string()); + + if (fs::exists(target_path)) + fs::remove(target_path); + + fs::copy(path, target_path); + + const auto container_path = utils::string_format("%s/%s", + config::container_share_path(), fs::path(path).filename().string()); + + auto c = std::make_shared>(); + protobuf::bridge::InstallApplication message; + message.set_path(container_path); + + channel_->call_method("install_application", + &message, + c->response.get(), + google::protobuf::NewCallback(this, &PlatformApiProxy::application_installed, c.get())); +} + +void PlatformApiProxy::application_installed(Request *request) { + DEBUG(""); +} + +void PlatformApiProxy::launch(const std::string &package, const std::string &activity) { + ensure_rpc_channel(); + + auto c = std::make_shared>(); + protobuf::bridge::LaunchApplication message; + message.set_package_name(package); + message.set_activity(activity); + + channel_->call_method("launch_application", + &message, + c->response.get(), + google::protobuf::NewCallback(this, &PlatformApiProxy::application_launched, c.get())); +} + +void PlatformApiProxy::application_launched(Request *request) { + DEBUG(""); +} + +void PlatformApiProxy::set_dns_servers(const std::string &domain, const std::vector &servers) { + ensure_rpc_channel(); + + auto c = std::make_shared>(); + + protobuf::bridge::SetDnsServers message; + message.set_domain(domain); + + for (const auto &server : servers) { + auto server_message = message.add_servers(); + server_message->set_address(server); + } + + channel_->call_method("set_dns_servers", + &message, + c->response.get(), + google::protobuf::NewCallback(this, &PlatformApiProxy::dns_servers_set, c.get())); +} + +void PlatformApiProxy::dns_servers_set(Request *request) { + DEBUG(""); +} +} // namespace bridge +} // namespace anbox diff --git a/src/anbox/bridge/platform_api_proxy.h b/src/anbox/bridge/platform_api_proxy.h new file mode 100644 index 0000000..a2d0271 --- /dev/null +++ b/src/anbox/bridge/platform_api_proxy.h @@ -0,0 +1,67 @@ +/* + * 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 . + * + */ + +#ifndef ANBOX_ANDROID_APPLICATION_MANAGER_H_ +#define ANBOX_ANDROID_APPLICATION_MANAGER_H_ + +#include "anbox/application_manager.h" + +#include +#include + +namespace anbox { +namespace protobuf { +namespace bridge { +class InstallApplication; +class LaunchApplication; +class SetDnsServers; +} // namespace bridge +} // namespace protobuf +namespace bridge { +class RpcChannel; +class PlatformApiProxy : public anbox::ApplicationManager { +public: + PlatformApiProxy(); + ~PlatformApiProxy(); + + void set_rpc_channel(const std::shared_ptr &channel); + void reset_rpc_channel(); + + void install(const std::string &path) override; + void launch(const std::string &package, const std::string &activity) override; + + void set_dns_servers(const std::string &domain, const std::vector &servers); + +private: + void ensure_rpc_channel(); + + template + struct Request { + Request() : response(std::make_shared()) { } + std::shared_ptr response; + }; + + void application_installed(Request *request); + void application_launched(Request *request); + void dns_servers_set(Request *request); + + std::shared_ptr channel_; +}; +} // namespace bridge +} // namespace anbox + +#endif diff --git a/src/anbox/cmds/install_app.cpp b/src/anbox/cmds/install_app.cpp new file mode 100644 index 0000000..d95c399 --- /dev/null +++ b/src/anbox/cmds/install_app.cpp @@ -0,0 +1,46 @@ +/* + * 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 . + * + */ + +#include "anbox/cmds/install_app.h" +#include "anbox/dbus/stub/application_manager.h" + +#include + +#include + +namespace fs = boost::filesystem; + +anbox::cmds::InstallApp::InstallApp() + : CommandWithFlagsAndAction{cli::Name{"install-app"}, cli::Usage{"install-app"}, cli::Description{"Install specified application in the Android container"}} +{ + flag(cli::make_flag(cli::Name{"apk"}, cli::Description{"Path to APK to install"}, apk_)); + action([this](const cli::Command::Context&) { + if (apk_.length() == 0) + BOOST_THROW_EXCEPTION(std::runtime_error("No APK to install specified")); + + if (!fs::is_regular_file(apk_)) + BOOST_THROW_EXCEPTION(std::runtime_error("Specified APK file does not exist")); + + auto bus = std::make_shared(core::dbus::WellKnownBus::session); + bus->install_executor(core::dbus::asio::make_executor(bus)); + auto stub = dbus::stub::ApplicationManager::create_for_bus(bus); + + stub->install(apk_); + + return EXIT_SUCCESS; + }); +} diff --git a/src/anbox/cmds/install_app.h b/src/anbox/cmds/install_app.h new file mode 100644 index 0000000..ba3edbe --- /dev/null +++ b/src/anbox/cmds/install_app.h @@ -0,0 +1,39 @@ +/* + * 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 . + * + */ + +#ifndef ANBOX_CMDS_INSTALL_APP_H_ +#define ANBOX_CMDS_INSTALL_APP_H_ + +#include +#include +#include + +#include "anbox/cli.h" + +namespace anbox { +namespace cmds { +class InstallApp : public cli::CommandWithFlagsAndAction { +public: + InstallApp(); + +private: + std::string apk_; +}; +} // namespace cmds +} // namespace anbox + +#endif diff --git a/src/anbox/cmds/launch_app.cpp b/src/anbox/cmds/launch_app.cpp new file mode 100644 index 0000000..1cfdd2b --- /dev/null +++ b/src/anbox/cmds/launch_app.cpp @@ -0,0 +1,44 @@ +/* + * 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 . + * + */ + +#include "anbox/cmds/launch_app.h" +#include "anbox/dbus/stub/application_manager.h" + +#include + +#include + +namespace fs = boost::filesystem; + +anbox::cmds::LaunchApp::LaunchApp() + : CommandWithFlagsAndAction{cli::Name{"launch-app"}, cli::Usage{"launch-app"}, cli::Description{"Launch specified application in the Android container"}} +{ + flag(cli::make_flag(cli::Name{"package"}, cli::Description{"Package the application is part of"}, package_)); + flag(cli::make_flag(cli::Name{"activity"}, cli::Description{"Activity of the application to start"}, activity_)); + action([this](const cli::Command::Context&) { + if (package_.empty() || activity_.empty()) + BOOST_THROW_EXCEPTION(std::runtime_error("No package or activity specified")); + + auto bus = std::make_shared(core::dbus::WellKnownBus::session); + bus->install_executor(core::dbus::asio::make_executor(bus)); + auto stub = dbus::stub::ApplicationManager::create_for_bus(bus); + + stub->launch(package_, activity_); + + return EXIT_SUCCESS; + }); +} diff --git a/src/anbox/cmds/launch_app.h b/src/anbox/cmds/launch_app.h new file mode 100644 index 0000000..917f110 --- /dev/null +++ b/src/anbox/cmds/launch_app.h @@ -0,0 +1,40 @@ +/* + * 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 . + * + */ + +#ifndef ANBOX_CMDS_LAUNCH_APP_H_ +#define ANBOX_CMDS_LAUNCH_APP_H_ + +#include +#include +#include + +#include "anbox/cli.h" + +namespace anbox { +namespace cmds { +class LaunchApp : public cli::CommandWithFlagsAndAction { +public: + LaunchApp(); + +private: + std::string package_; + std::string activity_; +}; +} // namespace cmds +} // namespace anbox + +#endif diff --git a/src/anbox/cmds/run.cpp b/src/anbox/cmds/run.cpp index ba4b9ad..6de115c 100644 --- a/src/anbox/cmds/run.cpp +++ b/src/anbox/cmds/run.cpp @@ -32,11 +32,16 @@ #include "anbox/bridge/connection_creator.h" #include "anbox/bridge/platform_message_processor.h" #include "anbox/bridge/rpc_channel.h" +#include "anbox/bridge/platform_api_proxy.h" #include "anbox/ubuntu/platform_server.h" #include "anbox/ubuntu/window_creator.h" +#include "anbox/dbus/skeleton/service.h" #include +#include +#include + namespace fs = boost::filesystem; namespace { @@ -50,8 +55,15 @@ public: }; } -anbox::cmds::Run::Run() - : CommandWithFlagsAndAction{cli::Name{"run"}, cli::Usage{"run"}, cli::Description{"Run the the anbox system"}} +anbox::cmds::Run::BusFactory anbox::cmds::Run::session_bus_factory() { + return []() { + return std::make_shared(core::dbus::WellKnownBus::session); + }; +} + +anbox::cmds::Run::Run(const BusFactory& bus_factory) + : CommandWithFlagsAndAction{cli::Name{"run"}, cli::Usage{"run"}, cli::Description{"Run the the anbox system"}}, + bus_factory_(bus_factory) { flag(cli::make_flag(cli::Name{"rootfs"}, cli::Description{"Path to Android rootfs"}, rootfs_)); // Just for the purpose to allow QtMir (or unity8) to find this on our /proc/*/cmdline @@ -92,13 +104,18 @@ anbox::cmds::Run::Run() rt, std::make_shared(rt, renderer->socket_path())); + auto platform_proxy = std::make_shared(); + auto bridge_connector = std::make_shared( utils::string_format("%s/anbox_bridge", config::data_path()), rt, std::make_shared(rt, - [](const std::shared_ptr &sender) { + [&](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. + platform_proxy->set_rpc_channel(rpc_channel); auto server = std::make_shared(pending_calls); return std::make_shared(sender, server, pending_calls); })); @@ -111,9 +128,15 @@ anbox::cmds::Run::Run() input_manager->generate_mappings(spec.bind_paths); + // A place where we can exchange files with the container + spec.bind_paths.insert({config::host_share_path(), config::container_share_path()}); + + // FIXME(morphis): those directories should be really somewhere on our + // persistent data directory so we keep any runtime data accross restarts. spec.temporary_dirs.push_back("/data"); spec.temporary_dirs.push_back("/cache"); spec.temporary_dirs.push_back("/storage"); + spec.temporary_dirs.push_back("/dev/input"); // NOTE: We're not mapping /dev/alarm here as if its not available @@ -130,6 +153,11 @@ anbox::cmds::Run::Run() auto container = Container::create(spec); + auto bus = bus_factory_(); + bus->install_executor(core::dbus::asio::make_executor(bus, rt->service())); + + auto skeleton = anbox::dbus::skeleton::Service::create_for_bus(bus, platform_proxy); + rt->start(); container->start(); diff --git a/src/anbox/cmds/run.h b/src/anbox/cmds/run.h index 541ee21..2a02aec 100644 --- a/src/anbox/cmds/run.h +++ b/src/anbox/cmds/run.h @@ -18,19 +18,26 @@ #ifndef ANBOX_CMDS_RUN_H_ #define ANBOX_CMDS_RUN_H_ +#include "anbox/cli.h" + #include #include #include -#include "anbox/cli.h" +#include namespace anbox { namespace cmds { class Run : public cli::CommandWithFlagsAndAction { public: - Run(); + typedef std::function BusFactory; + + static BusFactory session_bus_factory(); + + Run(const BusFactory& bus_factory = session_bus_factory()); private: + BusFactory bus_factory_; std::string rootfs_; std::string desktop_file_hint_; }; diff --git a/src/anbox/config.cpp b/src/anbox/config.cpp index b891dcd..91be9be 100644 --- a/src/anbox/config.cpp +++ b/src/anbox/config.cpp @@ -18,12 +18,33 @@ #include #include "anbox/config.h" +#include "anbox/utils.h" + +#include + +namespace fs = boost::filesystem; namespace anbox { namespace config { std::string data_path() { - // TODO(morphis): replace with proper compile time constant - return "/home/phablet/.local/share/anbox/"; + static std::string path; + if (path.length() == 0) { + const auto home_path = utils::get_env_value("HOME", "/home/phablet"); + path = utils::string_format("%s/.local/share/anbox", home_path); + fs::create_directories(fs::path(path)); + } + return path; +} + +std::string host_share_path() { + static std::string path; + if (path.length() == 0) + path = utils::string_format("%s/share", data_path()); + return path; +} + +std::string container_share_path() { + return "/data/anbox-share"; } } // namespace config } // namespace anbox diff --git a/src/anbox/config.h b/src/anbox/config.h index 694b5d2..2d52290 100644 --- a/src/anbox/config.h +++ b/src/anbox/config.h @@ -22,8 +22,10 @@ namespace anbox { namespace config { -std::string BubblewrapPath(); std::string data_path(); +std::string host_share_path(); +std::string container_share_path(); + } // namespace config } // namespace anbox diff --git a/src/anbox/daemon.cpp b/src/anbox/daemon.cpp index 02b1c34..0882d51 100644 --- a/src/anbox/daemon.cpp +++ b/src/anbox/daemon.cpp @@ -25,6 +25,8 @@ #include "anbox/cmds/version.h" #include "anbox/cmds/run.h" #include "anbox/cmds/shell.h" +#include "anbox/cmds/install_app.h" +#include "anbox/cmds/launch_app.h" #include @@ -36,7 +38,9 @@ Daemon::Daemon() : cmd.command(std::make_shared()) .command(std::make_shared()) - .command(std::make_shared()); + .command(std::make_shared()) + .command(std::make_shared()) + .command(std::make_shared()); } int Daemon::Run(const std::vector &arguments) @@ -52,5 +56,8 @@ catch(std::exception &err) { void Daemon::ensure_data_path() { if (!fs::is_directory(fs::path(config::data_path()))) fs::create_directories(fs::path(config::data_path())); + + if (!fs::is_directory(fs::path(config::host_share_path()))) + fs::create_directories(fs::path(config::host_share_path())); } } // namespace anbox diff --git a/src/anbox/dbus/interface.h b/src/anbox/dbus/interface.h new file mode 100644 index 0000000..7751680 --- /dev/null +++ b/src/anbox/dbus/interface.h @@ -0,0 +1,67 @@ +/* + * 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 . + * + */ + +#ifndef ANBOX_DBUS_INTERFACE_H_ +#define ANBOX_DBUS_INTERFACE_H_ + +#include + +#include +#include + +namespace anbox { +namespace dbus { +namespace interface { +struct Service { + static inline std::string name() { return "org.anbox"; } + static inline std::string path() { return "/"; } +}; +struct ApplicationManager { + static inline std::string name() { return "org.anbox.ApplicationManager"; } + struct Methods { + struct Install { + static inline std::string name() { return "Install"; } + typedef anbox::dbus::interface::ApplicationManager Interface; + typedef void ResultType; + static inline std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } + }; + struct Launch { + static inline std::string name() { return "Launch"; } + typedef anbox::dbus::interface::ApplicationManager Interface; + typedef void ResultType; + static inline std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } + }; + }; +}; +} // namespace interface +} // namespace dbus +} // namespace anbox + +namespace core { +namespace dbus { +namespace traits { +template<> struct Service { + static inline const std::string& interface_name() { + static const std::string s{"org.anbox.ApplicationManager"}; + return s; + } +}; +} // namespace traits +} // namespace dbus +} // namespace core + +#endif diff --git a/src/anbox/dbus/skeleton/application_manager.cpp b/src/anbox/dbus/skeleton/application_manager.cpp new file mode 100644 index 0000000..a5ae6f9 --- /dev/null +++ b/src/anbox/dbus/skeleton/application_manager.cpp @@ -0,0 +1,96 @@ +/* + * 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 . + * + */ + +#include "anbox/dbus/skeleton/application_manager.h" +#include "anbox/dbus/interface.h" +#include "anbox/logger.h" + +namespace anbox { +namespace dbus { +namespace skeleton { +ApplicationManager::ApplicationManager(const core::dbus::Bus::Ptr &bus, + const core::dbus::Object::Ptr& object, + const std::shared_ptr &impl) : + bus_(bus), + object_(object), + impl_(impl) { + + object_->install_method_handler( + [this](const core::dbus::Message::Ptr &msg) { + std::string path; + auto reader = msg->reader(); + reader >> path; + + DEBUG("path %s", path); + + core::dbus::Message::Ptr reply; + + try { + install(path); + DEBUG("install done"); + reply = core::dbus::Message::make_method_return(msg); + DEBUG("Successfully installed application"); + } + catch (std::exception const &err) { + DEBUG("Failed to install application: %s", err.what()); + reply = core::dbus::Message::make_error(msg, + "org.anbox.Error.Failed", + err.what()); + } + + DEBUG("Sending reply"); + + bus_->send(reply); + }); + + object_->install_method_handler( + [this](const core::dbus::Message::Ptr &msg) { + std::string package, activity; + auto reader = msg->reader(); + reader >> package; + reader >> activity; + + core::dbus::Message::Ptr reply; + + try { + launch(package, activity); + reply = core::dbus::Message::make_method_return(msg); + } + catch (std::exception const &err) { + reply = core::dbus::Message::make_error(msg, + "org.anbox.Error.Failed", + err.what()); + } + + bus_->send(reply); + }); +} + +ApplicationManager::~ApplicationManager() { + object_->uninstall_method_handler(); +} + +void ApplicationManager::install(const std::string &path) { + impl_->install(path); +} + +void ApplicationManager::launch(const std::string &package, const std::string &activity) { + impl_->launch(package, activity); +} +} // namespace skeleton +} // namespace dbus +} // namespace anbox diff --git a/src/anbox/dbus/skeleton/application_manager.h b/src/anbox/dbus/skeleton/application_manager.h new file mode 100644 index 0000000..3ccba27 --- /dev/null +++ b/src/anbox/dbus/skeleton/application_manager.h @@ -0,0 +1,50 @@ +/* + * 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 . + * + */ + +#ifndef ANBOX_DBUS_SKELETON_APPLICATION_MANAGER_H_ +#define ANBOX_DBUS_SKELETON_APPLICATION_MANAGER_H_ + +#include "anbox/application_manager.h" + +#include +#include +#include + +namespace anbox { +namespace dbus { +namespace skeleton { +class ApplicationManager : public anbox::ApplicationManager { +public: + ApplicationManager(const core::dbus::Bus::Ptr &bus, + const core::dbus::Object::Ptr& object, + const std::shared_ptr &impl); + ~ApplicationManager(); + + void install(const std::string &path) override; + void launch(const std::string &package, const std::string &activity) override; + +private: + core::dbus::Bus::Ptr bus_; + core::dbus::Service::Ptr service_; + core::dbus::Object::Ptr object_; + std::shared_ptr impl_; +}; +} // namespace skeleton +} // namespace dbus +} // namespace anbox + +#endif diff --git a/src/anbox/dbus/skeleton/service.cpp b/src/anbox/dbus/skeleton/service.cpp new file mode 100644 index 0000000..6abca53 --- /dev/null +++ b/src/anbox/dbus/skeleton/service.cpp @@ -0,0 +1,46 @@ +/* + * 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 . + * + */ + +#include "anbox/dbus/skeleton/service.h" +#include "anbox/dbus/skeleton/application_manager.h" +#include "anbox/dbus/interface.h" + +namespace anbox { +namespace dbus { +namespace skeleton { +std::shared_ptr Service::create_for_bus(const core::dbus::Bus::Ptr &bus, + const std::shared_ptr &application_manager) { + auto service = core::dbus::Service::add_service(bus, anbox::dbus::interface::Service::name()); + auto object = service->add_object_for_path(anbox::dbus::interface::Service::path()); + return std::make_shared(bus, service, object, application_manager); +} + +Service::Service(const core::dbus::Bus::Ptr &bus, + const core::dbus::Service::Ptr& service, + const core::dbus::Object::Ptr& object, + const std::shared_ptr &application_manager) : + bus_(bus), + service_(service), + object_(object), + application_manager_(std::make_shared(bus_, object_, application_manager)) { +} + +Service::~Service() { +} +} // namespace skeleton +} // namespace dbus +} // namespace anbox diff --git a/src/anbox/dbus/skeleton/service.h b/src/anbox/dbus/skeleton/service.h new file mode 100644 index 0000000..99e8be6 --- /dev/null +++ b/src/anbox/dbus/skeleton/service.h @@ -0,0 +1,53 @@ +/* + * 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 . + * + */ + +#ifndef ANBOX_DBUS_SKELETON_SERVICE_H_ +#define ANBOX_DBUS_SKELETON_SERVICE_H_ + +#include "anbox/do_not_copy_or_move.h" +#include "anbox/application_manager.h" + +#include +#include +#include + +namespace anbox { +namespace dbus { +namespace skeleton { +class ApplicationManager; +class Service : public DoNotCopyOrMove { +public: + static std::shared_ptr create_for_bus(const core::dbus::Bus::Ptr &bus, + const std::shared_ptr &application_manager); + + Service(const core::dbus::Bus::Ptr &bus, + const core::dbus::Service::Ptr& service, + const core::dbus::Object::Ptr& object, + const std::shared_ptr &application_manager); + ~Service(); + +private: + core::dbus::Bus::Ptr bus_; + core::dbus::Service::Ptr service_; + core::dbus::Object::Ptr object_; + std::shared_ptr application_manager_; +}; +} // namespace skeleton +} // namespace dbus +} // namespace anbox + +#endif diff --git a/src/anbox/dbus/stub/application_manager.cpp b/src/anbox/dbus/stub/application_manager.cpp new file mode 100644 index 0000000..e9f4bb7 --- /dev/null +++ b/src/anbox/dbus/stub/application_manager.cpp @@ -0,0 +1,65 @@ +/* + * 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 . + * + */ + +#include "anbox/dbus/stub/application_manager.h" +#include "anbox/dbus/interface.h" +#include "anbox/logger.h" + +namespace anbox { +namespace dbus { +namespace stub { +std::shared_ptr ApplicationManager::create_for_bus(const core::dbus::Bus::Ptr &bus) { + auto service = core::dbus::Service::use_service(bus, anbox::dbus::interface::Service::name()); + auto object = service->add_object_for_path(anbox::dbus::interface::Service::path()); + return std::make_shared(bus, service, object); +} + +ApplicationManager::ApplicationManager(const core::dbus::Bus::Ptr &bus, + const core::dbus::Service::Ptr& service, + const core::dbus::Object::Ptr& object) : + bus_(bus), + service_(service), + object_(object) { +} + +ApplicationManager::~ApplicationManager() { +} + +void ApplicationManager::install(const std::string &path) { + DEBUG("path %s", path); + + auto result = object_->invoke_method_synchronously< + anbox::dbus::interface::ApplicationManager::Methods::Install, + anbox::dbus::interface::ApplicationManager::Methods::Install::ResultType>(path); + + if (result.is_error()) + throw std::runtime_error(result.error().print()); +} + +void ApplicationManager::launch(const std::string &package, const std::string &activity) { + DEBUG("package %s activity %s", package, activity); + + auto result = object_->invoke_method_synchronously< + anbox::dbus::interface::ApplicationManager::Methods::Launch, + anbox::dbus::interface::ApplicationManager::Methods::Launch::ResultType>(package, activity); + + if (result.is_error()) + throw std::runtime_error(result.error().print()); +} +} // namespace skeleton +} // namespace dbus +} // namespace anbox diff --git a/src/anbox/dbus/stub/application_manager.h b/src/anbox/dbus/stub/application_manager.h new file mode 100644 index 0000000..f01ef16 --- /dev/null +++ b/src/anbox/dbus/stub/application_manager.h @@ -0,0 +1,51 @@ +/* + * 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 . + * + */ + +#ifndef ANBOX_DBUS_SKELETON_APPLICATION_MANAGER_H_ +#define ANBOX_DBUS_SKELETON_APPLICATION_MANAGER_H_ + +#include "anbox/application_manager.h" + +#include +#include +#include + +namespace anbox { +namespace dbus { +namespace stub { +class ApplicationManager : public anbox::ApplicationManager { +public: + static std::shared_ptr create_for_bus(const core::dbus::Bus::Ptr &bus); + + ApplicationManager(const core::dbus::Bus::Ptr &bus, + const core::dbus::Service::Ptr& service, + const core::dbus::Object::Ptr& object); + ~ApplicationManager(); + + void install(const std::string &path) override; + void launch(const std::string &package, const std::string &activity) override; + +private: + core::dbus::Bus::Ptr bus_; + core::dbus::Service::Ptr service_; + core::dbus::Object::Ptr object_; +}; +} // namespace stub +} // namespace dbus +} // namespace anbox + +#endif diff --git a/src/anbox/input/device.cpp b/src/anbox/input/device.cpp index 0dce8c5..42674a0 100644 --- a/src/anbox/input/device.cpp +++ b/src/anbox/input/device.cpp @@ -72,14 +72,16 @@ void Device::send_events(const std::vector &events) { data[n].code = event.code; data[n].value = event.value; +#ifdef DEBUG DEBUG("Event: time %lld, type %d, code %d, value %d", data[n].sec * 1000000000LL + data[n].usec * 1000LL, event.type, event.code, event.value); +#endif n++; } - for (auto n = 0; n < connections_->size(); n++) { + for (unsigned n = 0; n < connections_->size(); n++) { connections_->at(n)->send(reinterpret_cast(data), events.size() * sizeof(struct CompatEvent)); } diff --git a/src/anbox/protobuf/anbox_bridge.proto b/src/anbox/protobuf/anbox_bridge.proto index bc4898a..9ded4f3 100644 --- a/src/anbox/protobuf/anbox_bridge.proto +++ b/src/anbox/protobuf/anbox_bridge.proto @@ -12,7 +12,6 @@ message Invocation { message Result { optional uint32 id = 1; optional bytes response = 2; - repeated bytes events = 3; } message StructuredError { @@ -41,3 +40,11 @@ message LaunchApplication { required string package_name = 1; optional string activity = 2; } + +message SetDnsServers { + required string domain = 1; + message Server { + required string address = 1; + } + repeated Server servers = 2; +} diff --git a/src/anbox/ubuntu/platform_server.cpp b/src/anbox/ubuntu/platform_server.cpp index 0f8b317..1800530 100644 --- a/src/anbox/ubuntu/platform_server.cpp +++ b/src/anbox/ubuntu/platform_server.cpp @@ -18,7 +18,7 @@ #include "anbox/ubuntu/platform_server.h" #include "anbox/logger.h" -#include "bridge.pb.h" +#include "anbox_bridge.pb.h" namespace anbox { namespace ubuntu {