Forward Android ready status through our app manager dbus object

This commit is contained in:
Simon Fels 2017-02-12 16:18:13 +01:00
commit 03acb32ece
11 changed files with 159 additions and 22 deletions

View file

@ -24,10 +24,13 @@
#include <string> #include <string>
#include <core/property.h>
namespace anbox { namespace anbox {
class ApplicationManager : public DoNotCopyOrMove { class ApplicationManager : public DoNotCopyOrMove {
public: public:
virtual void launch(const android::Intent &intent, const graphics::Rect &launch_bounds = graphics::Rect::Invalid) = 0; virtual void launch(const android::Intent &intent, const graphics::Rect &launch_bounds = graphics::Rect::Invalid) = 0;
virtual core::Property<bool>& ready() = 0;
}; };
} // namespace anbox } // namespace anbox

View file

@ -92,6 +92,10 @@ void AndroidApiStub::launch(const android::Intent &intent,
if (c->response->has_error()) throw std::runtime_error(c->response->error()); if (c->response->has_error()) throw std::runtime_error(c->response->error());
} }
core::Property<bool>& AndroidApiStub::ready() {
return ready_;
}
void AndroidApiStub::application_launched( void AndroidApiStub::application_launched(
Request<protobuf::rpc::Void> *request) { Request<protobuf::rpc::Void> *request) {
(void)request; (void)request;

View file

@ -43,13 +43,14 @@ class AndroidApiStub : public anbox::ApplicationManager {
void set_rpc_channel(const std::shared_ptr<rpc::Channel> &channel); void set_rpc_channel(const std::shared_ptr<rpc::Channel> &channel);
void reset_rpc_channel(); void reset_rpc_channel();
void launch(const android::Intent &intent, const graphics::Rect &launch_bounds = graphics::Rect::Invalid) override;
void set_focused_task(const std::int32_t &id); void set_focused_task(const std::int32_t &id);
void remove_task(const std::int32_t &id); void remove_task(const std::int32_t &id);
void resize_task(const std::int32_t &id, const anbox::graphics::Rect &rect, void resize_task(const std::int32_t &id, const anbox::graphics::Rect &rect,
const std::int32_t &resize_mode); const std::int32_t &resize_mode);
void launch(const android::Intent &intent, const graphics::Rect &launch_bounds = graphics::Rect::Invalid) override;
core::Property<bool>& ready() override;
private: private:
void ensure_rpc_channel(); void ensure_rpc_channel();
@ -72,6 +73,7 @@ class AndroidApiStub : public anbox::ApplicationManager {
common::WaitHandle remove_task_handle_; common::WaitHandle remove_task_handle_;
common::WaitHandle resize_task_handle_; common::WaitHandle resize_task_handle_;
graphics::Rect launch_bounds_ = graphics::Rect::Invalid; graphics::Rect launch_bounds_ = graphics::Rect::Invalid;
core::Property<bool> ready_;
}; };
} // namespace bridge } // namespace bridge
} // namespace anbox } // namespace anbox

View file

@ -16,14 +16,24 @@
*/ */
#include "anbox/cmds/launch.h" #include "anbox/cmds/launch.h"
#include "anbox/common/wait_handle.h"
#include "anbox/dbus/stub/application_manager.h" #include "anbox/dbus/stub/application_manager.h"
#include "anbox/common/dispatcher.h"
#include "anbox/runtime.h"
#include "anbox/logger.h"
#include <core/dbus/asio/executor.h> #include <core/dbus/asio/executor.h>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include "core/posix/signal.h"
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
namespace {
const boost::posix_time::seconds max_wait_timeout{30};
}
anbox::cmds::Launch::Launch() anbox::cmds::Launch::Launch()
: CommandWithFlagsAndAction{ : CommandWithFlagsAndAction{
cli::Name{"launch"}, cli::Usage{"launch"}, cli::Name{"launch"}, cli::Usage{"launch"},
@ -46,13 +56,69 @@ anbox::cmds::Launch::Launch()
intent_.component)); intent_.component));
action([this](const cli::Command::Context&) { action([this](const cli::Command::Context&) {
auto bus = auto trap = core::posix::trap_signals_for_process({core::posix::Signal::sig_term, core::posix::Signal::sig_int});
std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::session); trap->signal_raised().connect([trap](const core::posix::Signal& signal) {
bus->install_executor(core::dbus::asio::make_executor(bus)); INFO("Signal %i received. Good night.", static_cast<int>(signal));
auto stub = dbus::stub::ApplicationManager::create_for_bus(bus); trap->stop();
});
stub->launch(intent_); auto rt = Runtime::create();
return EXIT_SUCCESS; auto bus = std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::session);
bus->install_executor(core::dbus::asio::make_executor(bus, rt->service()));
std::shared_ptr<dbus::stub::ApplicationManager> stub;
try {
stub = dbus::stub::ApplicationManager::create_for_bus(bus);
} catch (...) {
ERROR("Anbox session manager service isn't running!");
return EXIT_FAILURE;
}
auto dispatcher = anbox::common::create_dispatcher_for_runtime(rt);
bool success = false;
dispatcher->dispatch([&]() {
if (stub->ready()) {
try {
stub->launch(intent_);
success = true;
} catch (std::exception &err) {
ERROR("err %s", err.what());
}
trap->stop();
return;
}
DEBUG("Android hasn't fully booted yet. Waiting a bit..");
stub->ready().changed().connect([&](bool ready) {
if (!ready)
return;
try {
stub->launch(intent_);
success = true;
} catch (std::exception &err) {
ERROR("Failed to launch activity: %s", err.what());
success = false;
}
trap->stop();
});
});
boost::asio::deadline_timer timer(rt->service());
timer.expires_from_now(max_wait_timeout);
timer.async_wait([&](const boost::system::error_code&) {
WARNING("Stop waiting as we're already waiting for too long. Something is wrong");
WARNING("with your setup and the container may have failed to boot.");
trap->stop();
});
rt->start();
trap->run();
rt->stop();
return success ? EXIT_SUCCESS : EXIT_FAILURE;
}); });
} }

View file

@ -176,8 +176,10 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory)
auto server = std::make_shared<bridge::PlatformApiSkeleton>( auto server = std::make_shared<bridge::PlatformApiSkeleton>(
pending_calls, policy, window_manager, launcher_storage); pending_calls, policy, window_manager, launcher_storage);
server->register_boot_finished_handler( server->register_boot_finished_handler([&]() {
[&]() { DEBUG("Android successfully booted"); }); DEBUG("Android successfully booted");
android_api_stub->ready().set(true);
});
return std::make_shared<bridge::PlatformMessageProcessor>( return std::make_shared<bridge::PlatformMessageProcessor>(
sender, server, pending_calls); sender, server, pending_calls);
})); }));

View file

@ -19,6 +19,7 @@
#define ANBOX_DBUS_INTERFACE_H_ #define ANBOX_DBUS_INTERFACE_H_
#include <core/dbus/macros.h> #include <core/dbus/macros.h>
#include <core/dbus/property.h>
#include <chrono> #include <chrono>
#include <string> #include <string>
@ -42,6 +43,9 @@ struct ApplicationManager {
} }
}; };
}; };
struct Properties {
DBUS_CPP_READABLE_PROPERTY_DEF(Ready, ApplicationManager, bool)
};
}; };
} // namespace interface } // namespace interface
} // namespace dbus } // namespace dbus

View file

@ -20,15 +20,19 @@
#include "anbox/dbus/interface.h" #include "anbox/dbus/interface.h"
#include "anbox/logger.h" #include "anbox/logger.h"
#include <core/property.h>
namespace anbox { namespace anbox {
namespace dbus { namespace dbus {
namespace skeleton { namespace skeleton {
ApplicationManager::ApplicationManager( ApplicationManager::ApplicationManager(
const core::dbus::Bus::Ptr &bus, const core::dbus::Object::Ptr &object, const core::dbus::Bus::Ptr &bus, const core::dbus::Object::Ptr &object,
const std::shared_ptr<anbox::ApplicationManager> &impl) const std::shared_ptr<anbox::ApplicationManager> &impl)
: bus_(bus), object_(object), impl_(impl) { : bus_(bus), object_(object), impl_(impl),
object_->install_method_handler< properties_{ object_->get_property<anbox::dbus::interface::ApplicationManager::Properties::Ready>() },
anbox::dbus::interface::ApplicationManager::Methods::Launch>( signals_{ object_->get_signal<core::dbus::interfaces::Properties::Signals::PropertiesChanged>() } {
object_->install_method_handler<anbox::dbus::interface::ApplicationManager::Methods::Launch>(
[this](const core::dbus::Message::Ptr &msg) { [this](const core::dbus::Message::Ptr &msg) {
auto reader = msg->reader(); auto reader = msg->reader();
@ -59,13 +63,38 @@ ApplicationManager::ApplicationManager(
bus_->send(reply); bus_->send(reply);
}); });
// Forward AndroidApi status to our dbus property
properties_.ready->install([&]() { return impl_->ready().get(); });
impl_->ready().changed().connect([&](bool value) {
properties_.ready->set(value);
on_property_value_changed<anbox::dbus::interface::ApplicationManager::Properties::Ready>(value);
});
} }
ApplicationManager::~ApplicationManager() {} ApplicationManager::~ApplicationManager() {}
template<typename Property>
void ApplicationManager::on_property_value_changed(const typename Property::ValueType& value)
{
typedef std::map<std::string, core::dbus::types::Variant> Dictionary;
static const std::vector<std::string> the_empty_list_of_invalidated_properties;
Dictionary dict; dict[Property::name()] = core::dbus::types::Variant::encode(value);
signals_.properties_changed->emit(
std::make_tuple(core::dbus::traits::Service<anbox::dbus::interface::ApplicationManager>::interface_name(),
dict, the_empty_list_of_invalidated_properties));
}
void ApplicationManager::launch(const android::Intent &intent, const graphics::Rect &launch_bounds) { void ApplicationManager::launch(const android::Intent &intent, const graphics::Rect &launch_bounds) {
impl_->launch(intent, launch_bounds); impl_->launch(intent, launch_bounds);
} }
core::Property<bool>& ApplicationManager::ready() {
return impl_->ready();
}
} // namespace skeleton } // namespace skeleton
} // namespace dbus } // namespace dbus
} // namespace anbox } // namespace anbox

View file

@ -23,6 +23,9 @@
#include <core/dbus/bus.h> #include <core/dbus/bus.h>
#include <core/dbus/object.h> #include <core/dbus/object.h>
#include <core/dbus/service.h> #include <core/dbus/service.h>
#include <core/dbus/property.h>
#include "anbox/dbus/interface.h"
namespace anbox { namespace anbox {
namespace dbus { namespace dbus {
@ -35,12 +38,23 @@ class ApplicationManager : public anbox::ApplicationManager {
~ApplicationManager(); ~ApplicationManager();
void launch(const android::Intent &intent, const graphics::Rect &launch_bounds = graphics::Rect::Invalid) override; void launch(const android::Intent &intent, const graphics::Rect &launch_bounds = graphics::Rect::Invalid) override;
core::Property<bool>& ready() override;
private: private:
template<typename Property>
void on_property_value_changed(const typename Property::ValueType& value);
core::dbus::Bus::Ptr bus_; core::dbus::Bus::Ptr bus_;
core::dbus::Service::Ptr service_; core::dbus::Service::Ptr service_;
core::dbus::Object::Ptr object_; core::dbus::Object::Ptr object_;
std::shared_ptr<anbox::ApplicationManager> impl_; std::shared_ptr<anbox::ApplicationManager> impl_;
struct {
std::shared_ptr<core::dbus::Property<anbox::dbus::interface::ApplicationManager::Properties::Ready>> ready;
} properties_;
struct {
core::dbus::Signal<core::dbus::interfaces::Properties::Signals::PropertiesChanged,
core::dbus::interfaces::Properties::Signals::PropertiesChanged::ArgumentType>::Ptr properties_changed;
} signals_;
}; };
} // namespace skeleton } // namespace skeleton
} // namespace dbus } // namespace dbus

View file

@ -39,8 +39,7 @@ Service::Service(
: bus_(bus), : bus_(bus),
service_(service), service_(service),
object_(object), object_(object),
application_manager_(std::make_shared<ApplicationManager>( application_manager_(std::make_shared<ApplicationManager>(bus_, object_, application_manager)) {}
bus_, object_, application_manager)) {}
Service::~Service() {} Service::~Service() {}
} // namespace skeleton } // namespace skeleton

View file

@ -22,19 +22,22 @@
namespace anbox { namespace anbox {
namespace dbus { namespace dbus {
namespace stub { namespace stub {
std::shared_ptr<ApplicationManager> ApplicationManager::create_for_bus( std::shared_ptr<ApplicationManager> ApplicationManager::create_for_bus(const core::dbus::Bus::Ptr &bus) {
const core::dbus::Bus::Ptr &bus) { auto service = core::dbus::Service::use_service_or_throw_if_not_available(bus, anbox::dbus::interface::Service::name());
auto service = core::dbus::Service::use_service( auto object = service->add_object_for_path(anbox::dbus::interface::Service::path());
bus, anbox::dbus::interface::Service::name());
auto object =
service->add_object_for_path(anbox::dbus::interface::Service::path());
return std::make_shared<ApplicationManager>(bus, service, object); return std::make_shared<ApplicationManager>(bus, service, object);
} }
ApplicationManager::ApplicationManager(const core::dbus::Bus::Ptr &bus, ApplicationManager::ApplicationManager(const core::dbus::Bus::Ptr &bus,
const core::dbus::Service::Ptr &service, const core::dbus::Service::Ptr &service,
const core::dbus::Object::Ptr &object) const core::dbus::Object::Ptr &object)
: bus_(bus), service_(service), object_(object) {} : bus_(bus), service_(service), object_(object),
properties_{ object_->get_property<anbox::dbus::interface::ApplicationManager::Properties::Ready>() } {
// Forward changes on the dbus property to our users
ready_.install([&]() { return properties_.ready->get(); });
properties_.ready->changed().connect([&](bool value) { ready_.set(value); });
}
ApplicationManager::~ApplicationManager() {} ApplicationManager::~ApplicationManager() {}
@ -48,6 +51,10 @@ void ApplicationManager::launch(const android::Intent &intent, const graphics::R
if (result.is_error()) throw std::runtime_error(result.error().print()); if (result.is_error()) throw std::runtime_error(result.error().print());
} }
core::Property<bool>& ApplicationManager::ready() {
return ready_;
}
} // namespace skeleton } // namespace skeleton
} // namespace dbus } // namespace dbus
} // namespace anbox } // namespace anbox

View file

@ -24,6 +24,8 @@
#include <core/dbus/object.h> #include <core/dbus/object.h>
#include <core/dbus/service.h> #include <core/dbus/service.h>
#include "anbox/dbus/interface.h"
namespace anbox { namespace anbox {
namespace dbus { namespace dbus {
namespace stub { namespace stub {
@ -38,11 +40,16 @@ class ApplicationManager : public anbox::ApplicationManager {
~ApplicationManager(); ~ApplicationManager();
void launch(const android::Intent &intent, const graphics::Rect &launch_bounds = graphics::Rect::Invalid) override; void launch(const android::Intent &intent, const graphics::Rect &launch_bounds = graphics::Rect::Invalid) override;
core::Property<bool>& ready() override;
private: private:
core::dbus::Bus::Ptr bus_; core::dbus::Bus::Ptr bus_;
core::dbus::Service::Ptr service_; core::dbus::Service::Ptr service_;
core::dbus::Object::Ptr object_; core::dbus::Object::Ptr object_;
core::Property<bool> ready_;
struct {
std::shared_ptr<core::dbus::Property<anbox::dbus::interface::ApplicationManager::Properties::Ready>> ready;
} properties_;
}; };
} // namespace stub } // namespace stub
} // namespace dbus } // namespace dbus