From 1879e634c5f399fdeaab0c15835740940cab5f8e Mon Sep 17 00:00:00 2001 From: Simon Fels Date: Mon, 4 Jul 2016 12:10:31 +0200 Subject: [PATCH] Rework some of the RPC service bits and add boot support --- Android.mk | 27 ++++++++- android/CMakeLists.txt | 15 ++++- ...tform_api.cpp => android_api_skeleton.cpp} | 16 +++--- ...{platform_api.h => android_api_skeleton.h} | 12 ++-- android/service/daemon.cpp | 15 ++++- android/service/daemon.h | 2 - android/service/host_connector.cpp | 19 +++++-- android/service/host_connector.h | 12 ++-- android/service/local_socket_connection.cpp | 8 ++- android/service/local_socket_connection.h | 2 - android/service/main.cpp | 2 +- android/service/message_processor.cpp | 12 ++-- android/service/message_processor.h | 8 +-- android/service/platform_api_stub.cpp | 57 +++++++++++++++++++ android/service/platform_api_stub.h | 57 +++++++++++++++++++ android/service/platform_server_proxy.cpp | 0 android/service/platform_server_proxy.h | 0 android/service/platform_service.cpp | 37 ++++++++++++ android/service/platform_service.h | 43 ++++++++++++++ .../service/platform_service_interface.cpp | 45 +++++++++++++++ android/service/platform_service_interface.h | 55 ++++++++++++++++++ android/service/test_platform_service.cpp | 34 +++++++++++ src/CMakeLists.txt | 8 ++- ...orm_api_proxy.cpp => android_api_stub.cpp} | 30 +++++----- ...latform_api_proxy.h => android_api_stub.h} | 10 ++-- ...m_server.cpp => platform_api_skeleton.cpp} | 6 +- ...tform_server.h => platform_api_skeleton.h} | 10 +++- .../bridge/platform_message_processor.cpp | 11 ++-- src/anbox/bridge/platform_message_processor.h | 6 +- src/anbox/cmds/run.cpp | 43 +++++++++++--- src/anbox/cmds/run.h | 4 ++ src/anbox/common/dispatcher.cpp | 43 ++++++++++++++ src/anbox/common/dispatcher.h | 43 ++++++++++++++ .../network/qemu_pipe_connection_creator.cpp | 11 +++- .../network/qemu_pipe_connection_creator.h | 5 +- .../bootanimation_message_processor.cpp | 52 +++++++++++++++++ .../support/bootanimation_message_processor.h | 42 ++++++++++++++ ...m_server.cpp => platform_api_skeleton.cpp} | 27 +++++++-- ...tform_server.h => platform_api_skeleton.h} | 23 ++++++-- 39 files changed, 746 insertions(+), 106 deletions(-) rename android/service/{platform_api.cpp => android_api_skeleton.cpp} (85%) rename android/service/{platform_api.h => android_api_skeleton.h} (91%) create mode 100644 android/service/platform_api_stub.cpp create mode 100644 android/service/platform_api_stub.h create mode 100644 android/service/platform_server_proxy.cpp create mode 100644 android/service/platform_server_proxy.h create mode 100644 android/service/platform_service.cpp create mode 100644 android/service/platform_service.h create mode 100644 android/service/platform_service_interface.cpp create mode 100644 android/service/platform_service_interface.h create mode 100644 android/service/test_platform_service.cpp rename src/anbox/bridge/{platform_api_proxy.cpp => android_api_stub.cpp} (75%) rename src/anbox/bridge/{platform_api_proxy.h => android_api_stub.h} (91%) rename src/anbox/bridge/{platform_server.cpp => platform_api_skeleton.cpp} (81%) rename src/anbox/bridge/{platform_server.h => platform_api_skeleton.h} (79%) create mode 100644 src/anbox/common/dispatcher.cpp create mode 100644 src/anbox/common/dispatcher.h create mode 100644 src/anbox/support/bootanimation_message_processor.cpp create mode 100644 src/anbox/support/bootanimation_message_processor.h rename src/anbox/ubuntu/{platform_server.cpp => platform_api_skeleton.cpp} (53%) rename src/anbox/ubuntu/{platform_server.h => platform_api_skeleton.h} (61%) diff --git a/Android.mk b/Android.mk index 84d19ef..4dd9b16 100644 --- a/Android.mk +++ b/Android.mk @@ -28,8 +28,12 @@ LOCAL_SRC_FILES := \ android/service/host_connector.cpp \ android/service/local_socket_connection.cpp \ android/service/message_processor.cpp \ - android/service/platform_api.cpp \ + android/service/android_api_skeleton.cpp \ + android/service/platform_service_interface.cpp \ + android/service/platform_service.cpp \ + android/service/platform_api_stub.cpp \ src/anbox/common/fd.cpp \ + src/anbox/common/wait_handle.cpp \ src/anbox/bridge/message_processor.cpp \ src/anbox/bridge/pending_call_cache.cpp \ src/anbox/bridge/rpc_channel.cpp \ @@ -46,12 +50,30 @@ LOCAL_STATIC_LIBRARIES := \ LOCAL_SHARED_LIBRARIES := \ liblog \ libprotobuf-cpp-lite \ - libsysutils + libsysutils \ + libbinder \ + libcutils \ + libutils LOCAL_CFLAGS := \ -fexceptions \ -std=c++1y include $(BUILD_EXECUTABLE) +include $(CLEAR_VARS) +LOCAL_MODULE_CLASS := EXECUTABLES +LOCAL_MODULE := anbox_test_platform_service +LOCAL_SRC_FILES := \ + android/service/platform_service_interface.cpp \ + android/service/test_platform_service.cpp +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH)/android/service +LOCAL_SHARED_LIBRARIES := \ + liblog \ + libbinder \ + libcutils \ + libutils +include $(BUILD_EXECUTABLE) + # Include the Android.mk files below will override LOCAL_PATH so we # have to take a copy of it here. TMP_PATH := $(LOCAL_PATH) @@ -61,3 +83,4 @@ TMP_PATH := $(LOCAL_PATH) # include $(LOCAL_PATH)/android/shared_compositor/Android.mk include $(TMP_PATH)/android/launcher/Android.mk include $(TMP_PATH)/android/shared_compositor/Android.mk +include $(TMP_PATH)/android/bootanimation/Android.mk diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt index 40b37b6..4f0abe8 100644 --- a/android/CMakeLists.txt +++ b/android/CMakeLists.txt @@ -7,7 +7,10 @@ set(ANBOXD_SOURCES ${CMAKE_SOURCE_DIR}/src/anbox/bridge/message_processor.cpp ${CMAKE_SOURCE_DIR}/src/anbox/bridge/pending_call_cache.cpp ${CMAKE_SOURCE_DIR}/src/anbox/common/fd.cpp - service/platform_api.cpp + service/platform_service.cpp + service/platform_service_interface.cpp + service/platform_api_stub.cpp + service/android_api_skeleton.cpp service/message_processor.cpp service/local_socket_connection.cpp service/host_connector.cpp @@ -31,3 +34,13 @@ set(ANBOX_SHARED_COMPOSITOR add_executable(anbox_shared_compositor ${ANBOX_SHARED_COMPOSITOR}) set_target_properties(anbox_shared_compositor PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1) + +set(TEST_PLATFORM_SERVICE + service/test_platform_service.cpp) + +add_executable(test_platform_service ${TEST_PLATFORM_SERVICE}) +# As we're adding Android specific bits in this project we can't +# build this safely within default build anymore. We keep this +# for easy integration into used IDEs. +set_target_properties(test_platform_service + PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1) diff --git a/android/service/platform_api.cpp b/android/service/android_api_skeleton.cpp similarity index 85% rename from android/service/platform_api.cpp rename to android/service/android_api_skeleton.cpp index 4055340..15ba582 100644 --- a/android/service/platform_api.cpp +++ b/android/service/android_api_skeleton.cpp @@ -15,7 +15,7 @@ * */ -#include "android/service/platform_api.h" +#include "android/service/android_api_skeleton.h" #include "anbox_bridge.pb.h" @@ -30,14 +30,13 @@ std::map common_env = { } namespace anbox { -namespace android { -PlatformApi::PlatformApi() { +AndroidApiSkeleton::AndroidApiSkeleton() { } -PlatformApi::~PlatformApi() { +AndroidApiSkeleton::~AndroidApiSkeleton() { } -void PlatformApi::wait_for_process(core::posix::ChildProcess &process, +void AndroidApiSkeleton::wait_for_process(core::posix::ChildProcess &process, anbox::protobuf::bridge::Void *response) { const auto result = process.wait_for(core::posix::wait::Flags::untraced); if (result.status != core::posix::wait::Result::Status::exited || @@ -48,7 +47,7 @@ void PlatformApi::wait_for_process(core::posix::ChildProcess &process, } } -void PlatformApi::install_application(anbox::protobuf::bridge::InstallApplication const *request, +void AndroidApiSkeleton::install_application(anbox::protobuf::bridge::InstallApplication const *request, anbox::protobuf::bridge::Void *response, google::protobuf::Closure *done) { (void) response; @@ -65,7 +64,7 @@ void PlatformApi::install_application(anbox::protobuf::bridge::InstallApplicatio done->Run(); } -void PlatformApi::launch_application(anbox::protobuf::bridge::LaunchApplication const *request, +void AndroidApiSkeleton::launch_application(anbox::protobuf::bridge::LaunchApplication const *request, anbox::protobuf::bridge::Void *response, google::protobuf::Closure *done) { (void) response; @@ -86,7 +85,7 @@ void PlatformApi::launch_application(anbox::protobuf::bridge::LaunchApplication done->Run(); } -void PlatformApi::set_dns_servers(anbox::protobuf::bridge::SetDnsServers const *request, +void AndroidApiSkeleton::set_dns_servers(anbox::protobuf::bridge::SetDnsServers const *request, anbox::protobuf::bridge::Void *response, google::protobuf::Closure *done) { (void) response; @@ -107,4 +106,3 @@ void PlatformApi::set_dns_servers(anbox::protobuf::bridge::SetDnsServers const * done->Run(); } } // namespace anbox -} // namespace network diff --git a/android/service/platform_api.h b/android/service/android_api_skeleton.h similarity index 91% rename from android/service/platform_api.h rename to android/service/android_api_skeleton.h index 6e550b8..ac7577a 100644 --- a/android/service/platform_api.h +++ b/android/service/android_api_skeleton.h @@ -15,8 +15,8 @@ * */ -#ifndef ANBOX_ANDROID_PLATFORM_API_H_ -#define ANBOX_ANDROID_PLATFORM_API_H_ +#ifndef ANBOX_PLATFORM_API_SKELETON_H_ +#define ANBOX_PLATFORM_API_SKELETON_H_ namespace google { namespace protobuf { @@ -39,11 +39,10 @@ class SetDnsServers; class Void; } // namespace bridge } // namespace protobuf -namespace android { -class PlatformApi { +class AndroidApiSkeleton { public: - PlatformApi(); - ~PlatformApi(); + AndroidApiSkeleton(); + ~AndroidApiSkeleton(); void install_application(anbox::protobuf::bridge::InstallApplication const *request, anbox::protobuf::bridge::Void *response, @@ -61,7 +60,6 @@ private: void wait_for_process(core::posix::ChildProcess &process, anbox::protobuf::bridge::Void *response); }; -} // namespace android } // namespace anbox #endif diff --git a/android/service/daemon.cpp b/android/service/daemon.cpp index 8a2e627..6b3e41b 100644 --- a/android/service/daemon.cpp +++ b/android/service/daemon.cpp @@ -17,6 +17,7 @@ #include "android/service/daemon.h" #include "android/service/host_connector.h" +#include "android/service/platform_service.h" #include "core/posix/signal.h" @@ -24,8 +25,11 @@ #include +#include +#include +#include + namespace anbox { -namespace android { Daemon::Daemon() { } @@ -42,9 +46,16 @@ int Daemon::run() { auto host_connector = std::make_shared(); host_connector->start(); + android::defaultServiceManager()->addService( + android::String16(android::PlatformService::service_name()), + new android::PlatformService(host_connector->platform_api_stub())); + + android::ProcessState::self()->startThreadPool(); + trap->run(); + android::IPCThreadState::self()->joinThreadPool(); + return EXIT_SUCCESS; } -} // namespace android } // namespace anbox diff --git a/android/service/daemon.h b/android/service/daemon.h index 84f2bd1..6ce429b 100644 --- a/android/service/daemon.h +++ b/android/service/daemon.h @@ -19,7 +19,6 @@ #define ANBOX_ANDROID_DAEMON_H_ namespace anbox { -namespace android { class Daemon { public: Daemon(); @@ -27,7 +26,6 @@ public: int run(); }; -} // namespace android } // namespace anbox #endif diff --git a/android/service/host_connector.cpp b/android/service/host_connector.cpp index b4acda4..0da40d9 100644 --- a/android/service/host_connector.cpp +++ b/android/service/host_connector.cpp @@ -18,18 +18,22 @@ #include "android/service/host_connector.h" #include "android/service/local_socket_connection.h" #include "android/service/message_processor.h" -#include "android/service/platform_api.h" +#include "android/service/android_api_skeleton.h" +#include "android/service/platform_api_stub.h" + +#include "anbox/bridge/rpc_channel.h" #include #include namespace anbox { -namespace android { HostConnector::HostConnector() : socket_(std::make_shared("/dev/anbox_bridge")), pending_calls_(std::make_shared()), - platform_api_(std::make_shared()), - message_processor_(std::make_shared(socket_, pending_calls_, platform_api_)), + android_api_skeleton_(std::make_shared()), + message_processor_(std::make_shared(socket_, pending_calls_, android_api_skeleton_)), + rpc_channel_(std::make_shared(pending_calls_, socket_)), + platform_api_stub_(std::make_shared(rpc_channel_)), running_(false) { } @@ -61,7 +65,7 @@ void HostConnector::main_loop() { // MessageProcessor wants an vector so give it what it wants until // we refactor this. std::vector data; - for (auto n = 0; n < bytes_read; n++) + for (unsigned n = 0; n < bytes_read; n++) data.push_back(buffer[n]); if (!message_processor_->process_data(data)) @@ -70,5 +74,8 @@ void HostConnector::main_loop() { // FIXME notify our core that we've stopped } -} // namespace android + +std::shared_ptr HostConnector::platform_api_stub() const { + return platform_api_stub_; +} } // namespace anbox diff --git a/android/service/host_connector.h b/android/service/host_connector.h index 608752f..2360c72 100644 --- a/android/service/host_connector.h +++ b/android/service/host_connector.h @@ -25,11 +25,12 @@ namespace anbox { namespace bridge { class PendingCallCache; +class RpcChannel; } // namespace bridge -namespace android { class LocalSocketConnection; class MessageProcessor; -class PlatformApi; +class AndroidApiSkeleton; +class PlatformApiStub; class HostConnector { public: HostConnector(); @@ -38,17 +39,20 @@ public: void start(); void stop(); + std::shared_ptr platform_api_stub() const; + private: void main_loop(); std::shared_ptr socket_; std::shared_ptr pending_calls_; - std::shared_ptr platform_api_; + std::shared_ptr android_api_skeleton_; std::shared_ptr message_processor_; + std::shared_ptr rpc_channel_; + std::shared_ptr platform_api_stub_; std::thread thread_; std::atomic running_; }; -} // namespace android } // namespace anbox #endif diff --git a/android/service/local_socket_connection.cpp b/android/service/local_socket_connection.cpp index 12e6248..9b8dbea 100644 --- a/android/service/local_socket_connection.cpp +++ b/android/service/local_socket_connection.cpp @@ -23,6 +23,9 @@ #include #include +#define LOG_TAG "Anbox" +#include + namespace { bool socket_error_is_transient(int error_code) { return (error_code == EINTR); @@ -30,7 +33,6 @@ bool socket_error_is_transient(int error_code) { } namespace anbox { -namespace android { LocalSocketConnection::LocalSocketConnection(const std::string &path) : fd_(Fd::invalid) { @@ -52,12 +54,15 @@ LocalSocketConnection::~LocalSocketConnection() { ssize_t LocalSocketConnection::read_all(std::uint8_t *buffer, const size_t &size) { ssize_t bytes_read = ::recv(fd_, reinterpret_cast(buffer), size, 0); + ALOGI("Read %d bytes", bytes_read); return bytes_read; } void LocalSocketConnection::send(char const* data, size_t length) { size_t bytes_written{0}; + ALOGI("Writing %d bytes", length); + while(bytes_written < length) { ssize_t const result = ::send(fd_, data + bytes_written, @@ -73,5 +78,4 @@ void LocalSocketConnection::send(char const* data, size_t length) { bytes_written += result; } } -} // namespace android } // namespace anbox diff --git a/android/service/local_socket_connection.h b/android/service/local_socket_connection.h index 79fa7a0..eddad1b 100644 --- a/android/service/local_socket_connection.h +++ b/android/service/local_socket_connection.h @@ -25,7 +25,6 @@ #include "anbox/network/message_sender.h" namespace anbox { -namespace android { class LocalSocketConnection : public network::MessageSender { public: LocalSocketConnection(const std::string &path); @@ -37,7 +36,6 @@ public: private: Fd fd_; }; -} // namespace android } // namespace anbox #endif diff --git a/android/service/main.cpp b/android/service/main.cpp index 1220879..ec52c27 100644 --- a/android/service/main.cpp +++ b/android/service/main.cpp @@ -18,6 +18,6 @@ #include "android/service/daemon.h" int main(int, char**) { - anbox::android::Daemon daemon; + anbox::Daemon daemon; return daemon.run(); } diff --git a/android/service/message_processor.cpp b/android/service/message_processor.cpp index 1268476..1aee351 100644 --- a/android/service/message_processor.cpp +++ b/android/service/message_processor.cpp @@ -16,15 +16,14 @@ */ #include "android/service/message_processor.h" -#include "android/service/platform_api.h" +#include "android/service/android_api_skeleton.h" #include "anbox/bridge/template_message_processor.h" namespace anbox { -namespace android { MessageProcessor::MessageProcessor(const std::shared_ptr &sender, const std::shared_ptr &pending_calls, - const std::shared_ptr &platform_api) : + const std::shared_ptr &platform_api) : bridge::MessageProcessor(sender, pending_calls), platform_api_(platform_api) { } @@ -34,14 +33,13 @@ MessageProcessor::~MessageProcessor() { void MessageProcessor::dispatch(bridge::Invocation const& invocation) { if (invocation.method_name() == "install_application") - invoke(this, platform_api_.get(), &PlatformApi::install_application, invocation); + invoke(this, platform_api_.get(), &AndroidApiSkeleton::install_application, invocation); else if (invocation.method_name() == "launch_application") - invoke(this, platform_api_.get(), &PlatformApi::launch_application, invocation); + invoke(this, platform_api_.get(), &AndroidApiSkeleton::launch_application, invocation); else if (invocation.method_name() == "set_dns_servers") - invoke(this, platform_api_.get(), &PlatformApi::set_dns_servers, invocation); + invoke(this, platform_api_.get(), &AndroidApiSkeleton::set_dns_servers, invocation); } void MessageProcessor::process_event_sequence(const std::string&) { } -} // namespace anbox } // namespace network diff --git a/android/service/message_processor.h b/android/service/message_processor.h index eeab463..abb0769 100644 --- a/android/service/message_processor.h +++ b/android/service/message_processor.h @@ -21,22 +21,20 @@ #include "anbox/bridge/message_processor.h" namespace anbox { -namespace android { -class PlatformApi; +class AndroidApiSkeleton; class MessageProcessor : public bridge::MessageProcessor { public: MessageProcessor(const std::shared_ptr &sender, const std::shared_ptr &pending_calls, - const std::shared_ptr &platform_api); + const std::shared_ptr &platform_api); ~MessageProcessor(); void dispatch(bridge::Invocation const& invocation) override; void process_event_sequence(const std::string &event) override; private: - std::shared_ptr platform_api_; + std::shared_ptr platform_api_; }; -} // namespace anbox } // namespace network #endif diff --git a/android/service/platform_api_stub.cpp b/android/service/platform_api_stub.cpp new file mode 100644 index 0000000..7526fa1 --- /dev/null +++ b/android/service/platform_api_stub.cpp @@ -0,0 +1,57 @@ +/* + * 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 "android/service/platform_api_stub.h" +#include "anbox/bridge/rpc_channel.h" + +#include "anbox_bridge.pb.h" + +#define LOG_TAG "Anbox" +#include + +namespace anbox { +PlatformApiStub::PlatformApiStub(const std::shared_ptr &rpc_channel) : + rpc_channel_(rpc_channel) { +} + +void PlatformApiStub::boot_finished() { + auto c = std::make_shared>(); + + ALOGI("Boot finished"); + + { + std::lock_guard lock(mutex_); + boot_finished_wait_handle_.expect_result(); + } + + protobuf::bridge::Void message; + + rpc_channel_->call_method( + "boot_finished", + &message, c->response.get(), + google::protobuf::NewCallback(this, &PlatformApiStub::handle_boot_finished_response, c.get())); + + boot_finished_wait_handle_.wait_for_all(); + + ALOGI("Boot finished sent successfully!"); +} + +void PlatformApiStub::handle_boot_finished_response(Request*) { + ALOGI("handle_boot_finished_response"); + boot_finished_wait_handle_.result_received(); +} +} // namespace anbox diff --git a/android/service/platform_api_stub.h b/android/service/platform_api_stub.h new file mode 100644 index 0000000..5a8104c --- /dev/null +++ b/android/service/platform_api_stub.h @@ -0,0 +1,57 @@ +/* + * 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_PLATFORM_API_STUB_H_ +#define ANBOX_ANDROID_PLATFORM_API_STUB_H_ + +#include "anbox/common/wait_handle.h" + +#include + +namespace anbox { +namespace protobuf { +namespace bridge { +class Void; +} // namespace bridge +} // namespace protobuf +namespace bridge { +class RpcChannel; +} // namespace bridge +class PlatformApiStub { +public: + PlatformApiStub(const std::shared_ptr &rpc_channel); + + void boot_finished(); + +private: + template + struct Request { + Request() : response(std::make_shared()), success(true) { } + std::shared_ptr response; + bool success; + }; + + void handle_boot_finished_response(Request *request); + + mutable std::mutex mutex_; + common::WaitHandle boot_finished_wait_handle_; + + std::shared_ptr rpc_channel_; +}; +} // namespace anbox + +#endif diff --git a/android/service/platform_server_proxy.cpp b/android/service/platform_server_proxy.cpp new file mode 100644 index 0000000..e69de29 diff --git a/android/service/platform_server_proxy.h b/android/service/platform_server_proxy.h new file mode 100644 index 0000000..e69de29 diff --git a/android/service/platform_service.cpp b/android/service/platform_service.cpp new file mode 100644 index 0000000..901f2d7 --- /dev/null +++ b/android/service/platform_service.cpp @@ -0,0 +1,37 @@ +/* + * 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 "android/service/platform_service.h" +#include "android/service/platform_api_stub.h" +#include "anbox/bridge/rpc_channel.h" + +#define LOG_TAG "Anboxd" +#include + +using namespace android; + +namespace android { +PlatformService::PlatformService(const std::shared_ptr &platform_api_stub) : + platform_api_stub_(platform_api_stub) { +} + +status_t PlatformService::boot_finished() { + ALOGI("!!!!!!!!!!!!!!!!!!!!!!! BOOOT FINISHED --- ANBOXD"); + platform_api_stub_->boot_finished(); + return OK; +} +} // namespace android diff --git a/android/service/platform_service.h b/android/service/platform_service.h new file mode 100644 index 0000000..6fff224 --- /dev/null +++ b/android/service/platform_service.h @@ -0,0 +1,43 @@ +/* + * 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_PLATFORM_SERVICE_H_ +#define ANBOX_ANDROID_PLATFORM_SERVICE_H_ + +#include "android/service/platform_service_interface.h" + +#include + +namespace anbox { +class PlatformApiStub; +} // namespace anbox + +namespace android { +class PlatformService : public BnPlatformService { +public: + static const char* service_name() { return "anbox.PlatformService"; } + + PlatformService(const std::shared_ptr &platform_api_stub); + + status_t boot_finished() override; + +private: + std::shared_ptr platform_api_stub_; +}; +} // namespace android + +#endif diff --git a/android/service/platform_service_interface.cpp b/android/service/platform_service_interface.cpp new file mode 100644 index 0000000..f523738 --- /dev/null +++ b/android/service/platform_service_interface.cpp @@ -0,0 +1,45 @@ +/* + * 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 "android/service/platform_service_interface.h" + +namespace android { +BpPlatformService::BpPlatformService(const sp &binder) : + BpInterface(binder) { +} + +status_t BpPlatformService::boot_finished() { + Parcel data, reply; + data.writeInterfaceToken(IPlatformService::getInterfaceDescriptor()); + return remote()->transact(IPlatformService::BOOT_FINISHED, data, &reply); +} + +IMPLEMENT_META_INTERFACE(PlatformService, "anbox.IPlatformService"); + +status_t BnPlatformService::onTransact(uint32_t code, const Parcel &data, + Parcel *reply, uint32_t flags) { + switch (code) { + case BOOT_FINISHED: + CHECK_INTERFACE(IPlatformService, data, reply); + return boot_finished(); + default: + break; + } + + return BBinder::onTransact(code, data, reply, flags); +} +} // namespace android diff --git a/android/service/platform_service_interface.h b/android/service/platform_service_interface.h new file mode 100644 index 0000000..0a6c75a --- /dev/null +++ b/android/service/platform_service_interface.h @@ -0,0 +1,55 @@ +/* + * 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_PLATFORM_SERVICE_INTERFACE_H_ +#define ANBOX_ANDROID_PLATFORM_SERVICE_INTERFACE_H_ + +#include +#include +#include + +#include +#include + +#include + +namespace android { +class IPlatformService : public IInterface { +public: + DECLARE_META_INTERFACE(PlatformService); + + enum { + BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION, + }; + + virtual status_t boot_finished() = 0; +}; + +class BpPlatformService : public BpInterface { +public: + BpPlatformService(const sp &binder); + + status_t boot_finished() override; +}; + +class BnPlatformService : public BnInterface { +public: + virtual status_t onTransact(uint32_t code, const Parcel &data, + Parcel *reply, uint32_t flags); +}; +} // namespace android +#endif diff --git a/android/service/test_platform_service.cpp b/android/service/test_platform_service.cpp new file mode 100644 index 0000000..1435477 --- /dev/null +++ b/android/service/test_platform_service.cpp @@ -0,0 +1,34 @@ +/* + * 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 +#include +#include + +#include "android/service/platform_service_interface.h" + +int main(int, char**) { + auto binder = android::defaultServiceManager()->getService(android::String16("anbox.PlatformService")); + if (not binder.get()) + return 0; + + android::ProcessState::self()->startThreadPool(); + + android::sp platform_service = new android::BpPlatformService(binder); + + return platform_service->boot_finished(); +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d6ec191..edff3d5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,6 +45,7 @@ set(SOURCES anbox/common/fd_sets.h anbox/common/variable_length_array.h anbox/common/wait_handle.cpp + anbox/common/dispatcher.cpp anbox/network/message_sender.h anbox/network/message_receiver.h @@ -75,6 +76,7 @@ set(SOURCES anbox/support/fingerprint_message_processor.cpp anbox/support/gsm_message_processor.cpp anbox/support/at_parser.cpp + anbox/support/bootanimation_message_processor.cpp anbox/bridge/constants.h anbox/bridge/connection_creator.cpp @@ -83,11 +85,11 @@ set(SOURCES anbox/bridge/pending_call_cache.cpp anbox/bridge/make_protobuf_object.h anbox/bridge/platform_message_processor.cpp - anbox/bridge/platform_server.cpp + anbox/bridge/platform_api_skeleton.cpp anbox/bridge/rpc_channel.cpp - anbox/bridge/platform_api_proxy.cpp + anbox/bridge/android_api_stub.cpp - anbox/ubuntu/platform_server.cpp + anbox/ubuntu/platform_api_skeleton.cpp anbox/ubuntu/mir_display_connection.cpp anbox/ubuntu/window_creator.cpp anbox/ubuntu/window.cpp diff --git a/src/anbox/bridge/platform_api_proxy.cpp b/src/anbox/bridge/android_api_stub.cpp similarity index 75% rename from src/anbox/bridge/platform_api_proxy.cpp rename to src/anbox/bridge/android_api_stub.cpp index 6841fab..4a95f5c 100644 --- a/src/anbox/bridge/platform_api_proxy.cpp +++ b/src/anbox/bridge/android_api_stub.cpp @@ -15,7 +15,7 @@ * */ -#include "anbox/bridge/platform_api_proxy.h" +#include "anbox/bridge/android_api_stub.h" #include "anbox/bridge/rpc_channel.h" #include "anbox/utils.h" #include "anbox/config.h" @@ -29,26 +29,26 @@ namespace fs = boost::filesystem; namespace anbox { namespace bridge { -PlatformApiProxy::PlatformApiProxy() { +AndroidApiStub::AndroidApiStub() { } -PlatformApiProxy::~PlatformApiProxy() { +AndroidApiStub::~AndroidApiStub() { } -void PlatformApiProxy::set_rpc_channel(const std::shared_ptr &channel) { +void AndroidApiStub::set_rpc_channel(const std::shared_ptr &channel) { channel_ = channel; } -void PlatformApiProxy::reset_rpc_channel() { +void AndroidApiStub::reset_rpc_channel() { channel_.reset(); } -void PlatformApiProxy::ensure_rpc_channel() { +void AndroidApiStub::ensure_rpc_channel() { if (!channel_) throw std::runtime_error("No remote client connected"); } -void PlatformApiProxy::install(const std::string &path) { +void AndroidApiStub::install(const std::string &path) { ensure_rpc_channel(); const auto target_path = utils::string_format("%s/%s", @@ -74,7 +74,7 @@ void PlatformApiProxy::install(const std::string &path) { channel_->call_method("install_application", &message, c->response.get(), - google::protobuf::NewCallback(this, &PlatformApiProxy::application_installed, c.get())); + google::protobuf::NewCallback(this, &AndroidApiStub::application_installed, c.get())); install_wait_handle_.wait_for_all(); @@ -82,11 +82,11 @@ void PlatformApiProxy::install(const std::string &path) { throw std::runtime_error(c->response->error()); } -void PlatformApiProxy::application_installed(Request *request) { +void AndroidApiStub::application_installed(Request *request) { install_wait_handle_.result_received(); } -void PlatformApiProxy::launch(const std::string &package, const std::string &activity) { +void AndroidApiStub::launch(const std::string &package, const std::string &activity) { ensure_rpc_channel(); auto c = std::make_shared>(); @@ -102,7 +102,7 @@ void PlatformApiProxy::launch(const std::string &package, const std::string &act channel_->call_method("launch_application", &message, c->response.get(), - google::protobuf::NewCallback(this, &PlatformApiProxy::application_launched, c.get())); + google::protobuf::NewCallback(this, &AndroidApiStub::application_launched, c.get())); launch_wait_handle_.wait_for_all(); @@ -110,11 +110,11 @@ void PlatformApiProxy::launch(const std::string &package, const std::string &act throw std::runtime_error(c->response->error()); } -void PlatformApiProxy::application_launched(Request *request) { +void AndroidApiStub::application_launched(Request *request) { launch_wait_handle_.result_received(); } -void PlatformApiProxy::set_dns_servers(const std::string &domain, const std::vector &servers) { +void AndroidApiStub::set_dns_servers(const std::string &domain, const std::vector &servers) { ensure_rpc_channel(); auto c = std::make_shared>(); @@ -135,7 +135,7 @@ void PlatformApiProxy::set_dns_servers(const std::string &domain, const std::vec channel_->call_method("set_dns_servers", &message, c->response.get(), - google::protobuf::NewCallback(this, &PlatformApiProxy::dns_servers_set, c.get())); + google::protobuf::NewCallback(this, &AndroidApiStub::dns_servers_set, c.get())); set_dns_servers_wait_handle_.wait_for_all(); @@ -143,7 +143,7 @@ void PlatformApiProxy::set_dns_servers(const std::string &domain, const std::vec throw std::runtime_error(c->response->error()); } -void PlatformApiProxy::dns_servers_set(Request *request) { +void AndroidApiStub::dns_servers_set(Request *request) { set_dns_servers_wait_handle_.result_received(); } } // namespace bridge diff --git a/src/anbox/bridge/platform_api_proxy.h b/src/anbox/bridge/android_api_stub.h similarity index 91% rename from src/anbox/bridge/platform_api_proxy.h rename to src/anbox/bridge/android_api_stub.h index 25c8447..117fd13 100644 --- a/src/anbox/bridge/platform_api_proxy.h +++ b/src/anbox/bridge/android_api_stub.h @@ -15,8 +15,8 @@ * */ -#ifndef ANBOX_ANDROID_APPLICATION_MANAGER_H_ -#define ANBOX_ANDROID_APPLICATION_MANAGER_H_ +#ifndef ANBOX_BRIDGE_ANDROID_API_STUB_H_ +#define ANBOX_BRIDGE_ANDROID_API_STUB_H_ #include "anbox/application_manager.h" #include "anbox/common/wait_handle.h" @@ -32,10 +32,10 @@ class Void; } // namespace protobuf namespace bridge { class RpcChannel; -class PlatformApiProxy : public anbox::ApplicationManager { +class AndroidApiStub : public anbox::ApplicationManager { public: - PlatformApiProxy(); - ~PlatformApiProxy(); + AndroidApiStub(); + ~AndroidApiStub(); void set_rpc_channel(const std::shared_ptr &channel); void reset_rpc_channel(); diff --git a/src/anbox/bridge/platform_server.cpp b/src/anbox/bridge/platform_api_skeleton.cpp similarity index 81% rename from src/anbox/bridge/platform_server.cpp rename to src/anbox/bridge/platform_api_skeleton.cpp index 5476dc3..fd3d245 100644 --- a/src/anbox/bridge/platform_server.cpp +++ b/src/anbox/bridge/platform_api_skeleton.cpp @@ -15,18 +15,18 @@ * */ -#include "anbox/bridge/platform_server.h" +#include "anbox/bridge/platform_api_skeleton.h" #include "anbox/logger.h" #include "anbox_bridge.pb.h" namespace anbox { namespace bridge { -PlatformServer::PlatformServer(const std::shared_ptr &pending_calls) : +PlatformApiSkeleton::PlatformApiSkeleton(const std::shared_ptr &pending_calls) : pending_calls_(pending_calls) { } -PlatformServer::~PlatformServer() { +PlatformApiSkeleton::~PlatformApiSkeleton() { } } // namespace bridge } // namespace anbox diff --git a/src/anbox/bridge/platform_server.h b/src/anbox/bridge/platform_api_skeleton.h similarity index 79% rename from src/anbox/bridge/platform_server.h rename to src/anbox/bridge/platform_api_skeleton.h index 9745e03..f0fe9e4 100644 --- a/src/anbox/bridge/platform_server.h +++ b/src/anbox/bridge/platform_api_skeleton.h @@ -35,10 +35,14 @@ class Void; } // namespace protobuf namespace bridge { class PendingCallCache; -class PlatformServer { +class PlatformApiSkeleton { public: - PlatformServer(const std::shared_ptr &pending_calls); - virtual ~PlatformServer(); + PlatformApiSkeleton(const std::shared_ptr &pending_calls); + virtual ~PlatformApiSkeleton(); + + virtual void boot_finished(anbox::protobuf::bridge::Void const *request, + anbox::protobuf::bridge::Void *response, + google::protobuf::Closure *done) = 0; virtual void handle_notification(anbox::protobuf::bridge::Notification const *request, anbox::protobuf::bridge::Void *response, diff --git a/src/anbox/bridge/platform_message_processor.cpp b/src/anbox/bridge/platform_message_processor.cpp index 8edac86..d296dcf 100644 --- a/src/anbox/bridge/platform_message_processor.cpp +++ b/src/anbox/bridge/platform_message_processor.cpp @@ -16,7 +16,7 @@ */ #include "anbox/bridge/platform_message_processor.h" -#include "anbox/bridge/platform_server.h" +#include "anbox/bridge/platform_api_skeleton.h" #include "anbox/bridge/template_message_processor.h" #include "anbox_bridge.pb.h" @@ -24,7 +24,7 @@ namespace anbox { namespace bridge { PlatformMessageProcessor::PlatformMessageProcessor(const std::shared_ptr &sender, - const std::shared_ptr &server, + const std::shared_ptr &server, const std::shared_ptr &pending_calls) : MessageProcessor(sender, pending_calls), server_(server) { @@ -34,9 +34,10 @@ PlatformMessageProcessor::~PlatformMessageProcessor() { } void PlatformMessageProcessor::dispatch(Invocation const& invocation) { - if (invocation.method_name() == "handle_notification") { - invoke(this, server_.get(), &PlatformServer::handle_notification, invocation); - } + if (invocation.method_name() == "handle_notification") + invoke(this, server_.get(), &PlatformApiSkeleton::handle_notification, invocation); + else if (invocation.method_name() == "boot_finished") + invoke(this, server_.get(), &PlatformApiSkeleton::boot_finished, invocation); } void PlatformMessageProcessor::process_event_sequence(const std::string&) { diff --git a/src/anbox/bridge/platform_message_processor.h b/src/anbox/bridge/platform_message_processor.h index 34c5328..28085db 100644 --- a/src/anbox/bridge/platform_message_processor.h +++ b/src/anbox/bridge/platform_message_processor.h @@ -22,11 +22,11 @@ namespace anbox { namespace bridge { -class PlatformServer; +class PlatformApiSkeleton; class PlatformMessageProcessor : public MessageProcessor { public: PlatformMessageProcessor(const std::shared_ptr &sender, - const std::shared_ptr &server, + const std::shared_ptr &server, const std::shared_ptr &pending_calls); ~PlatformMessageProcessor(); @@ -34,7 +34,7 @@ public: void process_event_sequence(const std::string &event) override; private: - std::shared_ptr server_; + std::shared_ptr server_; }; } // namespace anbox } // namespace network diff --git a/src/anbox/cmds/run.cpp b/src/anbox/cmds/run.cpp index 6de115c..de04e4e 100644 --- a/src/anbox/cmds/run.cpp +++ b/src/anbox/cmds/run.cpp @@ -24,6 +24,7 @@ #include "anbox/container.h" #include "anbox/config.h" #include "anbox/pid_persister.h" +#include "anbox/common/dispatcher.h" #include "anbox/cmds/run.h" #include "anbox/network/published_socket_connector.h" #include "anbox/network/qemu_pipe_connection_creator.h" @@ -32,8 +33,8 @@ #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/bridge/android_api_stub.h" +#include "anbox/ubuntu/platform_api_skeleton.h" #include "anbox/ubuntu/window_creator.h" #include "anbox/dbus/skeleton/service.h" @@ -69,6 +70,11 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) // 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{"apk"}, cli::Description{"Android application to install on startup"}, apk_)); + flag(cli::make_flag(cli::Name{"package"}, cli::Description{"Specifies the package the activity should be launched from."}, package_)); + flag(cli::make_flag(cli::Name{"activity"}, cli::Description{"Activity to start from specified package"}, activity_)); + flag(cli::make_flag(cli::Name{"icon"}, cli::Description{"Icon of the application to run"}, icon_)); + action([this](const cli::Command::Context &ctx) { if (rootfs_.empty() || !fs::is_directory(fs::path(rootfs_))) { ctx.cout << "Not valid rootfs path provided" << std::endl; @@ -83,6 +89,7 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) }); auto rt = Runtime::create(); + auto dispatcher = anbox::common::create_dispatcher_for_runtime(rt); auto input_manager = std::make_shared(rt); @@ -102,9 +109,11 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) auto qemu_pipe_connector = std::make_shared( utils::string_format("%s/qemu_pipe", config::data_path()), rt, - std::make_shared(rt, renderer->socket_path())); + std::make_shared(rt, + renderer->socket_path(), + icon_)); - auto platform_proxy = std::make_shared(); + auto android_api_stub = std::make_shared(); auto bridge_connector = std::make_shared( utils::string_format("%s/anbox_bridge", config::data_path()), @@ -115,8 +124,28 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) 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); + android_api_stub->set_rpc_channel(rpc_channel); + + dispatcher->dispatch([&]() { + // FIXME make this configurable or once we have a bridge let the host + // act as a DNS proxy. + android_api_stub->set_dns_servers("anbox", std::vector{ "8.8.8.8" }); + }); + + auto server = std::make_shared(pending_calls); + // FIXME Implement a delegate or use signals from properties-cpp + server->on_boot_finished([&](){ + DEBUG("Boot finished."); + dispatcher->dispatch([&]() { + if (!apk_.empty()) { + DEBUG("Installing %s ..", apk_); + android_api_stub->install(apk_); + } + if (!package_.empty() || !activity_.empty()) + android_api_stub->launch(package_, activity_); + }); + }); + return std::make_shared(sender, server, pending_calls); })); @@ -156,7 +185,7 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) 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); + auto skeleton = anbox::dbus::skeleton::Service::create_for_bus(bus, android_api_stub); rt->start(); container->start(); diff --git a/src/anbox/cmds/run.h b/src/anbox/cmds/run.h index 2a02aec..f9dd2c2 100644 --- a/src/anbox/cmds/run.h +++ b/src/anbox/cmds/run.h @@ -40,6 +40,10 @@ private: BusFactory bus_factory_; std::string rootfs_; std::string desktop_file_hint_; + std::string apk_; + std::string package_; + std::string activity_; + std::string icon_; }; } // namespace cmds } // namespace anbox diff --git a/src/anbox/common/dispatcher.cpp b/src/anbox/common/dispatcher.cpp new file mode 100644 index 0000000..4a32c68 --- /dev/null +++ b/src/anbox/common/dispatcher.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 Canonical, Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + * + */ + +#include "anbox/common/dispatcher.h" + +namespace { +struct AsioStrandDispatcher : public anbox::common::Dispatcher { +public: + AsioStrandDispatcher(const std::shared_ptr& rt) + : rt{rt}, + strand{rt->service()} { + } + + void dispatch(const Task &task) override { + strand.post(task); + } + +private: + std::shared_ptr rt; + boost::asio::io_service::strand strand; +}; +} + +std::shared_ptr anbox::common::create_dispatcher_for_runtime( + const std::shared_ptr& rt) { + return std::make_shared(rt); +} diff --git a/src/anbox/common/dispatcher.h b/src/anbox/common/dispatcher.h new file mode 100644 index 0000000..8bd1eef --- /dev/null +++ b/src/anbox/common/dispatcher.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 Canonical, Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + * + */ + +#ifndef ANBOX_COMMON_DISPATCHER_H_ +#define ANBOX_COMMON_DISPATCHER_H_ + +#include "anbox/do_not_copy_or_move.h" +#include "anbox/runtime.h" + +#include + +namespace anbox { +namespace common { +class Dispatcher : public DoNotCopyOrMove { +public: + typedef std::function Task; + virtual void dispatch(const Task& task) = 0; + +protected: + Dispatcher() = default; +}; + +std::shared_ptr create_dispatcher_for_runtime(const std::shared_ptr&); +} // namespace common +} // namespace anbox + +#endif diff --git a/src/anbox/network/qemu_pipe_connection_creator.cpp b/src/anbox/network/qemu_pipe_connection_creator.cpp index 33cd86e..62e6c31 100644 --- a/src/anbox/network/qemu_pipe_connection_creator.cpp +++ b/src/anbox/network/qemu_pipe_connection_creator.cpp @@ -28,17 +28,20 @@ #include "anbox/support/camera_message_processor.h" #include "anbox/support/fingerprint_message_processor.h" #include "anbox/support/gsm_message_processor.h" +#include "anbox/support/bootanimation_message_processor.h" namespace ba = boost::asio; namespace anbox { namespace network { QemuPipeConnectionCreator::QemuPipeConnectionCreator(const std::shared_ptr &rt, - const std::string &renderer_socket_path) : + const std::string &renderer_socket_path, + const std::string &boot_animation_icon_path) : runtime_(rt), next_connection_id_(0), connections_(std::make_shared>()), - renderer_socket_path_(renderer_socket_path) { + renderer_socket_path_(renderer_socket_path), + boot_animation_icon_path_(boot_animation_icon_path) { } QemuPipeConnectionCreator::~QemuPipeConnectionCreator() { @@ -95,6 +98,8 @@ QemuPipeConnectionCreator::client_type QemuPipeConnectionCreator::identify_clien return client_type::qemud_fingerprint; else if (utils::string_starts_with(identifier_and_args, "pipe:qemud:gsm")) return client_type::qemud_gsm; + else if (utils::string_starts_with(identifier_and_args, "pipe:anbox:bootanimation")) + return client_type::bootanimation; return client_type::invalid; } @@ -114,6 +119,8 @@ std::shared_ptr QemuPipeConnectionCreator::create_processor(co return std::make_shared(messenger); else if (type == client_type::qemud_gsm) return std::make_shared(messenger); + else if (type == client_type::bootanimation) + return std::make_shared(messenger, boot_animation_icon_path_); return std::make_shared(); } diff --git a/src/anbox/network/qemu_pipe_connection_creator.h b/src/anbox/network/qemu_pipe_connection_creator.h index c9d5b41..bb13a60 100644 --- a/src/anbox/network/qemu_pipe_connection_creator.h +++ b/src/anbox/network/qemu_pipe_connection_creator.h @@ -36,7 +36,8 @@ class QemuPipeConnectionCreator : public ConnectionCreator { public: QemuPipeConnectionCreator( const std::shared_ptr &rt, - const std::string &renderer_socket_path); + const std::string &renderer_socket_path, + const std::string &boot_animation_icon_path); ~QemuPipeConnectionCreator() noexcept; void create_connection_for( @@ -51,6 +52,7 @@ public: qemud_camera, qemud_fingerprint, qemud_gsm, + bootanimation, }; private: @@ -65,6 +67,7 @@ private: std::shared_ptr> const connections_; std::string renderer_socket_path_; + std::string boot_animation_icon_path_; }; } // namespace anbox } // namespace network diff --git a/src/anbox/support/bootanimation_message_processor.cpp b/src/anbox/support/bootanimation_message_processor.cpp new file mode 100644 index 0000000..a36a85f --- /dev/null +++ b/src/anbox/support/bootanimation_message_processor.cpp @@ -0,0 +1,52 @@ +/* + * 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/logger.h" +#include "anbox/support/bootanimation_message_processor.h" + +#include + +namespace anbox { +namespace support { +BootAnimationMessageProcessor::BootAnimationMessageProcessor(const std::shared_ptr &messenger, + const std::string &icon_path) : + QemudMessageProcessor(messenger), + icon_path_(icon_path) { +} + +BootAnimationMessageProcessor::~BootAnimationMessageProcessor() { +} + +void BootAnimationMessageProcessor::handle_command(const std::string &command) { + DEBUG("command %s", command); + if (command == "retrieve-icon") + retrieve_icon(); +} + +void BootAnimationMessageProcessor::retrieve_icon() { + std::ifstream icon_file(icon_path_, std::ifstream::binary); + std::array buffer; + + while (icon_file.read(buffer.data(), buffer.size())) { + const auto bytes_read = icon_file.gcount(); + messenger_->send(buffer.data(), bytes_read); + DEBUG("Sending %d bytes", bytes_read); + } +} + +} // namespace support +} // namespace anbox diff --git a/src/anbox/support/bootanimation_message_processor.h b/src/anbox/support/bootanimation_message_processor.h new file mode 100644 index 0000000..3fb747b --- /dev/null +++ b/src/anbox/support/bootanimation_message_processor.h @@ -0,0 +1,42 @@ +/* + * 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_SUPPORT_BOOT_ANIMATION_MESSAGE_PROCESSOR_H_ +#define ANBOX_SUPPORT_BOOT_ANIMATION_MESSAGE_PROCESSOR_H_ + +#include "anbox/support/qemud_message_processor.h" + +namespace anbox { +namespace support { +class BootAnimationMessageProcessor : public QemudMessageProcessor { +public: + BootAnimationMessageProcessor(const std::shared_ptr &messenger, + const std::string &icon_path); + ~BootAnimationMessageProcessor(); + +protected: + void handle_command(const std::string &command) override; + +private: + void retrieve_icon(); + + std::string icon_path_; +}; +} // namespace graphics +} // namespace anbox + +#endif diff --git a/src/anbox/ubuntu/platform_server.cpp b/src/anbox/ubuntu/platform_api_skeleton.cpp similarity index 53% rename from src/anbox/ubuntu/platform_server.cpp rename to src/anbox/ubuntu/platform_api_skeleton.cpp index 1800530..59ecb52 100644 --- a/src/anbox/ubuntu/platform_server.cpp +++ b/src/anbox/ubuntu/platform_api_skeleton.cpp @@ -15,21 +15,23 @@ * */ -#include "anbox/ubuntu/platform_server.h" +#include "anbox/ubuntu/platform_api_skeleton.h" +#include "anbox/common/dispatcher.h" +#include "anbox/bridge/android_api_stub.h" #include "anbox/logger.h" #include "anbox_bridge.pb.h" namespace anbox { namespace ubuntu { -PlatformServer::PlatformServer(const std::shared_ptr &pending_calls) : - bridge::PlatformServer(pending_calls) { +PlatformApiSekeleton::PlatformApiSekeleton(const std::shared_ptr &pending_calls) : + bridge::PlatformApiSkeleton(pending_calls) { } -PlatformServer::~PlatformServer() { +PlatformApiSekeleton::~PlatformApiSekeleton() { } -void PlatformServer::handle_notification(anbox::protobuf::bridge::Notification const *request, +void PlatformApiSekeleton::handle_notification(anbox::protobuf::bridge::Notification const *request, anbox::protobuf::bridge::Void *response, google::protobuf::Closure *done) { (void) request; @@ -38,5 +40,20 @@ void PlatformServer::handle_notification(anbox::protobuf::bridge::Notification c done->Run(); } +void PlatformApiSekeleton::boot_finished(anbox::protobuf::bridge::Void const *request, + anbox::protobuf::bridge::Void *response, + google::protobuf::Closure *done) { + (void) request; + (void) response; + + if (on_boot_finished_action_) + on_boot_finished_action_(); + + done->Run(); +} + +void PlatformApiSekeleton::on_boot_finished(const std::function &action) { + on_boot_finished_action_ = action; +} } // namespace ubuntu } // namespace anbox diff --git a/src/anbox/ubuntu/platform_server.h b/src/anbox/ubuntu/platform_api_skeleton.h similarity index 61% rename from src/anbox/ubuntu/platform_server.h rename to src/anbox/ubuntu/platform_api_skeleton.h index e9f6001..c62b6fc 100644 --- a/src/anbox/ubuntu/platform_server.h +++ b/src/anbox/ubuntu/platform_api_skeleton.h @@ -18,18 +18,33 @@ #ifndef ANBOX_UBUNTU_PLATFORM_SERVER_H_ #define ANBOX_UBUNTU_PLATFORM_SERVER_H_ -#include "anbox/bridge/platform_server.h" +#include "anbox/bridge/platform_api_skeleton.h" namespace anbox { +namespace common { +class Dispatcher; +} // namespace common +namespace bridge { +class AndroidApiStub; +} // namespace bridge namespace ubuntu { -class PlatformServer : public bridge::PlatformServer { +class PlatformApiSekeleton : public bridge::PlatformApiSkeleton { public: - PlatformServer(const std::shared_ptr &pending_calls); - virtual ~PlatformServer(); + PlatformApiSekeleton(const std::shared_ptr &pending_calls); + virtual ~PlatformApiSekeleton(); void handle_notification(anbox::protobuf::bridge::Notification const *request, anbox::protobuf::bridge::Void *response, google::protobuf::Closure *done) override; + + void boot_finished(anbox::protobuf::bridge::Void const *request, + anbox::protobuf::bridge::Void *response, + google::protobuf::Closure *done) override; + + void on_boot_finished(const std::function &action); + +private: + std::function on_boot_finished_action_; }; } // namespace bridge } // namespace anbox