Rework some of the RPC service bits and add boot support

This commit is contained in:
Simon Fels 2016-07-04 12:10:31 +02:00
commit 1879e634c5
39 changed files with 746 additions and 106 deletions

View file

@ -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<std::string,std::string> 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

View file

@ -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

View file

@ -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 <cstdlib>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
namespace anbox {
namespace android {
Daemon::Daemon() {
}
@ -42,9 +46,16 @@ int Daemon::run() {
auto host_connector = std::make_shared<HostConnector>();
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

View file

@ -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

View file

@ -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 <functional>
#include <array>
namespace anbox {
namespace android {
HostConnector::HostConnector() :
socket_(std::make_shared<LocalSocketConnection>("/dev/anbox_bridge")),
pending_calls_(std::make_shared<bridge::PendingCallCache>()),
platform_api_(std::make_shared<PlatformApi>()),
message_processor_(std::make_shared<MessageProcessor>(socket_, pending_calls_, platform_api_)),
android_api_skeleton_(std::make_shared<AndroidApiSkeleton>()),
message_processor_(std::make_shared<MessageProcessor>(socket_, pending_calls_, android_api_skeleton_)),
rpc_channel_(std::make_shared<bridge::RpcChannel>(pending_calls_, socket_)),
platform_api_stub_(std::make_shared<PlatformApiStub>(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<std::uint8_t> 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<anbox::PlatformApiStub> HostConnector::platform_api_stub() const {
return platform_api_stub_;
}
} // namespace anbox

View file

@ -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<anbox::PlatformApiStub> platform_api_stub() const;
private:
void main_loop();
std::shared_ptr<LocalSocketConnection> socket_;
std::shared_ptr<bridge::PendingCallCache> pending_calls_;
std::shared_ptr<PlatformApi> platform_api_;
std::shared_ptr<AndroidApiSkeleton> android_api_skeleton_;
std::shared_ptr<MessageProcessor> message_processor_;
std::shared_ptr<bridge::RpcChannel> rpc_channel_;
std::shared_ptr<anbox::PlatformApiStub> platform_api_stub_;
std::thread thread_;
std::atomic<bool> running_;
};
} // namespace android
} // namespace anbox
#endif

View file

@ -23,6 +23,9 @@
#include <unistd.h>
#include <errno.h>
#define LOG_TAG "Anbox"
#include <cutils/log.h>
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<void*>(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

View file

@ -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

View file

@ -18,6 +18,6 @@
#include "android/service/daemon.h"
int main(int, char**) {
anbox::android::Daemon daemon;
anbox::Daemon daemon;
return daemon.run();
}

View file

@ -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<network::MessageSender> &sender,
const std::shared_ptr<bridge::PendingCallCache> &pending_calls,
const std::shared_ptr<PlatformApi> &platform_api) :
const std::shared_ptr<AndroidApiSkeleton> &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

View file

@ -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<network::MessageSender> &sender,
const std::shared_ptr<bridge::PendingCallCache> &pending_calls,
const std::shared_ptr<PlatformApi> &platform_api);
const std::shared_ptr<AndroidApiSkeleton> &platform_api);
~MessageProcessor();
void dispatch(bridge::Invocation const& invocation) override;
void process_event_sequence(const std::string &event) override;
private:
std::shared_ptr<PlatformApi> platform_api_;
std::shared_ptr<AndroidApiSkeleton> platform_api_;
};
} // namespace anbox
} // namespace network
#endif

View file

@ -0,0 +1,57 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include "android/service/platform_api_stub.h"
#include "anbox/bridge/rpc_channel.h"
#include "anbox_bridge.pb.h"
#define LOG_TAG "Anbox"
#include <cutils/log.h>
namespace anbox {
PlatformApiStub::PlatformApiStub(const std::shared_ptr<bridge::RpcChannel> &rpc_channel) :
rpc_channel_(rpc_channel) {
}
void PlatformApiStub::boot_finished() {
auto c = std::make_shared<Request<protobuf::bridge::Void>>();
ALOGI("Boot finished");
{
std::lock_guard<decltype(mutex_)> 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<protobuf::bridge::Void>*) {
ALOGI("handle_boot_finished_response");
boot_finished_wait_handle_.result_received();
}
} // namespace anbox

View file

@ -0,0 +1,57 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_ANDROID_PLATFORM_API_STUB_H_
#define ANBOX_ANDROID_PLATFORM_API_STUB_H_
#include "anbox/common/wait_handle.h"
#include <memory>
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<bridge::RpcChannel> &rpc_channel);
void boot_finished();
private:
template<typename Response>
struct Request {
Request() : response(std::make_shared<Response>()), success(true) { }
std::shared_ptr<Response> response;
bool success;
};
void handle_boot_finished_response(Request<protobuf::bridge::Void> *request);
mutable std::mutex mutex_;
common::WaitHandle boot_finished_wait_handle_;
std::shared_ptr<bridge::RpcChannel> rpc_channel_;
};
} // namespace anbox
#endif

View file

View file

@ -0,0 +1,37 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include "android/service/platform_service.h"
#include "android/service/platform_api_stub.h"
#include "anbox/bridge/rpc_channel.h"
#define LOG_TAG "Anboxd"
#include <cutils/log.h>
using namespace android;
namespace android {
PlatformService::PlatformService(const std::shared_ptr<anbox::PlatformApiStub> &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

View file

@ -0,0 +1,43 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_ANDROID_PLATFORM_SERVICE_H_
#define ANBOX_ANDROID_PLATFORM_SERVICE_H_
#include "android/service/platform_service_interface.h"
#include <memory>
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<anbox::PlatformApiStub> &platform_api_stub);
status_t boot_finished() override;
private:
std::shared_ptr<anbox::PlatformApiStub> platform_api_stub_;
};
} // namespace android
#endif

View file

@ -0,0 +1,45 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include "android/service/platform_service_interface.h"
namespace android {
BpPlatformService::BpPlatformService(const sp<IBinder> &binder) :
BpInterface<IPlatformService>(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

View file

@ -0,0 +1,55 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANBOX_ANDROID_PLATFORM_SERVICE_INTERFACE_H_
#define ANBOX_ANDROID_PLATFORM_SERVICE_INTERFACE_H_
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <utils/String16.h>
#include <utils/StrongPointer.h>
#include <cstdint>
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<IPlatformService> {
public:
BpPlatformService(const sp<IBinder> &binder);
status_t boot_finished() override;
};
class BnPlatformService : public BnInterface<IPlatformService> {
public:
virtual status_t onTransact(uint32_t code, const Parcel &data,
Parcel *reply, uint32_t flags);
};
} // namespace android
#endif

View file

@ -0,0 +1,34 @@
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#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<android::BpPlatformService> platform_service = new android::BpPlatformService(binder);
return platform_service->boot_finished();
}