A bunch more changes to get the whole system properly booted
This commit is contained in:
parent
3222551702
commit
720b71f1e8
58 changed files with 1835 additions and 532 deletions
|
|
@ -3,6 +3,9 @@ include_directories(
|
|||
${GLIB_INCLUDE_DIRS}
|
||||
${GIO_INCLUDE_DIRS}
|
||||
${GIO-UNIX_INCLUDE_DIRS}
|
||||
${MIRCLIENT_INCLUDE_DIRS}
|
||||
${LIBEVDEV_INCLUDE_DIRS}
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/external/process-cpp-minimal/include
|
||||
${CMAKE_SOURCE_DIR}/external/android-emugl/host/include
|
||||
|
|
@ -16,9 +19,12 @@ set(SOURCES
|
|||
anbox/version.cpp
|
||||
anbox/daemon.cpp
|
||||
anbox/config.cpp
|
||||
anbox/not_reachable.cpp
|
||||
anbox/pid_persister.cpp
|
||||
anbox/namespace_attacher.cpp
|
||||
anbox/container.cpp
|
||||
anbox/container_connector.cpp
|
||||
anbox/input_channel.cpp
|
||||
|
||||
anbox/common/fd.cpp
|
||||
anbox/common/fd_sets.h
|
||||
|
|
@ -37,11 +43,18 @@ set(SOURCES
|
|||
anbox/network/delegate_message_processor.h
|
||||
|
||||
anbox/graphics/opengles_message_processor.cpp
|
||||
anbox/graphics/mir_display_connection.cpp
|
||||
anbox/graphics/mir_window.cpp
|
||||
anbox/graphics/mir_native_window_creator.cpp
|
||||
anbox/graphics/gl_renderer_server.cpp
|
||||
|
||||
anbox/support/null_message_processor.cpp
|
||||
anbox/support/qemud_message_processor.cpp
|
||||
anbox/support/boot_properties_message_processor.cpp
|
||||
anbox/support/hwcontrol_message_processor.cpp
|
||||
anbox/support/sensors_message_processor.cpp
|
||||
anbox/support/camera_message_processor.cpp
|
||||
anbox/support/fingerprint_message_processor.cpp
|
||||
|
||||
anbox/cmds/version.cpp
|
||||
anbox/cmds/run.cpp
|
||||
|
|
@ -55,15 +68,22 @@ add_library(anbox-core ${SOURCES})
|
|||
target_link_libraries(anbox-core
|
||||
${Boost_LDFLAGS}
|
||||
${Boost_LIBRARIES}
|
||||
${MIRCLIENT_LDFLAGS}
|
||||
${MIRCLIENT_LIBRARIES}
|
||||
${LIBEVDEV_LDFLAGS}
|
||||
${LIBEVDEV_LIBRARIES}
|
||||
pthread
|
||||
process-cpp
|
||||
bwrap
|
||||
OpenglRender)
|
||||
|
||||
add_executable(anbox main.cpp)
|
||||
target_link_libraries(anbox
|
||||
anbox-core)
|
||||
|
||||
add_executable(anbox-container container_main.cpp)
|
||||
target_link_libraries(anbox-container
|
||||
bwrap)
|
||||
|
||||
install(
|
||||
TARGETS anbox
|
||||
RUNTIME DESTINATION sbin
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "anbox/network/published_socket_connector.h"
|
||||
#include "anbox/network/qemu_pipe_connection_creator.h"
|
||||
#include "anbox/graphics/gl_renderer_server.h"
|
||||
#include "anbox/input_channel.h"
|
||||
|
||||
#include <sys/prctl.h>
|
||||
|
||||
|
|
@ -66,7 +67,9 @@ anbox::cmds::Run::Run()
|
|||
|
||||
auto rt = Runtime::create();
|
||||
|
||||
auto renderer = std::make_shared<graphics::GLRendererServer>();
|
||||
auto input_channel = std::make_shared<InputChannel>();
|
||||
|
||||
auto renderer = std::make_shared<graphics::GLRendererServer>(input_channel);
|
||||
renderer->start();
|
||||
|
||||
// Socket which will be used by the qemud service inside the Android
|
||||
|
|
@ -87,7 +90,11 @@ anbox::cmds::Run::Run()
|
|||
spec.rootfs_path = rootfs_;
|
||||
spec.bind_paths.insert({qemud_connector->socket_file(), "/dev/qemud"});
|
||||
spec.bind_paths.insert({qemu_pipe_connector->socket_file(), "/dev/qemu_pipe"});
|
||||
|
||||
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");
|
||||
// We isolate the container from accessing binder nodes of the host
|
||||
// through the IPC namespace which gets support for binder with extra
|
||||
// patches we require.
|
||||
|
|
@ -95,6 +102,11 @@ anbox::cmds::Run::Run()
|
|||
// Required for shared memory allocations. TODO(morphis): Letting the guest
|
||||
// access should be ok but needs more investigation.
|
||||
spec.dev_bind_paths.push_back("/dev/ashmem");
|
||||
// Our uinput based event node should get root:android_input assigned on Ubuntu
|
||||
// which is enough for our phablet user (being root inside the container) to
|
||||
// read event data from it.
|
||||
spec.dev_bind_paths.push_back({input_channel->dev_path()});
|
||||
spec.dev_bind_paths.push_back({"/dev/input/event7"});
|
||||
|
||||
auto container = Container::create(spec);
|
||||
|
||||
|
|
|
|||
|
|
@ -27,10 +27,12 @@
|
|||
namespace fs = boost::filesystem;
|
||||
|
||||
anbox::cmds::Shell::Shell()
|
||||
: CommandWithFlagsAndAction{cli::Name{"shell"}, cli::Usage{"shell"}, cli::Description{"Open a shell within the Anbox container"}}
|
||||
: CommandWithFlagsAndAction{cli::Name{"shell"}, cli::Usage{"shell"}, cli::Description{"Open a shell within the Anbox container"}},
|
||||
pid_(-1)
|
||||
{
|
||||
action([this](const cli::Command::Context &ctx) {
|
||||
ContainerConnector connector;
|
||||
flag(cli::make_flag(cli::Name{"pid"}, cli::Description{"PID of container to attach to"}, pid_));
|
||||
action([this](const cli::Command::Context &) {
|
||||
ContainerConnector connector(pid_);
|
||||
return connector.run("/system/bin/sh");
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ public:
|
|||
Shell();
|
||||
|
||||
private:
|
||||
std::string rootfs_;
|
||||
int pid_;
|
||||
};
|
||||
} // namespace cmds
|
||||
} // namespace anbox
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "core/posix/fork.h"
|
||||
#include "core/posix/exec.h"
|
||||
|
||||
|
|
@ -28,14 +31,15 @@
|
|||
#include "anbox/container.h"
|
||||
#include "anbox/common/fd.h"
|
||||
|
||||
extern "C" int bwrap_main(int argc, char **argv);
|
||||
#include <grp.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
namespace anbox {
|
||||
|
||||
Container::Spec Container::Spec::Default() {
|
||||
Spec spec;
|
||||
spec.init_command = "/init";
|
||||
spec.init_command = "/anbox-init.sh";
|
||||
spec.environment.insert({"PATH", "/system/bin:/system/sbin:/system/xbin"});
|
||||
return spec;
|
||||
}
|
||||
|
|
@ -53,66 +57,76 @@ Container::~Container() {
|
|||
stop();
|
||||
}
|
||||
|
||||
std::vector<Container::IdMapping> Container::read_id_mappings() {
|
||||
std::vector<Container::IdMapping> mappings;
|
||||
|
||||
static const std::string subuid_path = "/etc/subuid";
|
||||
static const std::string subgid_path = "/etc/subgid";
|
||||
|
||||
std::ifstream subuid_file(subuid_path);
|
||||
|
||||
return mappings;
|
||||
}
|
||||
|
||||
void Container::start() {
|
||||
std::vector<std::string> arguments = {
|
||||
"--ro-bind", spec_.rootfs_path, "/",
|
||||
DEBUG("uid %d gid %d", getuid(), getgid());
|
||||
std::vector<std::string> args = {
|
||||
// We need to setup user mapping here as lxc-usernsexec will not
|
||||
// map our current user to root which we need to allow our container
|
||||
// to access files we've created.
|
||||
"-m", utils::string_format("u:0:%d:1", getuid()),
|
||||
"-m", utils::string_format("g:0:%d:1", getgid()),
|
||||
// FIXME(morphis): We need to determine those things dynamically and
|
||||
// error out if not subui range is set for our current user.
|
||||
"-m", "u:1:100000:100000",
|
||||
"-m", "g:1:100000:100000",
|
||||
"--",
|
||||
// FIXME(morphis): use system or in-click path
|
||||
"/home/phablet/anbox-container",
|
||||
"--bind", spec_.rootfs_path, "/",
|
||||
"--dev", "/dev",
|
||||
"--proc", "/proc",
|
||||
"--unshare-user",
|
||||
"--unshare-ipc",
|
||||
"--unshare-pid",
|
||||
"--unshare-net",
|
||||
"--unshare-uts",
|
||||
// We will take UID 0 (root) inside the container
|
||||
"--uid", "0",
|
||||
// We will take GID 0 (root) inside the container
|
||||
"--gid", "0",
|
||||
"--chdir", "/",
|
||||
"--pid-file", utils::string_format("%s/pid", config::data_path()),
|
||||
};
|
||||
|
||||
for (const auto &dir : spec_.temporary_dirs) {
|
||||
arguments.push_back("--tmpfs");
|
||||
arguments.push_back(dir);
|
||||
args.push_back("--tmpfs");
|
||||
args.push_back(dir);
|
||||
}
|
||||
|
||||
for (const auto &path : spec_.dev_bind_paths) {
|
||||
arguments.push_back("--dev-bind");
|
||||
arguments.push_back(path);
|
||||
arguments.push_back(path);
|
||||
args.push_back("--dev-bind");
|
||||
args.push_back(path);
|
||||
args.push_back(path);
|
||||
}
|
||||
|
||||
for (const auto &path : spec_.bind_paths) {
|
||||
arguments.push_back("--bind");
|
||||
arguments.push_back(path.first);
|
||||
arguments.push_back(path.second);
|
||||
args.push_back("--bind");
|
||||
args.push_back(path.first);
|
||||
args.push_back(path.second);
|
||||
}
|
||||
|
||||
for (const auto &env : spec_.environment) {
|
||||
arguments.push_back("--setenv");
|
||||
arguments.push_back(env.first);
|
||||
arguments.push_back(env.second);
|
||||
args.push_back("--setenv");
|
||||
args.push_back(env.first);
|
||||
args.push_back(env.second);
|
||||
}
|
||||
|
||||
arguments.push_back(spec_.init_command);
|
||||
args.push_back(spec_.init_command);
|
||||
|
||||
child_ = core::posix::fork([&]() {
|
||||
char **it, **pargv;
|
||||
it = pargv = new char*[arguments.size() + 2];
|
||||
*it = strdup("bwrap");
|
||||
it++;
|
||||
for (auto arg : arguments) {
|
||||
*it = ::strdup(arg.c_str());
|
||||
it++;
|
||||
}
|
||||
*it = nullptr;
|
||||
|
||||
if (bwrap_main(arguments.size() + 1, pargv))
|
||||
return core::posix::exit::Status::failure;
|
||||
|
||||
return core::posix::exit::Status::success;
|
||||
}, core::posix::StandardStream::empty);
|
||||
std::map<std::string,std::string> env = {
|
||||
// lxc-usernsexec needs this as otherwise it doesn't find the
|
||||
// newuidmap/newgidmap utilities it uses to setup the user
|
||||
// namespace
|
||||
{ "PATH", "/usr/bin" },
|
||||
};
|
||||
|
||||
child_ = core::posix::exec("/usr/bin/lxc-usernsexec", args, env, core::posix::StandardStream::empty);
|
||||
child_group_ = child_.process_group_or_throw();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,20 @@ public:
|
|||
private:
|
||||
Container(const Container::Spec &spec);
|
||||
|
||||
struct IdMapping {
|
||||
enum class Type {
|
||||
UID,
|
||||
GID
|
||||
};
|
||||
|
||||
Type type;
|
||||
int hostid;
|
||||
int nsid;
|
||||
int range;
|
||||
};
|
||||
|
||||
std::vector<IdMapping> read_id_mappings();
|
||||
|
||||
Spec spec_;
|
||||
core::posix::ChildProcess child_;
|
||||
core::posix::ProcessGroup child_group_;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
|
||||
#include "anbox/container_connector.h"
|
||||
#include "anbox/namespace_attacher.h"
|
||||
#include "anbox/config.h"
|
||||
#include "anbox/utils.h"
|
||||
#include "anbox/logger.h"
|
||||
|
|
@ -32,101 +33,36 @@
|
|||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace {
|
||||
class NamespaceAttacher {
|
||||
public:
|
||||
enum class ns_type {
|
||||
user,
|
||||
pid,
|
||||
uts,
|
||||
mount,
|
||||
ipc,
|
||||
net,
|
||||
};
|
||||
|
||||
static std::string ns_type_to_string(ns_type type) {
|
||||
switch (type) {
|
||||
case ns_type::user:
|
||||
return "user";
|
||||
case ns_type::pid:
|
||||
return "pid";
|
||||
case ns_type::uts:
|
||||
return "uts";
|
||||
case ns_type::mount:
|
||||
return "mnt";
|
||||
case ns_type::ipc:
|
||||
return "ipc";
|
||||
case ns_type::net:
|
||||
return "net";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Unknown namespace type"));
|
||||
}
|
||||
|
||||
NamespaceAttacher(const std::vector<ns_type> &types, pid_t pid) :
|
||||
pid_(pid) {
|
||||
|
||||
attach(types);
|
||||
}
|
||||
|
||||
~NamespaceAttacher() {
|
||||
}
|
||||
|
||||
private:
|
||||
void attach(const std::vector<ns_type> &types) {
|
||||
std::vector<int> fds;
|
||||
for (const auto &type : types) {
|
||||
const auto path = anbox::utils::string_format("/proc/%lu/ns/%s", pid_, ns_type_to_string(type));
|
||||
if (!fs::exists(fs::path(path)))
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to open namespace file"));
|
||||
|
||||
const auto fd = ::open(path.c_str(), O_RDONLY);
|
||||
if (fd < 0)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to open namespace file"));
|
||||
|
||||
fds.push_back(fd);
|
||||
}
|
||||
|
||||
for (const auto &fd : fds) {
|
||||
if (::setns(fd, 0) == -1)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Could not attach to namespace"));
|
||||
|
||||
::close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
pid_t pid_;
|
||||
};
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
ContainerConnector::ContainerConnector() {
|
||||
ContainerConnector::ContainerConnector(int pid) :
|
||||
pid_(pid) {
|
||||
}
|
||||
|
||||
ContainerConnector::~ContainerConnector() {
|
||||
}
|
||||
|
||||
int ContainerConnector::run(const std::string &path) {
|
||||
const auto pid = std::stol(utils::read_file_if_exists_or_throw(
|
||||
int pid = pid_;
|
||||
if (pid == -1)
|
||||
pid = std::stol(utils::read_file_if_exists_or_throw(
|
||||
utils::string_format("%s/pid", config::data_path())));
|
||||
|
||||
if (!fs::is_directory(fs::path(utils::string_format("/proc/%i", pid))))
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Container isn't running"));
|
||||
|
||||
namespaces_ = std::make_shared<NamespaceAttacher>(std::vector<NamespaceAttacher::ns_type>{
|
||||
NamespaceAttacher::ns_type::user,
|
||||
NamespaceAttacher::ns_type::mount,
|
||||
NamespaceAttacher::ns_type::pid,
|
||||
NamespaceAttacher::ns_type::uts,
|
||||
NamespaceAttacher::ns_type::ipc,
|
||||
NamespaceAttacher::ns_type::net,
|
||||
namespaces_ = std::make_shared<NamespaceAttacher>(std::vector<NamespaceType>{
|
||||
NamespaceType::user,
|
||||
NamespaceType::mount,
|
||||
NamespaceType::pid,
|
||||
NamespaceType::uts,
|
||||
NamespaceType::ipc,
|
||||
NamespaceType::net,
|
||||
}, pid);
|
||||
|
||||
// A few things we want to preset in our env within the container shell
|
||||
std::map<std::string, std::string> env = {
|
||||
{ "ANDROID_ROOT", "/" }
|
||||
{ "ANDROID_ROOT", "/system" },
|
||||
{ "ANDROID_DATA", "/data" },
|
||||
};
|
||||
|
||||
auto child = core::posix::exec(path, {}, env, core::posix::StandardStream::empty, [this]() {
|
||||
|
|
@ -137,6 +73,9 @@ int ContainerConnector::run(const std::string &path) {
|
|||
if (::chroot("/newroot") != 0)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to enter container root filesystem"));
|
||||
|
||||
setuid(0);
|
||||
setgid(0);
|
||||
|
||||
chdir("/");
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -20,19 +20,17 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
namespace {
|
||||
class NamespaceAttacher;
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
class NamespaceAttacher;
|
||||
class ContainerConnector {
|
||||
public:
|
||||
ContainerConnector();
|
||||
ContainerConnector(int pid = -1);
|
||||
~ContainerConnector();
|
||||
|
||||
int run(const std::string &path);
|
||||
|
||||
private:
|
||||
int pid_;
|
||||
std::shared_ptr<NamespaceAttacher> namespaces_;
|
||||
};
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ try {
|
|||
}
|
||||
catch(std::exception &err) {
|
||||
ERROR("%s", err.what());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
void Daemon::ensure_data_path() {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/graphics/gl_renderer_server.h"
|
||||
#include "anbox/graphics/mir_native_window_creator.h"
|
||||
|
||||
#include "OpenglRender/render_api.h"
|
||||
|
||||
|
|
@ -26,7 +27,9 @@
|
|||
|
||||
namespace anbox {
|
||||
namespace graphics {
|
||||
GLRendererServer::GLRendererServer() {
|
||||
GLRendererServer::GLRendererServer(const std::shared_ptr<InputChannel> &input_channel) :
|
||||
window_creator_(std::make_shared<MirNativeWindowCreator>(input_channel)) {
|
||||
|
||||
// Force the host EGL/GLES libraries as translator implementation
|
||||
::setenv("ANDROID_EGL_LIB", "libEGL.so.1", 1);
|
||||
::setenv("ANDROID_GLESv1_LIB", "libGLESv1_CM.so.1", 1);
|
||||
|
|
@ -36,6 +39,8 @@ GLRendererServer::GLRendererServer() {
|
|||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize OpenGL renderer"));
|
||||
|
||||
setStreamMode(RENDER_API_STREAM_MODE_UNIX);
|
||||
|
||||
registerSubWindowHandler(window_creator_);
|
||||
}
|
||||
|
||||
GLRendererServer::~GLRendererServer() {
|
||||
|
|
|
|||
|
|
@ -19,13 +19,16 @@
|
|||
#define ANBOX_GRAPHICS_GL_RENDERER_SERVER_H_
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace anbox {
|
||||
class InputChannel;
|
||||
namespace graphics {
|
||||
class MirNativeWindowCreator;
|
||||
|
||||
class GLRendererServer {
|
||||
public:
|
||||
GLRendererServer();
|
||||
GLRendererServer(const std::shared_ptr<InputChannel> &input_channel);
|
||||
~GLRendererServer();
|
||||
|
||||
void start();
|
||||
|
|
@ -34,6 +37,7 @@ public:
|
|||
|
||||
private:
|
||||
std::string socket_path_;
|
||||
std::shared_ptr<MirNativeWindowCreator> window_creator_;
|
||||
};
|
||||
|
||||
} // namespace graphics
|
||||
|
|
|
|||
122
src/anbox/graphics/mir_display_connection.cpp
Normal file
122
src/anbox/graphics/mir_display_connection.cpp
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* 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 "anbox/graphics/mir_display_connection.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
static const MirDisplayOutput *find_active_output(
|
||||
const MirDisplayConfiguration *conf)
|
||||
{
|
||||
const MirDisplayOutput *output = NULL;
|
||||
int d;
|
||||
|
||||
for (d = 0; d < (int)conf->num_outputs; d++)
|
||||
{
|
||||
const MirDisplayOutput *out = conf->outputs + d;
|
||||
|
||||
if (out->used &&
|
||||
out->connected &&
|
||||
out->num_modes &&
|
||||
out->current_mode < out->num_modes)
|
||||
{
|
||||
output = out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
namespace graphics {
|
||||
MirDisplayConnection::MirDisplayConnection() :
|
||||
connection_(nullptr),
|
||||
output_id_(-1),
|
||||
vertical_resolution_(0),
|
||||
horizontal_resolution_(0) {
|
||||
|
||||
auto xdg_runtime_dir = ::getenv("XDG_RUNTIME_DIR");
|
||||
if (!xdg_runtime_dir)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to find XDG_RUNTIME_DIR"));
|
||||
|
||||
std::string socket_path = xdg_runtime_dir;
|
||||
socket_path += "/mir_socket";
|
||||
|
||||
connection_ = mir_connect_sync(socket_path.c_str(), "anbox");
|
||||
if (!mir_connection_is_valid(connection_)) {
|
||||
std::string msg;
|
||||
msg += "Failed to connect with Mir server: ";
|
||||
msg += mir_connection_get_error_message(connection_);
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(msg.c_str()));
|
||||
}
|
||||
|
||||
MirDisplayConfiguration* display_config =
|
||||
mir_connection_create_display_config(connection_);
|
||||
|
||||
const MirDisplayOutput *output = find_active_output(display_config);
|
||||
if (!output)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to find active output display"));
|
||||
|
||||
DEBUG("Selecting output id %d", output->output_id);
|
||||
|
||||
output_id_ = output->output_id;
|
||||
|
||||
const MirDisplayMode *mode = &output->modes[output->current_mode];
|
||||
vertical_resolution_ = mode->vertical_resolution;
|
||||
horizontal_resolution_ = mode->horizontal_resolution;
|
||||
|
||||
mir_display_config_destroy(display_config);
|
||||
}
|
||||
|
||||
MirDisplayConnection::~MirDisplayConnection() {
|
||||
mir_connection_release(connection_);
|
||||
}
|
||||
|
||||
MirConnection* MirDisplayConnection::connection() const {
|
||||
return connection_;
|
||||
}
|
||||
|
||||
MirPixelFormat MirDisplayConnection::default_pixel_format() const {
|
||||
MirPixelFormat format;
|
||||
unsigned int nformats;
|
||||
mir_connection_get_available_surface_formats(connection_, &format, 1, &nformats);
|
||||
return format;
|
||||
}
|
||||
|
||||
EGLNativeDisplayType MirDisplayConnection::native_display() const {
|
||||
return mir_connection_get_egl_native_display(connection_);
|
||||
}
|
||||
|
||||
int MirDisplayConnection::output_id() const {
|
||||
return output_id_;
|
||||
}
|
||||
|
||||
int MirDisplayConnection::vertical_resolution() const {
|
||||
return vertical_resolution_;
|
||||
}
|
||||
|
||||
int MirDisplayConnection::horizontal_resolution() const {
|
||||
return horizontal_resolution_;
|
||||
}
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
54
src/anbox/graphics/mir_display_connection.h
Normal file
54
src/anbox/graphics/mir_display_connection.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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_GRAPHICS_MIR_DISPLAY_CONNECTION_H_
|
||||
#define ANBOX_GRAPHICS_MIR_DISPLAY_CONNECTION_H_
|
||||
|
||||
#define MIR_EGL_PLATFORM
|
||||
|
||||
#include <mirclient/mir_toolkit/mir_client_library.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
namespace anbox {
|
||||
namespace graphics {
|
||||
|
||||
class MirDisplayConnection {
|
||||
public:
|
||||
MirDisplayConnection();
|
||||
~MirDisplayConnection();
|
||||
|
||||
MirPixelFormat default_pixel_format() const;
|
||||
|
||||
MirConnection* connection() const;
|
||||
EGLNativeDisplayType native_display() const;
|
||||
|
||||
int output_id() const;
|
||||
int vertical_resolution() const;
|
||||
int horizontal_resolution() const;
|
||||
|
||||
private:
|
||||
MirConnection *connection_;
|
||||
int output_id_;
|
||||
int vertical_resolution_;
|
||||
int horizontal_resolution_;
|
||||
};
|
||||
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
61
src/anbox/graphics/mir_native_window_creator.cpp
Normal file
61
src/anbox/graphics/mir_native_window_creator.cpp
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* 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 "anbox/graphics/mir_native_window_creator.h"
|
||||
#include "anbox/graphics/mir_display_connection.h"
|
||||
#include "anbox/graphics/mir_window.h"
|
||||
#include "anbox/input_channel.h"
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
namespace anbox {
|
||||
namespace graphics {
|
||||
MirNativeWindowCreator::MirNativeWindowCreator(const std::shared_ptr<InputChannel> &input_channel) :
|
||||
input_channel_(input_channel),
|
||||
display_connection_(std::make_shared<MirDisplayConnection>()) {
|
||||
|
||||
input_channel_->setup(display_connection_->horizontal_resolution(),
|
||||
display_connection_->vertical_resolution());
|
||||
}
|
||||
|
||||
MirNativeWindowCreator::~MirNativeWindowCreator() {
|
||||
}
|
||||
|
||||
EGLNativeWindowType MirNativeWindowCreator::create_window(int x, int y, int width, int height) {
|
||||
(void) x;
|
||||
(void) y;
|
||||
(void) width;
|
||||
(void) height;
|
||||
|
||||
if (windows_.size() > 0)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("We currently only allow a single native window"));
|
||||
|
||||
auto window = std::make_shared<MirWindow>(display_connection_, input_channel_);
|
||||
windows_.insert({window->native_window(), window});
|
||||
|
||||
return window->native_window();
|
||||
}
|
||||
|
||||
void MirNativeWindowCreator::destroy_window(EGLNativeWindowType win) {
|
||||
auto iter = windows_.find(win);
|
||||
if (iter == windows_.end())
|
||||
return;
|
||||
|
||||
windows_.erase(iter);
|
||||
}
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
51
src/anbox/graphics/mir_native_window_creator.h
Normal file
51
src/anbox/graphics/mir_native_window_creator.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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_GRAPHICS_MIR_NATIVE_WINDOW_CREATOR_H_
|
||||
#define ANBOX_GRAPHICS_MIR_NATIVE_WINDOW_CREATOR_H_
|
||||
|
||||
#include "external/android-emugl/host/libs/libOpenglRender/NativeSubWindow.h"
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
namespace anbox {
|
||||
class InputChannel;
|
||||
|
||||
namespace graphics {
|
||||
|
||||
class MirDisplayConnection;
|
||||
class MirWindow;
|
||||
|
||||
class MirNativeWindowCreator : public SubWindowHandler {
|
||||
public:
|
||||
MirNativeWindowCreator(const std::shared_ptr<InputChannel> &input_channel);
|
||||
virtual ~MirNativeWindowCreator();
|
||||
|
||||
EGLNativeWindowType create_window(int x, int y, int width, int height) override;
|
||||
void destroy_window(EGLNativeWindowType win) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<InputChannel> input_channel_;
|
||||
std::shared_ptr<MirDisplayConnection> display_connection_;
|
||||
std::map<EGLNativeWindowType,std::shared_ptr<MirWindow>> windows_;
|
||||
};
|
||||
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
107
src/anbox/graphics/mir_window.cpp
Normal file
107
src/anbox/graphics/mir_window.cpp
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* 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 "anbox/graphics/mir_window.h"
|
||||
#include "anbox/graphics/mir_display_connection.h"
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/input_channel.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace graphics {
|
||||
MirWindow::MirWindow(const std::shared_ptr<MirDisplayConnection> &display, const std::shared_ptr<InputChannel> &input_channel) :
|
||||
input_channel_(input_channel),
|
||||
native_window_(0),
|
||||
surface_(nullptr) {
|
||||
|
||||
const auto pixel_format = display->default_pixel_format();
|
||||
|
||||
DEBUG("Selected pixel format %i", pixel_format);
|
||||
|
||||
auto spec = mir_connection_create_spec_for_normal_surface(
|
||||
display->connection(),
|
||||
display->vertical_resolution(),
|
||||
display->horizontal_resolution(),
|
||||
pixel_format);
|
||||
|
||||
mir_surface_spec_set_name(spec, "anbox");
|
||||
mir_surface_spec_set_event_handler(spec, handle_surface_event, this);
|
||||
mir_surface_spec_set_fullscreen_on_output(spec, display->output_id());
|
||||
mir_surface_spec_set_buffer_usage(spec, mir_buffer_usage_hardware);
|
||||
|
||||
surface_ = mir_surface_create_sync(spec);
|
||||
mir_surface_spec_release(spec);
|
||||
|
||||
if (!mir_surface_is_valid(surface_)) {
|
||||
DEBUG("surface error: %s", mir_surface_get_error_message(surface_));
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create a Mir surface"));
|
||||
}
|
||||
|
||||
MirSurfaceParameters parameters;
|
||||
mir_surface_get_parameters(surface_, ¶meters);
|
||||
DEBUG("width %i height %i output id %i",
|
||||
parameters.width,
|
||||
parameters.height,
|
||||
parameters.output_id);
|
||||
|
||||
auto surface_buffer_stream = mir_surface_get_buffer_stream(surface_);
|
||||
native_window_ = reinterpret_cast<EGLNativeWindowType>(
|
||||
mir_buffer_stream_get_egl_native_window(surface_buffer_stream));
|
||||
}
|
||||
|
||||
MirWindow::~MirWindow() {
|
||||
}
|
||||
|
||||
void MirWindow::handle_touch_event(MirTouchEvent const* touch_event) {
|
||||
const auto action = mir_touch_event_action(touch_event, 0);
|
||||
}
|
||||
|
||||
void MirWindow::handle_input_event(MirInputEvent const* input_event) {
|
||||
const auto type = mir_input_event_get_type(input_event);
|
||||
MirTouchEvent const* touch_event = nullptr;
|
||||
MirKeyboardEvent const* key_event = nullptr;
|
||||
|
||||
switch (type) {
|
||||
case mir_input_event_type_touch:
|
||||
touch_event = mir_input_event_get_touch_event(input_event);
|
||||
handle_touch_event(touch_event);
|
||||
break;
|
||||
case mir_input_event_type_pointer:
|
||||
break;
|
||||
case mir_input_event_type_key:
|
||||
key_event = mir_input_event_get_keyboard_event(input_event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MirWindow::handle_surface_event(MirSurface *surface, MirEvent const* event, void *context) {
|
||||
const auto event_type = mir_event_get_type(event);
|
||||
auto thiz = static_cast<MirWindow*>(context);
|
||||
|
||||
switch (event_type) {
|
||||
case mir_event_type_input:
|
||||
thiz->handle_input_event(mir_event_get_input_event(event));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EGLNativeWindowType MirWindow::native_window() const {
|
||||
return native_window_;
|
||||
}
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
56
src/anbox/graphics/mir_window.h
Normal file
56
src/anbox/graphics/mir_window.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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_GRAPHICS_MIR_WINDOW_H_
|
||||
#define ANBOX_GRAPHICS_MIR_WINDOW_H_
|
||||
|
||||
#define MIR_EGL_PLATFORM
|
||||
|
||||
#include <mirclient/mir_toolkit/mir_client_library.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace anbox {
|
||||
class InputChannel;
|
||||
|
||||
namespace graphics {
|
||||
class MirDisplayConnection;
|
||||
|
||||
class MirWindow {
|
||||
public:
|
||||
MirWindow(const std::shared_ptr<MirDisplayConnection> &display, const std::shared_ptr<InputChannel> &input_channel);
|
||||
~MirWindow();
|
||||
|
||||
EGLNativeWindowType native_window() const;
|
||||
|
||||
private:
|
||||
static void handle_surface_event(MirSurface *surface, MirEvent const* event, void *context);
|
||||
|
||||
void handle_input_event(MirInputEvent const* input_event);
|
||||
void handle_touch_event(MirTouchEvent const* touch_event);
|
||||
|
||||
std::shared_ptr<InputChannel> input_channel_;
|
||||
EGLNativeWindowType native_window_;
|
||||
MirSurface *surface_;
|
||||
};
|
||||
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
282
src/anbox/id_map_writer.cpp
Normal file
282
src/anbox/id_map_writer.cpp
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* 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 "anbox/id_map_writer.h"
|
||||
#include "anbox/not_reachable.h"
|
||||
#include "anbox/utils.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <pwd.h>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
#define getid(type) ((unsigned) ((type) == GID ? getgid() : getuid()))
|
||||
#define idfile(type) ((type) == GID ? "gid_map" : "uid_map")
|
||||
#define idname(type) ((type) == GID ? "GID" : "UID")
|
||||
#define subpath(type) ((type) == GID ? "/etc/subgid" : "/etc/subuid")
|
||||
|
||||
namespace {
|
||||
char *append(char **destination, const char *format, ...) {
|
||||
char *extra, *result;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
if (vasprintf(&extra, format, args) < 0)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(""));
|
||||
va_end(args);
|
||||
|
||||
if (*destination == NULL) {
|
||||
*destination = extra;
|
||||
return extra;
|
||||
}
|
||||
|
||||
if (asprintf(&result, "%s%s", *destination, extra) < 0)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(""));
|
||||
free(*destination);
|
||||
free(extra);
|
||||
*destination = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
char *string(const char *format, ...) {
|
||||
char *result;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
if (vasprintf(&result, format, args) < 0)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(""));
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
static char *getmap(pid_t pid, int type) {
|
||||
char *line = NULL, *result = NULL, *path;
|
||||
size_t size;
|
||||
unsigned count, first, lower;
|
||||
FILE *file;
|
||||
|
||||
if (pid == -1)
|
||||
path = string("/proc/self/%s", idfile(type));
|
||||
else
|
||||
path = string("/proc/%d/%s", pid, idfile(type));
|
||||
if (!(file = fopen(path, "r")))
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(""));
|
||||
|
||||
while (getline(&line, &size, file) >= 0) {
|
||||
if (sscanf(line, " %u %u %u", &first, &lower, &count) != 3)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(""));
|
||||
append(&result, "%s%u:%u:%u", result ? "," : "", first, lower, count);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(""));
|
||||
|
||||
fclose(file);
|
||||
free(line);
|
||||
free(path);
|
||||
return result;
|
||||
}
|
||||
|
||||
static char *mapitem(char *map, unsigned *first, unsigned *lower,
|
||||
unsigned *count) {
|
||||
ssize_t skip;
|
||||
|
||||
while (map && *map && strchr(",;", *map))
|
||||
map++;
|
||||
if (map == NULL || *map == '\0')
|
||||
return NULL;
|
||||
if (sscanf(map, "%u:%u:%u%zn", first, lower, count, &skip) < 3)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(""));
|
||||
return map + skip;
|
||||
}
|
||||
|
||||
static char *rangeitem(char *range, unsigned *start, unsigned *length) {
|
||||
ssize_t skip;
|
||||
|
||||
while (range && *range && strchr(",;", *range))
|
||||
range++;
|
||||
if (range == NULL || *range == '\0')
|
||||
return NULL;
|
||||
if (sscanf(range, "%u:%u%zn", start, length, &skip) < 2)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(""));
|
||||
return range + skip;
|
||||
}
|
||||
|
||||
static char *readranges(int type) {
|
||||
char *line = NULL, *range, *user;
|
||||
size_t end, size;
|
||||
struct passwd *passwd;
|
||||
unsigned length, start;
|
||||
FILE *file;
|
||||
|
||||
range = string("%u:1", getid(type));
|
||||
if (!(file = fopen(subpath(type), "r")))
|
||||
return range;
|
||||
|
||||
user = getenv("USER");
|
||||
user = user ? user : getenv("LOGNAME");
|
||||
user = user ? user : getlogin();
|
||||
if (!user || !(passwd = getpwnam(user)) || passwd->pw_uid != getuid()) {
|
||||
if (!(passwd = getpwuid(getuid())))
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(""));
|
||||
user = passwd->pw_name;
|
||||
}
|
||||
endpwent();
|
||||
|
||||
while (getline(&line, &size, file) >= 0) {
|
||||
if (strncmp(line, user, strlen(user)))
|
||||
continue;
|
||||
if (sscanf(line + strlen(user), ":%u:%u%zn", &start, &length, &end) < 2)
|
||||
continue;
|
||||
if (strchr(":\n", line[end + strlen(user) + 1]))
|
||||
append(&range, ",%u:%u", start, length);
|
||||
}
|
||||
|
||||
free(line);
|
||||
fclose(file);
|
||||
return range;
|
||||
}
|
||||
|
||||
static char *rootdefault(int type) {
|
||||
char *cursor, *map, *result;
|
||||
unsigned count, first, last = INVALID, lower;
|
||||
|
||||
cursor = map = getmap(-1, type);
|
||||
while ((cursor = mapitem(cursor, &first, &lower, &count)))
|
||||
if (last == INVALID || last < first + count - 1)
|
||||
last = first + count - 1;
|
||||
result = string("0:%u:1", last);
|
||||
|
||||
cursor = map;
|
||||
while ((cursor = mapitem(cursor, &first, &lower, &count))) {
|
||||
if (first == 0) {
|
||||
if (count == 1 && first >= last)
|
||||
error(1, 0, "No unprivileged %s available\n", idname(type));
|
||||
first++, lower++, count--;
|
||||
}
|
||||
|
||||
if (last <= first + count - 1 && count > 0)
|
||||
count--;
|
||||
|
||||
if (count > 0)
|
||||
append(&result, "%s%u:%u:%u", result ? "," : "", first, first, count);
|
||||
}
|
||||
|
||||
free(map);
|
||||
return result;
|
||||
}
|
||||
|
||||
static char *userdefault(int type) {
|
||||
char *cursor, *map, *range, *result = NULL;
|
||||
unsigned count, first, index = 0, length, lower, start;
|
||||
|
||||
if (geteuid() != 0)
|
||||
return string("0:%u:1", getid(type));
|
||||
|
||||
map = getmap(-1, type);
|
||||
range = readranges(type);
|
||||
|
||||
while ((range = rangeitem(range, &start, &length))) {
|
||||
cursor = map;
|
||||
while ((cursor = mapitem(cursor, &first, &lower, &count))) {
|
||||
if (start + length <= first || first + count <= start)
|
||||
continue;
|
||||
if (first + count < start + length)
|
||||
length = start - first + count;
|
||||
if (start < first) {
|
||||
index += first - start;
|
||||
length -= first - start;
|
||||
start = first;
|
||||
}
|
||||
append(&result, "%s%u:%u:%u", result ? "," : "", index, start, length);
|
||||
index += length;
|
||||
}
|
||||
}
|
||||
|
||||
free(map);
|
||||
free(range);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void validate(char *range, unsigned first, unsigned count) {
|
||||
unsigned length, start;
|
||||
|
||||
while ((range = rangeitem(range, &start, &length)))
|
||||
if (first < start + length && start < first + count) {
|
||||
if (first < start)
|
||||
validate(range, first, start - first);
|
||||
if (first + count > start + length)
|
||||
validate(range, start + length, first + count - start - length);
|
||||
return;
|
||||
}
|
||||
error(1, 0, "Cannot map onto IDs that are not delegated to you");
|
||||
}
|
||||
|
||||
static void verifymap(char *map, char *range) {
|
||||
unsigned count, first, lower;
|
||||
|
||||
while ((map = mapitem(map, &first, &lower, &count)))
|
||||
validate(range, lower, count);
|
||||
}
|
||||
|
||||
static void writemap(pid_t pid, int type, char *map) {
|
||||
char *path, *range, *text = NULL;
|
||||
int fd;
|
||||
unsigned count, first, lower;
|
||||
|
||||
if (!map) {
|
||||
map = (getuid() == 0 ? rootdefault : userdefault)(type);
|
||||
} else if (getuid() != 0) {
|
||||
range = readranges(type);
|
||||
verifymap(map, range);
|
||||
free(range);
|
||||
}
|
||||
|
||||
while ((map = mapitem(map, &first, &lower, &count)))
|
||||
append(&text, "%u %u %u\n", first, lower, count);
|
||||
|
||||
path = string("/proc/%d/%s", pid, idfile(type));
|
||||
if ((fd = open(path, O_WRONLY)) < 0)
|
||||
error(1, 0, "Failed to set container %s map", idname(type));
|
||||
else if (write(fd, text, strlen(text)) != (ssize_t) strlen(text))
|
||||
error(1, 0, "Failed to set container %s map", idname(type));
|
||||
|
||||
close(fd);
|
||||
free(path);
|
||||
free(text);
|
||||
}
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
IdMapWriter::IdMapWriter(const Type &type, const pid_t &pid) :
|
||||
type_(type),
|
||||
pid_(pid) {
|
||||
}
|
||||
|
||||
IdMapWriter::~IdMapWriter() {
|
||||
}
|
||||
|
||||
void IdMapWriter::apply() {
|
||||
const auto map = retrieve_mappings();
|
||||
}
|
||||
|
||||
} // namespace anbox
|
||||
43
src/anbox/id_map_writer.h
Normal file
43
src/anbox/id_map_writer.h
Normal 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_ID_MAP_WRITER_H_
|
||||
#define ANBOX_ID_MAP_WRITER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace anbox {
|
||||
class IdMapWriter {
|
||||
public:
|
||||
enum class Type {
|
||||
UID,
|
||||
GID
|
||||
};
|
||||
|
||||
IdMapWriter(const Type &type, const pid_t &pid = -1);
|
||||
~IdMapWriter();
|
||||
|
||||
void apply();
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
pid_t pid_;
|
||||
};
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
75
src/anbox/input_channel.cpp
Normal file
75
src/anbox/input_channel.cpp
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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 "anbox/input_channel.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <libevdev/libevdev.h>
|
||||
#include <libevdev/libevdev-uinput.h>
|
||||
|
||||
namespace anbox {
|
||||
InputChannel::InputChannel() :
|
||||
dev_(nullptr) {
|
||||
}
|
||||
|
||||
InputChannel::~InputChannel() {
|
||||
if (dev_)
|
||||
libevdev_uinput_destroy(dev_);
|
||||
}
|
||||
|
||||
void InputChannel::setup(int width, int height) {
|
||||
DEBUG("");
|
||||
auto dev = libevdev_new();
|
||||
libevdev_set_name(dev, "anbox-tp");
|
||||
|
||||
libevdev_enable_event_type(dev, EV_ABS);
|
||||
struct input_absinfo mt_tracking_id = { 0, 0, 255, 0, 0, 0 };
|
||||
libevdev_enable_event_code(dev, EV_ABS, ABS_MT_TRACKING_ID, &mt_tracking_id);
|
||||
struct input_absinfo mt_slot = { 0, 0, 255, 0, 0, 0 };
|
||||
libevdev_enable_event_code(dev, EV_ABS, ABS_MT_SLOT, &mt_slot);
|
||||
struct input_absinfo mt_pos_x = { 0, 0, width, 0, 0, 0 };
|
||||
libevdev_enable_event_code(dev, EV_ABS, ABS_MT_POSITION_X, &mt_pos_x);
|
||||
struct input_absinfo mt_pos_y = { 0, 0, height, 0, 0, 0 };
|
||||
libevdev_enable_event_code(dev, EV_ABS, ABS_MT_POSITION_Y, &mt_pos_y);
|
||||
struct input_absinfo mt_pressure = { 0, 0, 5, 0, 0, 0 };
|
||||
libevdev_enable_event_code(dev, EV_ABS, ABS_MT_PRESSURE, &mt_pressure);
|
||||
|
||||
libevdev_enable_event_type(dev, EV_SYN);
|
||||
|
||||
libevdev_enable_property(dev, INPUT_PROP_DIRECT);
|
||||
|
||||
if (libevdev_uinput_create_from_device(dev, LIBEVDEV_UINPUT_OPEN_MANAGED, &dev_) < 0) {
|
||||
libevdev_free(dev);
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create uinput based device"));
|
||||
}
|
||||
}
|
||||
|
||||
void InputChannel::push_event(const Event &event) {
|
||||
libevdev_uinput_write_event(dev_, event.type, event.code, event.value);
|
||||
}
|
||||
|
||||
std::string InputChannel::dev_path() const {
|
||||
if (!dev_)
|
||||
return "";
|
||||
|
||||
return std::string(libevdev_uinput_get_devnode(dev_));
|
||||
}
|
||||
} // namespace anbox
|
||||
47
src/anbox/input_channel.h
Normal file
47
src/anbox/input_channel.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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_INPUT_CHANNEL_H_
|
||||
#define ANBOX_INPUT_CHANNEL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
struct libevdev_uinput;
|
||||
|
||||
namespace anbox {
|
||||
class InputChannel {
|
||||
public:
|
||||
InputChannel();
|
||||
~InputChannel();
|
||||
|
||||
struct Event {
|
||||
int type;
|
||||
int code;
|
||||
int value;
|
||||
};
|
||||
|
||||
void setup(int width, int height);
|
||||
void push_event(const Event &event);
|
||||
|
||||
std::string dev_path() const;
|
||||
|
||||
private:
|
||||
struct libevdev_uinput *dev_;
|
||||
};
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
81
src/anbox/namespace_attacher.cpp
Normal file
81
src/anbox/namespace_attacher.cpp
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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 "anbox/namespace_attacher.h"
|
||||
#include "anbox/utils.h"
|
||||
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace anbox {
|
||||
std::string NamespaceAttacher::ns_type_to_string(NamespaceType type) {
|
||||
switch (type) {
|
||||
case NamespaceType::user:
|
||||
return "user";
|
||||
case NamespaceType::pid:
|
||||
return "pid";
|
||||
case NamespaceType::uts:
|
||||
return "uts";
|
||||
case NamespaceType::mount:
|
||||
return "mnt";
|
||||
case NamespaceType::ipc:
|
||||
return "ipc";
|
||||
case NamespaceType::net:
|
||||
return "net";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Unknown namespace type"));
|
||||
}
|
||||
|
||||
NamespaceAttacher::NamespaceAttacher(const std::vector<NamespaceType> &types, pid_t pid) :
|
||||
pid_(pid) {
|
||||
|
||||
attach(types);
|
||||
}
|
||||
|
||||
NamespaceAttacher::~NamespaceAttacher() {
|
||||
}
|
||||
|
||||
void NamespaceAttacher::attach(const std::vector<NamespaceType> &types) {
|
||||
std::vector<int> fds;
|
||||
for (const auto &type : types) {
|
||||
const auto path = anbox::utils::string_format("/proc/%lu/ns/%s", pid_, ns_type_to_string(type));
|
||||
if (!fs::exists(fs::path(path)))
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to open namespace file"));
|
||||
|
||||
const auto fd = ::open(path.c_str(), O_RDONLY);
|
||||
if (fd < 0)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to open namespace file"));
|
||||
|
||||
fds.push_back(fd);
|
||||
}
|
||||
|
||||
for (const auto &fd : fds) {
|
||||
if (::setns(fd, 0) == -1)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Could not attach to namespace"));
|
||||
|
||||
::close(fd);
|
||||
}
|
||||
}
|
||||
} // namespace anbox
|
||||
49
src/anbox/namespace_attacher.h
Normal file
49
src/anbox/namespace_attacher.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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_NAMESPACE_ATTACHER_H_
|
||||
#define ANBOX_NAMESPACE_ATTACHER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace anbox {
|
||||
enum class NamespaceType {
|
||||
user,
|
||||
pid,
|
||||
uts,
|
||||
mount,
|
||||
ipc,
|
||||
net,
|
||||
};
|
||||
|
||||
class NamespaceAttacher {
|
||||
public:
|
||||
static std::string ns_type_to_string(NamespaceType type);
|
||||
|
||||
NamespaceAttacher(const std::vector<NamespaceType> &types, pid_t pid);
|
||||
~NamespaceAttacher();
|
||||
|
||||
private:
|
||||
void attach(const std::vector<NamespaceType> &types);
|
||||
|
||||
pid_t pid_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
|
@ -23,6 +23,10 @@
|
|||
#include "anbox/graphics/opengles_message_processor.h"
|
||||
#include "anbox/support/boot_properties_message_processor.h"
|
||||
#include "anbox/support/null_message_processor.h"
|
||||
#include "anbox/support/hwcontrol_message_processor.h"
|
||||
#include "anbox/support/sensors_message_processor.h"
|
||||
#include "anbox/support/camera_message_processor.h"
|
||||
#include "anbox/support/fingerprint_message_processor.h"
|
||||
|
||||
namespace ba = boost::asio;
|
||||
|
||||
|
|
@ -81,6 +85,14 @@ QemuPipeConnectionCreator::client_type QemuPipeConnectionCreator::identify_clien
|
|||
// take this as a own service instance as that is what it is.
|
||||
else if (utils::string_starts_with(identifier_and_args, "pipe:qemud:boot-properties"))
|
||||
return client_type::qemud_boot_properties;
|
||||
else if (utils::string_starts_with(identifier_and_args, "pipe:qemud:hw-control"))
|
||||
return client_type::qemud_hw_control;
|
||||
else if (utils::string_starts_with(identifier_and_args, "pipe:qemud:sensors"))
|
||||
return client_type::qemud_sensors;
|
||||
else if (utils::string_starts_with(identifier_and_args, "pipe:qemud:camera"))
|
||||
return client_type::qemud_camera;
|
||||
else if (utils::string_starts_with(identifier_and_args, "pipe:qemud:fingerprintlisten"))
|
||||
return client_type::qemud_fingerprint;
|
||||
|
||||
return client_type::invalid;
|
||||
}
|
||||
|
|
@ -90,6 +102,14 @@ std::shared_ptr<MessageProcessor> QemuPipeConnectionCreator::create_processor(co
|
|||
return std::make_shared<graphics::OpenGlesMessageProcessor>(renderer_socket_path_, runtime_, messenger);
|
||||
else if (type == client_type::qemud_boot_properties)
|
||||
return std::make_shared<support::BootPropertiesMessageProcessor>(messenger);
|
||||
else if (type == client_type::qemud_hw_control)
|
||||
return std::make_shared<support::HwControlMessageProcessor>(messenger);
|
||||
else if (type == client_type::qemud_sensors)
|
||||
return std::make_shared<support::SensorsMessageProcessor>(messenger);
|
||||
else if (type == client_type::qemud_camera)
|
||||
return std::make_shared<support::CameraMessageProcessor>(messenger);
|
||||
else if (type == client_type::qemud_fingerprint)
|
||||
return std::make_shared<support::FingerprintMessageProcessor>(messenger);
|
||||
|
||||
return std::make_shared<support::NullMessageProcessor>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,10 @@ public:
|
|||
invalid,
|
||||
opengles,
|
||||
qemud_boot_properties,
|
||||
qemud_hw_control,
|
||||
qemud_sensors,
|
||||
qemud_camera,
|
||||
qemud_fingerprint,
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -51,14 +51,22 @@ void SocketMessenger::send(char const* data, size_t length)
|
|||
VariableLengthArray<serialization_buffer_size> whole_message{length};
|
||||
std::copy(data, data + length, whole_message.data());
|
||||
|
||||
try {
|
||||
std::unique_lock<std::mutex> lg(message_lock);
|
||||
ba::write(*socket,
|
||||
ba::buffer(whole_message.data(), whole_message.size()),
|
||||
boost::asio::transfer_all());
|
||||
}
|
||||
catch (std::exception &err) {
|
||||
ERROR("Failed to write message: %s", err.what());
|
||||
while (true) {
|
||||
try {
|
||||
std::unique_lock<std::mutex> lg(message_lock);
|
||||
ba::write(*socket,
|
||||
ba::buffer(whole_message.data(), whole_message.size()),
|
||||
boost::asio::transfer_all());
|
||||
}
|
||||
catch (const boost::system::system_error &err) {
|
||||
if (err.code() == boost::asio::error::try_again)
|
||||
continue;
|
||||
}
|
||||
catch (const std::exception &err) {
|
||||
ERROR("Could not write message: %s", err.what());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
32
src/anbox/not_reachable.cpp
Normal file
32
src/anbox/not_reachable.cpp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Thomas Voß <thomas.voss@canonical.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/not_reachable.h"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
anbox::util::NotReachable::NotReachable(const std::string& function, const std::string& file, std::uint32_t line)
|
||||
: std::logic_error{(boost::format{"Code should not be reachable: %1% in %2%:%3%"} % function % file % line).str()}
|
||||
{
|
||||
}
|
||||
|
||||
void anbox::util::not_reachable(const std::string& function, const std::string& file, std::uint32_t line)
|
||||
{
|
||||
throw NotReachable{function, file, line};
|
||||
}
|
||||
40
src/anbox/not_reachable.h
Normal file
40
src/anbox/not_reachable.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authored by: Thomas Voß <thomas.voss@canonical.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_UTIL_NOT_REACHABLE_H_
|
||||
#define ANBOX_UTIL_NOT_REACHABLE_H_
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace anbox {
|
||||
namespace util {
|
||||
/// @brief NotReachable is thrown from not_reachable.
|
||||
struct NotReachable : public std::logic_error
|
||||
{
|
||||
/// @brief NotImplemented initializes a new instance for the given function name.
|
||||
NotReachable(const std::string& function, const std::string& file, std::uint32_t line);
|
||||
};
|
||||
|
||||
/// @brief not_reachable throws NotReachable.
|
||||
[[noreturn]] void not_reachable(const std::string& function, const std::string& file, std::uint32_t line);
|
||||
} // namespace util
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
|
|
@ -38,7 +38,7 @@ void exception_safe_run(boost::asio::io_service& service) {
|
|||
break;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "test" << e.what();
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Unknown exception caught while executing boost::asio::io_service";
|
||||
|
|
|
|||
|
|
@ -15,67 +15,24 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/support/boot_properties_message_processor.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
#include "anbox/network/connections.h"
|
||||
#include "anbox/network/delegate_message_processor.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace ba = boost::asio;
|
||||
|
||||
namespace {
|
||||
static constexpr const long header_size{4};
|
||||
}
|
||||
#include "anbox/logger.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
BootPropertiesMessageProcessor::BootPropertiesMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger) :
|
||||
messenger_(messenger) {
|
||||
QemudMessageProcessor(messenger) {
|
||||
}
|
||||
|
||||
BootPropertiesMessageProcessor::~BootPropertiesMessageProcessor() {
|
||||
}
|
||||
|
||||
bool BootPropertiesMessageProcessor::process_data(const std::vector<std::uint8_t> &data) {
|
||||
for (const auto &byte : data)
|
||||
buffer_.push_back(byte);
|
||||
|
||||
process_commands();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BootPropertiesMessageProcessor::process_commands() {
|
||||
while (true) {
|
||||
if (buffer_.size() < header_size)
|
||||
break;
|
||||
|
||||
char header[header_size] = { 0 };
|
||||
::memcpy(header, buffer_.data(), header_size);
|
||||
|
||||
unsigned int body_size = 0;
|
||||
::sscanf(header, "%04x", &body_size);
|
||||
if (body_size != buffer_.size() - header_size)
|
||||
break;
|
||||
|
||||
std::string command;
|
||||
// Make sure we only copy as much bytes as we have to and not more
|
||||
command.insert(0, reinterpret_cast<const char*>(buffer_.data()) + header_size, body_size);
|
||||
|
||||
if (command == "list")
|
||||
list_properties();
|
||||
else
|
||||
DEBUG("Unknown command '%s'", command);
|
||||
|
||||
const auto consumed = header_size + body_size;
|
||||
buffer_.erase(buffer_.begin(), buffer_.begin() + consumed);
|
||||
|
||||
const auto remaining = buffer_.size() - consumed;
|
||||
if (remaining <= 0)
|
||||
break;
|
||||
}
|
||||
void BootPropertiesMessageProcessor::handle_command(const std::string &command) {
|
||||
if (command == "list")
|
||||
list_properties();
|
||||
else
|
||||
DEBUG("Unknown command '%s'", command);
|
||||
}
|
||||
|
||||
void BootPropertiesMessageProcessor::list_properties() {
|
||||
|
|
@ -96,18 +53,20 @@ void BootPropertiesMessageProcessor::list_properties() {
|
|||
|
||||
// TODO(morphis): Using HDPI here for now but should be adjusted to the device
|
||||
// we're running on.
|
||||
"qemu.sf.lcd_density=240"
|
||||
"qemu.sf.lcd_density=240",
|
||||
|
||||
// libhwui detects that we support certain GLESv3 extensions which
|
||||
// we don't yet support in our host channel so we have to disable
|
||||
// those things here.
|
||||
"ro.hwui.use_gpu_pixel_buffers=0",
|
||||
};
|
||||
|
||||
for (const auto &prop : properties) {
|
||||
char header[header_size + 1];
|
||||
std::snprintf(header, header_size + 1, "%04x", prop.length());
|
||||
messenger_->send(header, header_size);
|
||||
send_header(prop.length());
|
||||
messenger_->send(prop.c_str(), prop.length());
|
||||
}
|
||||
|
||||
// Send terminating NULL byte
|
||||
messenger_->send(static_cast<const char*>(""), 1);
|
||||
finish_message();
|
||||
}
|
||||
} // namespace support
|
||||
} // namespace anbox
|
||||
|
|
|
|||
|
|
@ -18,30 +18,20 @@
|
|||
#ifndef ANBOX_SUPPORT_BOOT_PROPERTIES_MESSAGE_PROCESSOR_H_
|
||||
#define ANBOX_SUPPORT_BOOT_PROPERTIES_MESSAGE_PROCESSOR_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include "anbox/runtime.h"
|
||||
#include "anbox/network/message_processor.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
#include "anbox/network/socket_connection.h"
|
||||
#include "anbox/support/qemud_message_processor.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
class BootPropertiesMessageProcessor : public network::MessageProcessor {
|
||||
class BootPropertiesMessageProcessor : public QemudMessageProcessor {
|
||||
public:
|
||||
BootPropertiesMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger);
|
||||
~BootPropertiesMessageProcessor();
|
||||
|
||||
bool process_data(const std::vector<std::uint8_t> &data) override;
|
||||
protected:
|
||||
void handle_command(const std::string &command) override;
|
||||
|
||||
private:
|
||||
void process_commands();
|
||||
void list_properties();
|
||||
|
||||
std::shared_ptr<network::SocketMessenger> messenger_;
|
||||
std::vector<std::uint8_t> buffer_;
|
||||
};
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
|
|
|||
68
src/anbox/support/camera_message_processor.cpp
Normal file
68
src/anbox/support/camera_message_processor.cpp
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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 "anbox/logger.h"
|
||||
#include "anbox/support/camera_message_processor.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
CameraMessageProcessor::CameraMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger) :
|
||||
messenger_(messenger) {
|
||||
}
|
||||
|
||||
CameraMessageProcessor::~CameraMessageProcessor() {
|
||||
}
|
||||
|
||||
bool CameraMessageProcessor::process_data(const std::vector<std::uint8_t> &data) {
|
||||
DEBUG("Received: %s", utils::hex_dump(data.data(), data.size()));
|
||||
|
||||
for (const auto &byte : data)
|
||||
buffer_.push_back(byte);
|
||||
|
||||
process_commands();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CameraMessageProcessor::process_commands() {
|
||||
while (true) {
|
||||
size_t size;
|
||||
for (size = 0; size < buffer_.size(); size++) {
|
||||
if (buffer_.at(size) == 0x0)
|
||||
break;
|
||||
}
|
||||
|
||||
std::string command;
|
||||
command.insert(0, reinterpret_cast<const char*>(buffer_.data()), size);
|
||||
buffer_.erase(buffer_.begin(), buffer_.begin() + size);
|
||||
|
||||
handle_command(command);
|
||||
}
|
||||
}
|
||||
|
||||
void CameraMessageProcessor::handle_command(const std::string &command) {
|
||||
if (command == "list")
|
||||
list();
|
||||
}
|
||||
|
||||
void CameraMessageProcessor::list() {
|
||||
char buf[5];
|
||||
snprintf(buf, 5, "\n");
|
||||
messenger_->send(buf, strlen(buf));
|
||||
}
|
||||
} // namespace support
|
||||
} // namespace anbox
|
||||
45
src/anbox/support/camera_message_processor.h
Normal file
45
src/anbox/support/camera_message_processor.h
Normal 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_SUPPORT_CAMERA_MESSAGE_PROCESSOR_H_
|
||||
#define ANBOX_SUPPORT_CAMERA_MESSAGE_PROCESSOR_H_
|
||||
|
||||
#include "anbox/network/message_processor.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
class CameraMessageProcessor : public network::MessageProcessor {
|
||||
public:
|
||||
CameraMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger);
|
||||
~CameraMessageProcessor();
|
||||
|
||||
bool process_data(const std::vector<std::uint8_t> &data) override;
|
||||
|
||||
private:
|
||||
void process_commands();
|
||||
|
||||
void handle_command(const std::string &command);
|
||||
void list();
|
||||
|
||||
std::shared_ptr<network::SocketMessenger> messenger_;
|
||||
std::vector<std::uint8_t> buffer_;
|
||||
};
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
43
src/anbox/support/fingerprint_message_processor.cpp
Normal file
43
src/anbox/support/fingerprint_message_processor.cpp
Normal 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/support/fingerprint_message_processor.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
FingerprintMessageProcessor::FingerprintMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger) :
|
||||
QemudMessageProcessor(messenger) {
|
||||
}
|
||||
|
||||
FingerprintMessageProcessor::~FingerprintMessageProcessor() {
|
||||
}
|
||||
|
||||
void FingerprintMessageProcessor::handle_command(const std::string &command) {
|
||||
if (command == "listen")
|
||||
listen();
|
||||
}
|
||||
|
||||
void FingerprintMessageProcessor::listen() {
|
||||
char buf[12];
|
||||
snprintf(buf, sizeof(buf), "off");
|
||||
send_header(strlen(buf));
|
||||
messenger_->send(buf, strlen(buf));
|
||||
finish_message();
|
||||
}
|
||||
} // namespace support
|
||||
} // namespace anbox
|
||||
39
src/anbox/support/fingerprint_message_processor.h
Normal file
39
src/anbox/support/fingerprint_message_processor.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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_SUPPORT_FINGERPRINT_MESSAGE_PROCESSOR_H_
|
||||
#define ANBOX_SUPPORT_FINGERPRINT_MESSAGE_PROCESSOR_H_
|
||||
|
||||
#include "anbox/support/qemud_message_processor.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
class FingerprintMessageProcessor : public QemudMessageProcessor {
|
||||
public:
|
||||
FingerprintMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger);
|
||||
~FingerprintMessageProcessor();
|
||||
|
||||
protected:
|
||||
void handle_command(const std::string &command) override;
|
||||
|
||||
private:
|
||||
void listen();
|
||||
};
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
|
|
@ -15,68 +15,27 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/support/hwcontrol_message_processor.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
#include "anbox/network/connections.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace ba = boost::asio;
|
||||
|
||||
namespace {
|
||||
static constexpr const long header_size{4};
|
||||
}
|
||||
#include "anbox/logger.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
HwControlMessageProcessor::HwControlMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger) :
|
||||
messenger_(messenger) {
|
||||
QemudMessageProcessor(messenger) {
|
||||
}
|
||||
|
||||
HwControlMessageProcessor::~HwControlMessageProcessor() {
|
||||
}
|
||||
|
||||
bool HwControlMessageProcessor::process_data(const std::vector<std::uint8_t> &data) {
|
||||
for (const auto &byte : data)
|
||||
buffer_.push_back(byte);
|
||||
|
||||
process_commands();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HwControlMessageProcessor::process_commands() {
|
||||
while (true) {
|
||||
if (buffer_.size() < header_size)
|
||||
break;
|
||||
|
||||
char header[header_size] = { 0 };
|
||||
::memcpy(header, buffer_.data(), header_size);
|
||||
|
||||
unsigned int body_size = 0;
|
||||
::sscanf(header, "%04x", &body_size);
|
||||
if (body_size != buffer_.size() - header_size)
|
||||
break;
|
||||
|
||||
std::string command;
|
||||
// Make sure we only copy as much bytes as we have to and not more
|
||||
command.insert(0, reinterpret_cast<const char*>(buffer_.data()) + header_size, body_size);
|
||||
|
||||
if (command == "power:screen_state:wake")
|
||||
DEBUG("Got screen wake command");
|
||||
else if (command == "power:screen_state:standby")
|
||||
DEBUG("Got screen standby command");
|
||||
else
|
||||
DEBUG("Unknown command '%s'", command);
|
||||
|
||||
const auto consumed = header_size + body_size;
|
||||
buffer_.erase(buffer_.begin(), buffer_.begin() + consumed);
|
||||
|
||||
const auto remaining = buffer_.size() - consumed;
|
||||
if (remaining <= 0)
|
||||
break;
|
||||
}
|
||||
void HwControlMessageProcessor::handle_command(const std::string &command) {
|
||||
if (command == "power:screen_state:wake")
|
||||
DEBUG("Got screen wake command");
|
||||
else if (command == "power:screen_state:standby")
|
||||
DEBUG("Got screen standby command");
|
||||
else if (utils::string_starts_with(command, "power:light:brightness:lcd_backlight"))
|
||||
DEBUG("Got LCD backligh brightness control command");
|
||||
else
|
||||
DEBUG("Unknown command '%s'", command);
|
||||
}
|
||||
} // namespace support
|
||||
} // namespace anbox
|
||||
|
|
|
|||
|
|
@ -18,29 +18,17 @@
|
|||
#ifndef ANBOX_SUPPORT_HWCONTROL_MESSAGE_PROCESSOR_H_
|
||||
#define ANBOX_SUPPORT_HWCONTROL_MESSAGE_PROCESSOR_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include "anbox/runtime.h"
|
||||
#include "anbox/network/message_processor.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
#include "anbox/network/socket_connection.h"
|
||||
#include "anbox/support/qemud_message_processor.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
class HwControlMessageProcessor : public network::MessageProcessor {
|
||||
class HwControlMessageProcessor : public QemudMessageProcessor {
|
||||
public:
|
||||
HwControlMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger);
|
||||
~HwControlMessageProcessor();
|
||||
|
||||
bool process_data(const std::vector<std::uint8_t> &data) override;
|
||||
|
||||
private:
|
||||
void process_commands();
|
||||
|
||||
std::shared_ptr<network::SocketMessenger> messenger_;
|
||||
std::vector<std::uint8_t> buffer_;
|
||||
protected:
|
||||
void handle_command(const std::string &command) override;
|
||||
};
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
*/
|
||||
|
||||
#include "anbox/support/null_message_processor.h"
|
||||
#include "anbox/utils.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
|
@ -27,7 +29,8 @@ NullMessageProcessor::NullMessageProcessor() {
|
|||
NullMessageProcessor::~NullMessageProcessor() {
|
||||
}
|
||||
|
||||
bool NullMessageProcessor::process_data(const std::vector<std::uint8_t>&) {
|
||||
bool NullMessageProcessor::process_data(const std::vector<std::uint8_t> &data) {
|
||||
DEBUG("Received: %s", utils::hex_dump(data.data(), data.size()));
|
||||
return true;
|
||||
}
|
||||
} // namespace support
|
||||
|
|
|
|||
|
|
@ -18,11 +18,6 @@
|
|||
#ifndef ANBOX_SUPPORT_NULL_MESSAGE_PROCESSOR_H_
|
||||
#define ANBOX_SUPPORT_NULL_MESSAGE_PROCESSOR_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include "anbox/runtime.h"
|
||||
#include "anbox/network/message_processor.h"
|
||||
|
||||
namespace anbox {
|
||||
|
|
|
|||
87
src/anbox/support/qemud_message_processor.cpp
Normal file
87
src/anbox/support/qemud_message_processor.cpp
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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 "anbox/support/qemud_message_processor.h"
|
||||
#include "anbox/utils.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace {
|
||||
static constexpr const long header_size{4};
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
QemudMessageProcessor::QemudMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger) :
|
||||
messenger_(messenger) {
|
||||
}
|
||||
|
||||
QemudMessageProcessor::~QemudMessageProcessor() {
|
||||
}
|
||||
|
||||
bool QemudMessageProcessor::process_data(const std::vector<std::uint8_t> &data) {
|
||||
DEBUG("Received: %s", utils::hex_dump(data.data(), data.size()));
|
||||
|
||||
for (const auto &byte : data)
|
||||
buffer_.push_back(byte);
|
||||
|
||||
process_commands();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QemudMessageProcessor::process_commands() {
|
||||
while (true) {
|
||||
if (buffer_.size() < header_size)
|
||||
break;
|
||||
|
||||
char header[header_size] = { 0 };
|
||||
::memcpy(header, buffer_.data(), header_size);
|
||||
|
||||
unsigned int body_size = 0;
|
||||
::sscanf(header, "%04x", &body_size);
|
||||
if (body_size != buffer_.size() - header_size)
|
||||
break;
|
||||
|
||||
std::string command;
|
||||
// Make sure we only copy as much bytes as we have to and not more
|
||||
command.insert(0, reinterpret_cast<const char*>(buffer_.data()) + header_size, body_size);
|
||||
|
||||
handle_command(command);
|
||||
|
||||
const auto consumed = header_size + body_size;
|
||||
buffer_.erase(buffer_.begin(), buffer_.begin() + consumed);
|
||||
|
||||
const auto remaining = buffer_.size() - consumed;
|
||||
if (remaining <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QemudMessageProcessor::send_header(const size_t &size) {
|
||||
char header[header_size + 1];
|
||||
std::snprintf(header, header_size + 1, "%04x", size);
|
||||
messenger_->send(header, header_size);
|
||||
}
|
||||
|
||||
void QemudMessageProcessor::finish_message() {
|
||||
// Send terminating NULL byte
|
||||
messenger_->send(static_cast<const char*>(""), 1);
|
||||
}
|
||||
} // namespace support
|
||||
} // namespace anbox
|
||||
49
src/anbox/support/qemud_message_processor.h
Normal file
49
src/anbox/support/qemud_message_processor.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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_SUPPORT_QEMUD_MESSAGE_PROCESSOR_H_
|
||||
#define ANBOX_SUPPORT_QEMUD_MESSAGE_PROCESSOR_H_
|
||||
|
||||
#include "anbox/network/message_processor.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
class QemudMessageProcessor : public network::MessageProcessor {
|
||||
public:
|
||||
QemudMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger);
|
||||
~QemudMessageProcessor();
|
||||
|
||||
bool process_data(const std::vector<std::uint8_t> &data) override;
|
||||
|
||||
protected:
|
||||
virtual void handle_command(const std::string &command) = 0;
|
||||
|
||||
void send_header(const size_t &size);
|
||||
void finish_message();
|
||||
|
||||
std::shared_ptr<network::SocketMessenger> messenger_;
|
||||
|
||||
private:
|
||||
void process_commands();
|
||||
|
||||
std::vector<std::uint8_t> buffer_;
|
||||
};
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
46
src/anbox/support/sensors_message_processor.cpp
Normal file
46
src/anbox/support/sensors_message_processor.cpp
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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 "anbox/logger.h"
|
||||
#include "anbox/support/sensors_message_processor.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
SensorsMessageProcessor::SensorsMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger) :
|
||||
QemudMessageProcessor(messenger) {
|
||||
}
|
||||
|
||||
SensorsMessageProcessor::~SensorsMessageProcessor() {
|
||||
}
|
||||
|
||||
void SensorsMessageProcessor::handle_command(const std::string &command) {
|
||||
DEBUG("command %s", command);
|
||||
if (command == "list-sensors")
|
||||
list_sensors();
|
||||
}
|
||||
|
||||
void SensorsMessageProcessor::list_sensors() {
|
||||
// We don't support sensors yet so we mark all as disabled
|
||||
int mask = 0;
|
||||
char buf[12];
|
||||
snprintf(buf, sizeof(buf), "%d", mask);
|
||||
send_header(strlen(buf));
|
||||
messenger_->send(buf, strlen(buf));
|
||||
finish_message();
|
||||
}
|
||||
} // namespace support
|
||||
} // namespace anbox
|
||||
39
src/anbox/support/sensors_message_processor.h
Normal file
39
src/anbox/support/sensors_message_processor.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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_SUPPORT_SENSORS_MESSAGE_PROCESSOR_H_
|
||||
#define ANBOX_SUPPORT_SENSORS_MESSAGE_PROCESSOR_H_
|
||||
|
||||
#include "anbox/support/qemud_message_processor.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace support {
|
||||
class SensorsMessageProcessor : public QemudMessageProcessor {
|
||||
public:
|
||||
SensorsMessageProcessor(const std::shared_ptr<network::SocketMessenger> &messenger);
|
||||
~SensorsMessageProcessor();
|
||||
|
||||
protected:
|
||||
void handle_command(const std::string &command) override;
|
||||
|
||||
private:
|
||||
void list_sensors();
|
||||
};
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
|
|
@ -132,5 +132,12 @@ std::string hex_dump(const uint8_t *data, uint32_t size) {
|
|||
return buffer.str();
|
||||
}
|
||||
|
||||
std::string get_env_value(const std::string &name, const std::string &default_value) {
|
||||
char *value = getenv(name.c_str());
|
||||
if (!value)
|
||||
return default_value;
|
||||
return std::string(value);
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
} // namespace anbox
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ bool string_starts_with(const std::string &text, const std::string &prefix);
|
|||
|
||||
std::string hex_dump(const uint8_t *data, uint32_t size);
|
||||
|
||||
std::string get_env_value(const std::string &name, const std::string &default_value = "");
|
||||
|
||||
template<typename... Types>
|
||||
static std::string string_format(const std::string& fmt_str, Types&&... args);
|
||||
} // namespace utils
|
||||
|
|
|
|||
22
src/container_main.cpp
Normal file
22
src/container_main.cpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
extern "C" int bwrap_main(int argc, char **argv);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
return bwrap_main(argc, argv);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue