Implement input event forwarding
This commit is contained in:
parent
309fd3021d
commit
f75a9f4f1c
18 changed files with 590 additions and 38 deletions
|
|
@ -40,6 +40,7 @@ set(SOURCES
|
||||||
anbox/network/socket_connection.cpp
|
anbox/network/socket_connection.cpp
|
||||||
anbox/network/socket_messenger.cpp
|
anbox/network/socket_messenger.cpp
|
||||||
anbox/network/delegate_message_processor.h
|
anbox/network/delegate_message_processor.h
|
||||||
|
anbox/network/delegate_connection_creator.h
|
||||||
|
|
||||||
anbox/graphics/opengles_message_processor.cpp
|
anbox/graphics/opengles_message_processor.cpp
|
||||||
anbox/graphics/mir_display_connection.cpp
|
anbox/graphics/mir_display_connection.cpp
|
||||||
|
|
@ -47,6 +48,9 @@ set(SOURCES
|
||||||
anbox/graphics/mir_native_window_creator.cpp
|
anbox/graphics/mir_native_window_creator.cpp
|
||||||
anbox/graphics/gl_renderer_server.cpp
|
anbox/graphics/gl_renderer_server.cpp
|
||||||
|
|
||||||
|
anbox/input/manager.cpp
|
||||||
|
anbox/input/device.cpp
|
||||||
|
|
||||||
anbox/support/null_message_processor.cpp
|
anbox/support/null_message_processor.cpp
|
||||||
anbox/support/qemud_message_processor.cpp
|
anbox/support/qemud_message_processor.cpp
|
||||||
anbox/support/boot_properties_message_processor.cpp
|
anbox/support/boot_properties_message_processor.cpp
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
#include "anbox/network/published_socket_connector.h"
|
#include "anbox/network/published_socket_connector.h"
|
||||||
#include "anbox/network/qemu_pipe_connection_creator.h"
|
#include "anbox/network/qemu_pipe_connection_creator.h"
|
||||||
#include "anbox/graphics/gl_renderer_server.h"
|
#include "anbox/graphics/gl_renderer_server.h"
|
||||||
#include "anbox/input_channel.h"
|
#include "anbox/input/manager.h"
|
||||||
|
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
|
|
@ -67,9 +67,9 @@ anbox::cmds::Run::Run()
|
||||||
|
|
||||||
auto rt = Runtime::create();
|
auto rt = Runtime::create();
|
||||||
|
|
||||||
auto input_channel = std::make_shared<InputChannel>();
|
auto input_manager = std::make_shared<input::Manager>(rt);
|
||||||
|
|
||||||
auto renderer = std::make_shared<graphics::GLRendererServer>(input_channel);
|
auto renderer = std::make_shared<graphics::GLRendererServer>(input_manager);
|
||||||
renderer->start();
|
renderer->start();
|
||||||
|
|
||||||
// Socket which will be used by the qemud service inside the Android
|
// Socket which will be used by the qemud service inside the Android
|
||||||
|
|
@ -91,6 +91,8 @@ anbox::cmds::Run::Run()
|
||||||
spec.bind_paths.insert({qemud_connector->socket_file(), "/dev/qemud"});
|
spec.bind_paths.insert({qemud_connector->socket_file(), "/dev/qemud"});
|
||||||
spec.bind_paths.insert({qemu_pipe_connector->socket_file(), "/dev/qemu_pipe"});
|
spec.bind_paths.insert({qemu_pipe_connector->socket_file(), "/dev/qemu_pipe"});
|
||||||
|
|
||||||
|
input_manager->generate_mappings(spec.bind_paths);
|
||||||
|
|
||||||
spec.temporary_dirs.push_back("/data");
|
spec.temporary_dirs.push_back("/data");
|
||||||
spec.temporary_dirs.push_back("/cache");
|
spec.temporary_dirs.push_back("/cache");
|
||||||
spec.temporary_dirs.push_back("/storage");
|
spec.temporary_dirs.push_back("/storage");
|
||||||
|
|
@ -102,16 +104,6 @@ anbox::cmds::Run::Run()
|
||||||
// Required for shared memory allocations. TODO(morphis): Letting the guest
|
// Required for shared memory allocations. TODO(morphis): Letting the guest
|
||||||
// access should be ok but needs more investigation.
|
// access should be ok but needs more investigation.
|
||||||
spec.dev_bind_paths.push_back("/dev/ashmem");
|
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.
|
|
||||||
// FIXME(morphis): Need to reenable this once we have both sides prepared
|
|
||||||
// for an socket based approach.
|
|
||||||
// spec.dev_bind_paths.push_back({input_channel->dev_path()});
|
|
||||||
// Until then we forward just the host input device which needs to have
|
|
||||||
// proper permissions (insecure!!!) for this.
|
|
||||||
// $ sudo chmod 666 /dev/input/event7
|
|
||||||
spec.dev_bind_paths.push_back({"/dev/input/event7"});
|
|
||||||
|
|
||||||
auto container = Container::create(spec);
|
auto container = Container::create(spec);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
GLRendererServer::GLRendererServer(const std::shared_ptr<InputChannel> &input_channel) :
|
GLRendererServer::GLRendererServer(const std::shared_ptr<input::Manager> &input_manager) :
|
||||||
window_creator_(std::make_shared<MirNativeWindowCreator>(input_channel)) {
|
window_creator_(std::make_shared<MirNativeWindowCreator>(input_manager)) {
|
||||||
|
|
||||||
// Force the host EGL/GLES libraries as translator implementation
|
// Force the host EGL/GLES libraries as translator implementation
|
||||||
::setenv("ANDROID_EGL_LIB", "libEGL.so.1", 1);
|
::setenv("ANDROID_EGL_LIB", "libEGL.so.1", 1);
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,15 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
class InputChannel;
|
namespace input {
|
||||||
|
class Manager;
|
||||||
|
}
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
class MirNativeWindowCreator;
|
class MirNativeWindowCreator;
|
||||||
|
|
||||||
class GLRendererServer {
|
class GLRendererServer {
|
||||||
public:
|
public:
|
||||||
GLRendererServer(const std::shared_ptr<InputChannel> &input_channel);
|
GLRendererServer(const std::shared_ptr<input::Manager> &input_manager);
|
||||||
~GLRendererServer();
|
~GLRendererServer();
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
|
|
|
||||||
|
|
@ -18,18 +18,15 @@
|
||||||
#include "anbox/graphics/mir_native_window_creator.h"
|
#include "anbox/graphics/mir_native_window_creator.h"
|
||||||
#include "anbox/graphics/mir_display_connection.h"
|
#include "anbox/graphics/mir_display_connection.h"
|
||||||
#include "anbox/graphics/mir_window.h"
|
#include "anbox/graphics/mir_window.h"
|
||||||
#include "anbox/input_channel.h"
|
#include "anbox/input/manager.h"
|
||||||
|
|
||||||
#include <boost/throw_exception.hpp>
|
#include <boost/throw_exception.hpp>
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
MirNativeWindowCreator::MirNativeWindowCreator(const std::shared_ptr<InputChannel> &input_channel) :
|
MirNativeWindowCreator::MirNativeWindowCreator(const std::shared_ptr<input::Manager> &input_manager) :
|
||||||
input_channel_(input_channel),
|
input_manager_(input_manager),
|
||||||
display_connection_(std::make_shared<MirDisplayConnection>()) {
|
display_connection_(std::make_shared<MirDisplayConnection>()) {
|
||||||
|
|
||||||
input_channel_->setup(display_connection_->horizontal_resolution(),
|
|
||||||
display_connection_->vertical_resolution());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MirNativeWindowCreator::~MirNativeWindowCreator() {
|
MirNativeWindowCreator::~MirNativeWindowCreator() {
|
||||||
|
|
@ -44,7 +41,7 @@ EGLNativeWindowType MirNativeWindowCreator::create_window(int x, int y, int widt
|
||||||
if (windows_.size() > 0)
|
if (windows_.size() > 0)
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error("We currently only allow a single native window"));
|
BOOST_THROW_EXCEPTION(std::runtime_error("We currently only allow a single native window"));
|
||||||
|
|
||||||
auto window = std::make_shared<MirWindow>(display_connection_, input_channel_);
|
auto window = std::make_shared<MirWindow>(display_connection_, input_manager_);
|
||||||
windows_.insert({window->native_window(), window});
|
windows_.insert({window->native_window(), window});
|
||||||
|
|
||||||
return window->native_window();
|
return window->native_window();
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,9 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
class InputChannel;
|
namespace input {
|
||||||
|
class Manager;
|
||||||
|
}
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
|
|
||||||
class MirDisplayConnection;
|
class MirDisplayConnection;
|
||||||
|
|
@ -33,7 +34,7 @@ class MirWindow;
|
||||||
|
|
||||||
class MirNativeWindowCreator : public SubWindowHandler {
|
class MirNativeWindowCreator : public SubWindowHandler {
|
||||||
public:
|
public:
|
||||||
MirNativeWindowCreator(const std::shared_ptr<InputChannel> &input_channel);
|
MirNativeWindowCreator(const std::shared_ptr<input::Manager> &input_channel);
|
||||||
virtual ~MirNativeWindowCreator();
|
virtual ~MirNativeWindowCreator();
|
||||||
|
|
||||||
EGLNativeWindowType create_window(int x, int y, int width, int height) override;
|
EGLNativeWindowType create_window(int x, int y, int width, int height) override;
|
||||||
|
|
@ -42,7 +43,7 @@ public:
|
||||||
std::shared_ptr<MirDisplayConnection> display() const;
|
std::shared_ptr<MirDisplayConnection> display() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<InputChannel> input_channel_;
|
std::shared_ptr<input::Manager> input_manager_;
|
||||||
std::shared_ptr<MirDisplayConnection> display_connection_;
|
std::shared_ptr<MirDisplayConnection> display_connection_;
|
||||||
std::map<EGLNativeWindowType,std::shared_ptr<MirWindow>> windows_;
|
std::map<EGLNativeWindowType,std::shared_ptr<MirWindow>> windows_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,12 @@
|
||||||
#include "anbox/graphics/mir_window.h"
|
#include "anbox/graphics/mir_window.h"
|
||||||
#include "anbox/graphics/mir_display_connection.h"
|
#include "anbox/graphics/mir_display_connection.h"
|
||||||
#include "anbox/logger.h"
|
#include "anbox/logger.h"
|
||||||
#include "anbox/input_channel.h"
|
#include "anbox/input/manager.h"
|
||||||
|
#include "anbox/input/device.h"
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
MirWindow::MirWindow(const std::shared_ptr<MirDisplayConnection> &display, const std::shared_ptr<InputChannel> &input_channel) :
|
MirWindow::MirWindow(const std::shared_ptr<MirDisplayConnection> &display, const std::shared_ptr<input::Manager> &input_manager) :
|
||||||
input_channel_(input_channel),
|
|
||||||
native_window_(0),
|
native_window_(0),
|
||||||
surface_(nullptr) {
|
surface_(nullptr) {
|
||||||
|
|
||||||
|
|
@ -60,13 +60,119 @@ MirWindow::MirWindow(const std::shared_ptr<MirDisplayConnection> &display, const
|
||||||
auto surface_buffer_stream = mir_surface_get_buffer_stream(surface_);
|
auto surface_buffer_stream = mir_surface_get_buffer_stream(surface_);
|
||||||
native_window_ = reinterpret_cast<EGLNativeWindowType>(
|
native_window_ = reinterpret_cast<EGLNativeWindowType>(
|
||||||
mir_buffer_stream_get_egl_native_window(surface_buffer_stream));
|
mir_buffer_stream_get_egl_native_window(surface_buffer_stream));
|
||||||
|
|
||||||
|
// Create our touch panel input device
|
||||||
|
input_device_ = input_manager->create_device();
|
||||||
|
input_device_->set_name("mir-touchpanel");
|
||||||
|
input_device_->set_driver_version(1);
|
||||||
|
input_device_->set_input_id({ BUS_VIRTUAL, 1, 1, 1 });
|
||||||
|
input_device_->set_physical_location("none");
|
||||||
|
input_device_->set_abs_bit(ABS_MT_TRACKING_ID);
|
||||||
|
input_device_->set_abs_bit(ABS_MT_SLOT);
|
||||||
|
input_device_->set_abs_bit(ABS_MT_POSITION_X);
|
||||||
|
input_device_->set_abs_bit(ABS_MT_POSITION_Y);
|
||||||
|
input_device_->set_prop_bit(INPUT_PROP_DIRECT);
|
||||||
|
input_device_->set_abs_min(ABS_MT_POSITION_X, 0);
|
||||||
|
input_device_->set_abs_max(ABS_MT_POSITION_X, display->horizontal_resolution());
|
||||||
|
input_device_->set_abs_min(ABS_MT_POSITION_Y, 0);
|
||||||
|
input_device_->set_abs_max(ABS_MT_POSITION_Y, display->vertical_resolution());
|
||||||
|
input_device_->set_abs_max(ABS_MT_SLOT, 10);
|
||||||
|
input_device_->set_abs_max(ABS_MT_TRACKING_ID, 255);
|
||||||
|
input_device_->set_key_bit(BTN_TOUCH);
|
||||||
|
input_device_->set_key_bit(BTN_TOOL_FINGER);
|
||||||
}
|
}
|
||||||
|
|
||||||
MirWindow::~MirWindow() {
|
MirWindow::~MirWindow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::vector<int> slot_to_fingerId;
|
||||||
|
|
||||||
|
int find_slot(int id)
|
||||||
|
{
|
||||||
|
auto iter = std::find(slot_to_fingerId.begin(), slot_to_fingerId.end(), id);
|
||||||
|
if (iter != slot_to_fingerId.end())
|
||||||
|
return std::distance(slot_to_fingerId.begin(), iter);
|
||||||
|
|
||||||
|
std::vector<int>::size_type i;
|
||||||
|
for(i = 0;i < slot_to_fingerId.size();i++) {
|
||||||
|
if (slot_to_fingerId[i] == -1) {
|
||||||
|
slot_to_fingerId[i] = id;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
slot_to_fingerId.resize(slot_to_fingerId.size()+1);
|
||||||
|
slot_to_fingerId[slot_to_fingerId.size()-1] = id;
|
||||||
|
|
||||||
|
return slot_to_fingerId.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase_slot(int id)
|
||||||
|
{
|
||||||
|
auto it = find(slot_to_fingerId.begin(), slot_to_fingerId.end(), id);
|
||||||
|
|
||||||
|
if (it != slot_to_fingerId.end()) {
|
||||||
|
auto index = std::distance(slot_to_fingerId.begin(), it);
|
||||||
|
slot_to_fingerId[index] = -1;
|
||||||
|
if (index == slot_to_fingerId.size()-1) {
|
||||||
|
while (slot_to_fingerId[index] == -1) {
|
||||||
|
slot_to_fingerId.resize(index);
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MirWindow::handle_touch_event(MirTouchEvent const* touch_event) {
|
void MirWindow::handle_touch_event(MirTouchEvent const* touch_event) {
|
||||||
const auto action = mir_touch_event_action(touch_event, 0);
|
const auto point_count = mir_touch_event_point_count(touch_event);
|
||||||
|
|
||||||
|
for (int n = 0; n < point_count; n++) {
|
||||||
|
const auto id = mir_touch_event_id(touch_event, n);
|
||||||
|
const auto slot = find_slot(id);
|
||||||
|
const auto x = mir_touch_event_axis_value(touch_event, n, mir_touch_axis_x);
|
||||||
|
const auto y = mir_touch_event_axis_value(touch_event, n, mir_touch_axis_y);
|
||||||
|
const auto pressure = mir_touch_event_axis_value(touch_event, n, mir_touch_axis_pressure);
|
||||||
|
const auto touch_major = mir_touch_event_axis_value(touch_event, n, mir_touch_axis_touch_major);
|
||||||
|
const auto touch_minor = mir_touch_event_axis_value(touch_event, n, mir_touch_axis_touch_minor);
|
||||||
|
|
||||||
|
DEBUG("Event: id %d, slot %d, x %f, y %f, pressure %f",
|
||||||
|
id, slot, x, y, pressure);
|
||||||
|
|
||||||
|
std::vector<input::Device::Event> events;
|
||||||
|
|
||||||
|
switch (mir_touch_event_action(touch_event, n)) {
|
||||||
|
case mir_touch_action_up:
|
||||||
|
events.push_back({ EV_ABS, ABS_MT_SLOT, slot });
|
||||||
|
events.push_back({ EV_ABS, ABS_MT_TRACKING_ID, -1 });
|
||||||
|
events.push_back({ EV_KEY, BTN_TOUCH, 0 });
|
||||||
|
events.push_back({ EV_KEY, BTN_TOOL_FINGER, 0 });
|
||||||
|
events.push_back({ EV_SYN, SYN_REPORT, 0 });
|
||||||
|
erase_slot(id);
|
||||||
|
break;
|
||||||
|
case mir_touch_action_down:
|
||||||
|
events.push_back({ EV_ABS, ABS_MT_SLOT, slot });
|
||||||
|
events.push_back({ EV_ABS, ABS_MT_TRACKING_ID, id });
|
||||||
|
events.push_back({ EV_ABS, ABS_MT_POSITION_X, static_cast<std::int32_t>(x) });
|
||||||
|
events.push_back({ EV_ABS, ABS_MT_POSITION_Y, static_cast<std::int32_t>(y) });
|
||||||
|
events.push_back({ EV_ABS, ABS_MT_TOUCH_MAJOR, static_cast<std::int32_t>(touch_major) });
|
||||||
|
events.push_back({ EV_ABS, ABS_MT_TOUCH_MINOR, static_cast<std::int32_t>(touch_minor) });
|
||||||
|
events.push_back({ EV_SYN, SYN_REPORT, 0 });
|
||||||
|
break;
|
||||||
|
case mir_touch_action_change:
|
||||||
|
events.push_back({ EV_ABS, ABS_MT_SLOT, slot });
|
||||||
|
events.push_back({ EV_ABS, ABS_MT_TRACKING_ID, id });
|
||||||
|
events.push_back({ EV_KEY, BTN_TOUCH, 1 });
|
||||||
|
events.push_back({ EV_KEY, BTN_TOOL_FINGER, 1 });
|
||||||
|
events.push_back({ EV_ABS, ABS_MT_POSITION_X, static_cast<std::int32_t>(x) });
|
||||||
|
events.push_back({ EV_ABS, ABS_MT_POSITION_Y, static_cast<std::int32_t>(y) });
|
||||||
|
events.push_back({ EV_ABS, ABS_MT_TOUCH_MAJOR, static_cast<std::int32_t>(touch_major) });
|
||||||
|
events.push_back({ EV_ABS, ABS_MT_TOUCH_MINOR, static_cast<std::int32_t>(touch_minor) });
|
||||||
|
events.push_back({ EV_SYN, SYN_REPORT, 0 });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
input_device_->send_events(events);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MirWindow::handle_input_event(MirInputEvent const* input_event) {
|
void MirWindow::handle_input_event(MirInputEvent const* input_event) {
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,16 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
class InputChannel;
|
namespace input {
|
||||||
|
class Manager;
|
||||||
|
class Device;
|
||||||
|
}
|
||||||
namespace graphics {
|
namespace graphics {
|
||||||
class MirDisplayConnection;
|
class MirDisplayConnection;
|
||||||
|
|
||||||
class MirWindow {
|
class MirWindow {
|
||||||
public:
|
public:
|
||||||
MirWindow(const std::shared_ptr<MirDisplayConnection> &display, const std::shared_ptr<InputChannel> &input_channel);
|
MirWindow(const std::shared_ptr<MirDisplayConnection> &display, const std::shared_ptr<input::Manager> &input_manager);
|
||||||
~MirWindow();
|
~MirWindow();
|
||||||
|
|
||||||
EGLNativeWindowType native_window() const;
|
EGLNativeWindowType native_window() const;
|
||||||
|
|
@ -45,7 +47,7 @@ private:
|
||||||
void handle_input_event(MirInputEvent const* input_event);
|
void handle_input_event(MirInputEvent const* input_event);
|
||||||
void handle_touch_event(MirTouchEvent const* touch_event);
|
void handle_touch_event(MirTouchEvent const* touch_event);
|
||||||
|
|
||||||
std::shared_ptr<InputChannel> input_channel_;
|
std::shared_ptr<input::Device> input_device_;
|
||||||
EGLNativeWindowType native_window_;
|
EGLNativeWindowType native_window_;
|
||||||
MirSurface *surface_;
|
MirSurface *surface_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ void OpenGlesMessageProcessor::connect_and_attach(const std::string &socket_path
|
||||||
|
|
||||||
messenger_ = std::make_shared<network::SocketMessenger>(socket);
|
messenger_ = std::make_shared<network::SocketMessenger>(socket);
|
||||||
renderer_ = std::make_shared<network::SocketConnection>(
|
renderer_ = std::make_shared<network::SocketConnection>(
|
||||||
|
messenger_,
|
||||||
messenger_,
|
messenger_,
|
||||||
0,
|
0,
|
||||||
std::make_shared<network::Connections<network::SocketConnection>>(),
|
std::make_shared<network::Connections<network::SocketConnection>>(),
|
||||||
|
|
|
||||||
173
src/anbox/input/device.cpp
Normal file
173
src/anbox/input/device.cpp
Normal file
|
|
@ -0,0 +1,173 @@
|
||||||
|
/*
|
||||||
|
* 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/device.h"
|
||||||
|
#include "anbox/network/delegate_connection_creator.h"
|
||||||
|
#include "anbox/network/delegate_message_processor.h"
|
||||||
|
#include "anbox/network/socket_messenger.h"
|
||||||
|
#include "anbox/support/null_message_processor.h"
|
||||||
|
#include "anbox/logger.h"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
namespace anbox {
|
||||||
|
namespace input {
|
||||||
|
std::shared_ptr<Device> Device::create(const std::string &path, const std::shared_ptr<Runtime> &runtime) {
|
||||||
|
auto sp = std::make_shared<Device>();
|
||||||
|
|
||||||
|
auto delegate_connector = std::make_shared<network::DelegateConnectionCreator>(
|
||||||
|
[sp](std::shared_ptr<boost::asio::local::stream_protocol::socket> const &socket) {
|
||||||
|
sp->new_client(socket);
|
||||||
|
});
|
||||||
|
|
||||||
|
sp->connector_ = std::make_shared<network::PublishedSocketConnector>(path, runtime, delegate_connector);
|
||||||
|
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
Device::Device() :
|
||||||
|
next_connection_id_(0),
|
||||||
|
connections_(std::make_shared<network::Connections<network::SocketConnection>>()) {
|
||||||
|
::memset(&info_, 0, sizeof(info_));
|
||||||
|
}
|
||||||
|
|
||||||
|
Device::~Device() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::send_events(const std::vector<Event> &events) {
|
||||||
|
struct CompatEvent {
|
||||||
|
// NOTE: A bit dirty but as we're running currently a 64 bit container
|
||||||
|
// struct input_event has a different size. We rebuild the struct here
|
||||||
|
// to reach the correct size.
|
||||||
|
std::uint64_t sec;
|
||||||
|
std::uint64_t usec;
|
||||||
|
std::uint16_t type;
|
||||||
|
std::uint16_t code;
|
||||||
|
std::uint32_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct timespec spec;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &spec);
|
||||||
|
|
||||||
|
auto data = new CompatEvent[events.size()];
|
||||||
|
int n = 0;
|
||||||
|
for (const auto &event : events) {
|
||||||
|
data[n].sec = spec.tv_sec;
|
||||||
|
data[n].usec = spec.tv_nsec / 1000;
|
||||||
|
data[n].type = event.type;
|
||||||
|
data[n].code = event.code;
|
||||||
|
data[n].value = event.value;
|
||||||
|
|
||||||
|
DEBUG("Event: time %lld, type %d, code %d, value %d",
|
||||||
|
data[n].sec * 1000000000LL + data[n].usec * 1000LL,
|
||||||
|
event.type, event.code, event.value);
|
||||||
|
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto n = 0; n < connections_->size(); n++) {
|
||||||
|
connections_->at(n)->send(reinterpret_cast<const char*>(data),
|
||||||
|
events.size() * sizeof(struct CompatEvent));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_name(const std::string &name) {
|
||||||
|
snprintf(info_.name, 80, "%s", name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_driver_version(const int &version) {
|
||||||
|
info_.driver_version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_input_id(const struct input_id &id) {
|
||||||
|
info_.id.bustype = id.bustype;
|
||||||
|
info_.id.product = id.product;
|
||||||
|
info_.id.vendor = id.vendor;
|
||||||
|
info_.id.version = id.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_physical_location(const std::string &physical_location) {
|
||||||
|
snprintf(info_.physical_location, 80, "%s", physical_location.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_key_bit(const std::uint8_t &bit) {
|
||||||
|
set_bit(info_.key_bitmask, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_abs_bit(const std::uint8_t &bit) {
|
||||||
|
set_bit(info_.abs_bitmask, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_rel_bit(const std::uint8_t &bit) {
|
||||||
|
set_bit(info_.rel_bitmask, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_sw_bit(const std::uint8_t &bit) {
|
||||||
|
set_bit(info_.sw_bitmask, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_led_bit(const std::uint8_t &bit) {
|
||||||
|
set_bit(info_.led_bitmask, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_ff_bit(const std::uint8_t &bit) {
|
||||||
|
set_bit(info_.ff_bitmask, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_prop_bit(const std::uint8_t &bit) {
|
||||||
|
set_bit(info_.prop_bitmask, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_abs_min(const std::uint8_t &bit, const std::uint32_t &value) {
|
||||||
|
info_.abs_min[bit] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_abs_max(const std::uint8_t &bit, const std::uint32_t &value) {
|
||||||
|
info_.abs_max[bit] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_bit(std::uint8_t *array, const std::uint8_t &bit) {
|
||||||
|
array[bit/8] |= (1 << (bit % 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::set_unique_id(const std::string &unique_id) {
|
||||||
|
snprintf(info_.unique_id, 80, "%s", unique_id.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Device::socket_path() const {
|
||||||
|
return connector_->socket_file();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Device::next_id()
|
||||||
|
{
|
||||||
|
return next_connection_id_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Device::new_client(std::shared_ptr<boost::asio::local::stream_protocol::socket> const &socket) {
|
||||||
|
auto const messenger = std::make_shared<network::SocketMessenger>(socket);
|
||||||
|
auto const& connection = std::make_shared<network::SocketConnection>(
|
||||||
|
messenger, messenger, next_id(), connections_,
|
||||||
|
std::make_shared<support::NullMessageProcessor>());
|
||||||
|
|
||||||
|
connections_->add(connection);
|
||||||
|
|
||||||
|
// Send all necessary information about our device so that the remote
|
||||||
|
// side can properly configure itself for this input device
|
||||||
|
connection->send(reinterpret_cast<char const*>(&info_), sizeof(info_));
|
||||||
|
}
|
||||||
|
} // namespace input
|
||||||
|
} // namespace anbox
|
||||||
99
src/anbox/input/device.h
Normal file
99
src/anbox/input/device.h
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* 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_DEVICE_H_
|
||||||
|
#define ANBOX_INPUT_DEVICE_H_
|
||||||
|
|
||||||
|
#include "anbox/network/published_socket_connector.h"
|
||||||
|
#include "anbox/network/connections.h"
|
||||||
|
#include "anbox/network/socket_connection.h"
|
||||||
|
#include "anbox/runtime.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <linux/input.h>
|
||||||
|
|
||||||
|
namespace anbox {
|
||||||
|
namespace input {
|
||||||
|
class Device : public std::enable_shared_from_this<Device> {
|
||||||
|
public:
|
||||||
|
static std::shared_ptr<Device> create(const std::string &path, const std::shared_ptr<Runtime> &runtime);
|
||||||
|
|
||||||
|
Device();
|
||||||
|
~Device();
|
||||||
|
|
||||||
|
struct Event {
|
||||||
|
std::uint16_t type;
|
||||||
|
std::uint16_t code;
|
||||||
|
std::int32_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
void send_events(const std::vector<Event> &events);
|
||||||
|
void send_event(const std::uint16_t &code, const std::uint16_t &event, const std::int32_t &value);
|
||||||
|
|
||||||
|
void set_name(const std::string &name);
|
||||||
|
void set_driver_version(const int &version);
|
||||||
|
void set_input_id(const struct input_id &id);
|
||||||
|
void set_physical_location(const std::string &physical_location);
|
||||||
|
void set_unique_id(const std::string &unique_id);
|
||||||
|
void set_key_bit(const std::uint8_t &bit);
|
||||||
|
void set_abs_bit(const std::uint8_t &bit);
|
||||||
|
void set_rel_bit(const std::uint8_t &bit);
|
||||||
|
void set_sw_bit(const std::uint8_t &bit);
|
||||||
|
void set_led_bit(const std::uint8_t &bit);
|
||||||
|
void set_ff_bit(const std::uint8_t &bit);
|
||||||
|
void set_prop_bit(const std::uint8_t &bit);
|
||||||
|
|
||||||
|
void set_abs_min(const std::uint8_t &bit, const std::uint32_t &value);
|
||||||
|
void set_abs_max(const std::uint8_t &bit, const std::uint32_t &value);
|
||||||
|
|
||||||
|
std::string socket_path() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int next_id();
|
||||||
|
void new_client(std::shared_ptr<boost::asio::local::stream_protocol::socket> const &socket);
|
||||||
|
|
||||||
|
// NOTE: If you modify this struct you have to modify the version on
|
||||||
|
// the Android side too. See frameworks/native/services/inputflinger/EventHub.cpp
|
||||||
|
struct Info {
|
||||||
|
char name[80];
|
||||||
|
int driver_version;
|
||||||
|
struct input_id id;
|
||||||
|
char physical_location[80];
|
||||||
|
char unique_id[80];
|
||||||
|
std::uint8_t key_bitmask[(KEY_MAX + 1) / 8];
|
||||||
|
std::uint8_t abs_bitmask[(ABS_MAX + 1) / 8];
|
||||||
|
std::uint8_t rel_bitmask[(REL_MAX + 1) / 8];
|
||||||
|
std::uint8_t sw_bitmask[(SW_MAX + 1) / 8];
|
||||||
|
std::uint8_t led_bitmask[(LED_MAX + 1) / 8];
|
||||||
|
std::uint8_t ff_bitmask[(FF_MAX + 1) / 8];
|
||||||
|
std::uint8_t prop_bitmask[(INPUT_PROP_MAX + 1) / 8];
|
||||||
|
std::uint32_t abs_max[ABS_CNT];
|
||||||
|
std::uint32_t abs_min[ABS_CNT];
|
||||||
|
};
|
||||||
|
|
||||||
|
void set_bit(std::uint8_t *array, const std::uint8_t &bit);
|
||||||
|
|
||||||
|
std::shared_ptr<network::PublishedSocketConnector> connector_;
|
||||||
|
std::atomic<int> next_connection_id_;
|
||||||
|
std::shared_ptr<network::Connections<network::SocketConnection>> const connections_;
|
||||||
|
Info info_;
|
||||||
|
};
|
||||||
|
} // namespace input
|
||||||
|
} // namespace anbox
|
||||||
|
|
||||||
|
#endif
|
||||||
61
src/anbox/input/manager.cpp
Normal file
61
src/anbox/input/manager.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/input/manager.h"
|
||||||
|
#include "anbox/input/device.h"
|
||||||
|
#include "anbox/runtime.h"
|
||||||
|
#include "anbox/config.h"
|
||||||
|
|
||||||
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
|
namespace anbox {
|
||||||
|
namespace input {
|
||||||
|
Manager::Manager(const std::shared_ptr<Runtime> &runtime) :
|
||||||
|
runtime_(runtime) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Manager::~Manager() {
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Device> Manager::create_device() {
|
||||||
|
const auto id = next_id();
|
||||||
|
const auto path = build_device_path(id);
|
||||||
|
auto device = Device::create(path, runtime_);
|
||||||
|
devices_.insert({id, device});
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::generate_mappings(std::map<std::string,std::string> &target) {
|
||||||
|
for (const auto &iter : devices_) {
|
||||||
|
target.insert({
|
||||||
|
iter.second->socket_path(),
|
||||||
|
(boost::format("/dev/input/event%1%") % iter.first).str(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t Manager::next_id() {
|
||||||
|
static std::uint32_t next_id = 0;
|
||||||
|
return next_id++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Manager::build_device_path(const std::uint32_t &id) {
|
||||||
|
return (boost::format("%1%/input_device_%2%") % config::data_path() % id).str();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace input
|
||||||
|
} // namespace anbox
|
||||||
47
src/anbox/input/manager.h
Normal file
47
src/anbox/input/manager.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_MANAGER_H_
|
||||||
|
#define ANBOX_INPUT_MANAGER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace anbox {
|
||||||
|
class Runtime;
|
||||||
|
namespace input {
|
||||||
|
class Device;
|
||||||
|
class Manager {
|
||||||
|
public:
|
||||||
|
Manager(const std::shared_ptr<Runtime> &runtime);
|
||||||
|
~Manager();
|
||||||
|
|
||||||
|
std::shared_ptr<Device> create_device();
|
||||||
|
|
||||||
|
void generate_mappings(std::map<std::string,std::string> &target);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::uint32_t next_id();
|
||||||
|
std::string build_device_path(const std::uint32_t &id);
|
||||||
|
|
||||||
|
std::shared_ptr<Runtime> runtime_;
|
||||||
|
std::map<std::uint32_t,std::shared_ptr<Device>> devices_;
|
||||||
|
};
|
||||||
|
} // namespace input
|
||||||
|
} // namespace anbox
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -35,7 +35,7 @@ public:
|
||||||
void add(std::shared_ptr<Connection> const& connection)
|
void add(std::shared_ptr<Connection> const& connection)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(mutex);
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
connections[connection->id()] = connection;
|
connections.insert({connection->id(), connection});
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(int id)
|
void remove(int id)
|
||||||
|
|
@ -56,6 +56,15 @@ public:
|
||||||
connections.clear();
|
connections.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t size()
|
||||||
|
{
|
||||||
|
return connections.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Connection> at(size_t n)
|
||||||
|
{
|
||||||
|
return connections.at(n);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Connections(Connections const&) = delete;
|
Connections(Connections const&) = delete;
|
||||||
|
|
|
||||||
47
src/anbox/network/delegate_connection_creator.h
Normal file
47
src/anbox/network/delegate_connection_creator.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_NETWORK_DELEGATE_CONNECTION_CREATOR_H_
|
||||||
|
#define ANBOX_NETWORK_DELEGATE_CONNECTION_CREATOR_H_
|
||||||
|
|
||||||
|
#include "anbox/network/connection_creator.h"
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace anbox {
|
||||||
|
namespace network {
|
||||||
|
class DelegateConnectionCreator : public ConnectionCreator {
|
||||||
|
public:
|
||||||
|
DelegateConnectionCreator(std::function<void(std::shared_ptr<boost::asio::local::stream_protocol::socket> const&)> delegate) :
|
||||||
|
delegate_(delegate) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_connection_for(
|
||||||
|
std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket) override {
|
||||||
|
if (delegate_)
|
||||||
|
delegate_(socket);
|
||||||
|
else
|
||||||
|
socket->close();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::function<void(std::shared_ptr<boost::asio::local::stream_protocol::socket> const&)> delegate_;
|
||||||
|
};
|
||||||
|
} // namespace network
|
||||||
|
} // namespace anbox
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -52,7 +52,8 @@ void QemuPipeConnectionCreator::create_connection_for(
|
||||||
if (!processor)
|
if (!processor)
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error("Unhandled client type"));
|
BOOST_THROW_EXCEPTION(std::runtime_error("Unhandled client type"));
|
||||||
|
|
||||||
auto const& connection = std::make_shared<SocketConnection>(messenger, next_id(), connections_, processor);
|
auto const& connection = std::make_shared<SocketConnection>(
|
||||||
|
messenger, messenger, next_id(), connections_, processor);
|
||||||
connections_->add(connection);
|
connections_->add(connection);
|
||||||
connection->read_next_message();
|
connection->read_next_message();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,10 +37,12 @@ namespace anbox {
|
||||||
namespace network {
|
namespace network {
|
||||||
SocketConnection::SocketConnection(
|
SocketConnection::SocketConnection(
|
||||||
std::shared_ptr<MessageReceiver> const& message_receiver,
|
std::shared_ptr<MessageReceiver> const& message_receiver,
|
||||||
|
std::shared_ptr<MessageSender> const& message_sender,
|
||||||
int id_,
|
int id_,
|
||||||
std::shared_ptr<Connections<SocketConnection>> const& connections,
|
std::shared_ptr<Connections<SocketConnection>> const& connections,
|
||||||
std::shared_ptr<MessageProcessor> const& processor)
|
std::shared_ptr<MessageProcessor> const& processor)
|
||||||
: message_receiver_(message_receiver),
|
: message_receiver_(message_receiver),
|
||||||
|
message_sender_(message_sender),
|
||||||
id_(id_),
|
id_(id_),
|
||||||
connections_(connections),
|
connections_(connections),
|
||||||
processor_(processor)
|
processor_(processor)
|
||||||
|
|
@ -51,6 +53,10 @@ SocketConnection::~SocketConnection() noexcept
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SocketConnection::send(char const* data, size_t length) {
|
||||||
|
message_sender_->send(data, length);
|
||||||
|
}
|
||||||
|
|
||||||
void SocketConnection::read_next_message()
|
void SocketConnection::read_next_message()
|
||||||
{
|
{
|
||||||
auto callback = std::bind(&SocketConnection::on_read_size,
|
auto callback = std::bind(&SocketConnection::on_read_size,
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include "anbox/network/connections.h"
|
#include "anbox/network/connections.h"
|
||||||
#include "anbox/network/message_receiver.h"
|
#include "anbox/network/message_receiver.h"
|
||||||
|
#include "anbox/network/message_sender.h"
|
||||||
#include "anbox/network/message_processor.h"
|
#include "anbox/network/message_processor.h"
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
|
@ -34,6 +35,7 @@ class SocketConnection
|
||||||
public:
|
public:
|
||||||
SocketConnection(
|
SocketConnection(
|
||||||
std::shared_ptr<MessageReceiver> const& message_receiver,
|
std::shared_ptr<MessageReceiver> const& message_receiver,
|
||||||
|
std::shared_ptr<MessageSender> const& message_sender,
|
||||||
int id,
|
int id,
|
||||||
std::shared_ptr<Connections<SocketConnection>> const& connections,
|
std::shared_ptr<Connections<SocketConnection>> const& connections,
|
||||||
std::shared_ptr<MessageProcessor> const& processor);
|
std::shared_ptr<MessageProcessor> const& processor);
|
||||||
|
|
@ -42,6 +44,7 @@ public:
|
||||||
|
|
||||||
int id() const { return id_; }
|
int id() const { return id_; }
|
||||||
|
|
||||||
|
void send(char const* data, size_t length);
|
||||||
void read_next_message();
|
void read_next_message();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -49,6 +52,7 @@ private:
|
||||||
void on_read_size(const boost::system::error_code& ec, std::size_t bytes_read);
|
void on_read_size(const boost::system::error_code& ec, std::size_t bytes_read);
|
||||||
|
|
||||||
std::shared_ptr<MessageReceiver> const message_receiver_;
|
std::shared_ptr<MessageReceiver> const message_receiver_;
|
||||||
|
std::shared_ptr<MessageSender> const message_sender_;
|
||||||
int const id_;
|
int const id_;
|
||||||
std::shared_ptr<Connections<SocketConnection>> const connections_;
|
std::shared_ptr<Connections<SocketConnection>> const connections_;
|
||||||
std::shared_ptr<MessageProcessor> const processor_;
|
std::shared_ptr<MessageProcessor> const processor_;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue