Merge branch 'master' of https://github.com/anbox/anbox
This commit is contained in:
commit
ec926d13ae
112 changed files with 2167 additions and 525 deletions
15
.github/ISSUE_TEMPLATE.md
vendored
15
.github/ISSUE_TEMPLATE.md
vendored
|
|
@ -1,15 +1,16 @@
|
|||
Make sure you are running the latest version of Anbox before reporting an issue.
|
||||
|
||||
Please also check that no similar bug is already reported. Have a look on the
|
||||
list of open bugs at https://github.com/anbox/anbox/issues
|
||||
Please also check that no similar bug is already reported. Have a look on the list of open bugs at https://github.com/anbox/anbox/issues
|
||||
|
||||
**Anbox release (`anbox version`) and system info (`anbox system-info`):**
|
||||
** Please paste the result of `anbox system-info` below:**
|
||||
```
|
||||
[please paste printout of `anbox system-info` here]
|
||||
```
|
||||
|
||||
**Please describe your problem:**
|
||||
|
||||
|
||||
**Description of the problem:**
|
||||
|
||||
|
||||
**Expected:**
|
||||
**What were you expecting?:**
|
||||
|
||||
|
||||
**Additional info:**
|
||||
|
|
|
|||
|
|
@ -64,9 +64,11 @@ find_package(GLESv2 REQUIRED)
|
|||
find_package(Protobuf REQUIRED)
|
||||
|
||||
pkg_check_modules(SDL2 sdl2 REQUIRED)
|
||||
pkg_check_modules(SDL2_IMAGE SDL2_image REQUIRED)
|
||||
pkg_check_modules(DBUS_CPP dbus-cpp REQUIRED)
|
||||
pkg_check_modules(DBUS dbus-1 REQUIRED)
|
||||
pkg_check_modules(LXC lxc REQUIRED)
|
||||
pkg_check_modules(PROPERTIES_CPP properties-cpp REQUIRED)
|
||||
pkg_check_modules(MIRCLIENT mirclient)
|
||||
if (MIRCLIENT_FOUND)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMIR_SUPPORT")
|
||||
|
|
@ -94,6 +96,16 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fPIC")
|
|||
set(ANBOX_TRANSLATOR_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/anbox/translators)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTRANSLATOR_INSTALL_DIR=\\\"${CMAKE_INSTALL_PREFIX}/${ANBOX_TRANSLATOR_INSTALL_DIR}\\\"")
|
||||
|
||||
if (NOT ANBOX_VERSION)
|
||||
exec_program("git" ${CMAKE_SOURCE_DIR} ARGS "rev-parse --short HEAD" OUTPUT_VARIABLE GIT_COMMIT_HASH)
|
||||
set(ANBOX_VERSION "local-${GIT_COMMIT_HASH}")
|
||||
endif()
|
||||
if (ANBOX_VERSION_SUFFIX)
|
||||
set(ANBOX_VERSION "${ANBOX_VERSION}-${ANBOX_VERSION_SUFFIX}")
|
||||
endif()
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/anbox/build/version.h.in
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/anbox/build/version.h)
|
||||
|
||||
add_subdirectory(external)
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(tests)
|
||||
|
|
@ -103,3 +115,6 @@ if (NOT "${HOST_CMAKE_C_COMPILER}" STREQUAL "")
|
|||
message(STATUS "Host C compiler: ${HOST_CMAKE_C_COMPILER}")
|
||||
message(STATUS "Host C compiler: ${HOST_CMAKE_CXX_COMPILER}")
|
||||
endif()
|
||||
|
||||
install(FILES data/ui/loading-screen.png DESTINATION share/anbox/ui)
|
||||
|
||||
|
|
|
|||
30
README.md
30
README.md
|
|
@ -1,18 +1,23 @@
|
|||
[](https://build.snapcraft.io/user/anbox/anbox)
|
||||
[](https://travis-ci.org/anbox/anbox)
|
||||
|
||||
# Anbox
|
||||
|
||||
Anbox is container based approach to boot a full Android system on a
|
||||
regular GNU Linux system like Ubuntu.
|
||||
Anbox is a container-based approach to boot a full Android system on a
|
||||
regular GNU/Linux system like Ubuntu. In other words: Anbox will let
|
||||
you run Android on your Linux system without the slowness of
|
||||
virtualization.
|
||||
|
||||
## Overview
|
||||
|
||||
Anbox uses Linux namespaces (user, pid, uts, net, mount, ipc) to run a
|
||||
full Android system in a container and provide Android applications on
|
||||
any GNU Linux based platform.
|
||||
any GNU/Linux-based platform.
|
||||
|
||||
The Android inside the container has no direct access to any hardware.
|
||||
All hardware access is going through the anbox daemon on the host. We're
|
||||
reusing what Android implemented within the QEMU based emulator for Open
|
||||
GL ES accelerated rendering. The Android system inside the container uses
|
||||
reusing what Android implemented within the QEMU-based emulator for OpenGL
|
||||
ES accelerated rendering. The Android system inside the container uses
|
||||
different pipes to communicate with the host system and sends all hardware
|
||||
access commands through these.
|
||||
|
||||
|
|
@ -128,8 +133,8 @@ $ sudo apt install build-essential cmake cmake-data debhelper dbus google-mock \
|
|||
libboost-program-options-dev libboost-system-dev libboost-test-dev \
|
||||
libboost-thread-dev libcap-dev libdbus-1-dev libdbus-cpp-dev libegl1-mesa-dev \
|
||||
libgles2-mesa-dev libglib2.0-dev libglm-dev libgtest-dev liblxc1 \
|
||||
libproperties-cpp-dev libprotobuf-dev libsdl2-dev lxc-dev pkg-config \
|
||||
protobuf-compiler
|
||||
libproperties-cpp-dev libprotobuf-dev libsdl2-dev libsdl2-image-dev lxc-dev \
|
||||
pkg-config protobuf-compiler
|
||||
```
|
||||
|
||||
Afterwards you can build Anbox with
|
||||
|
|
@ -172,14 +177,11 @@ Running Anbox from a local build requires a few more things you need to know
|
|||
about. Please have a look at the ["Runtime Setup"](docs/runtime-setup.md)
|
||||
documentation.
|
||||
|
||||
An alias will save typing later.
|
||||
```
|
||||
$ alias android='anbox launch --package=org.anbox.appmgr --component=org.anbox.appmgr.AppViewActivity'
|
||||
$ alias android >> ~/.bashrc
|
||||
$ android
|
||||
$ anbox launch --package=org.anbox.appmgr --component=org.anbox.appmgr.AppViewActivity'
|
||||
```
|
||||
|
||||
## documentation
|
||||
## Documentation
|
||||
|
||||
You will find additional documentation for Anbox in the *docs* subdirectory
|
||||
of the project source.
|
||||
|
|
@ -196,7 +198,7 @@ If you have found an issue with Anbox, please [file a bug](https://github.com/an
|
|||
## Get in Touch
|
||||
|
||||
If you want to get in contact with the developers please feel free to join the
|
||||
*#anbox* IRC channel on [FreeNode](https://freenode.net/).
|
||||
*#anbox* IRC channel on [Freenode](https://freenode.net/).
|
||||
|
||||
## Copyright and Licensing
|
||||
|
||||
|
|
@ -204,5 +206,5 @@ Anbox reuses code from other projects like the Android QEMU emulator. These
|
|||
projects are available in the external/ subdirectory with the licensing terms
|
||||
included.
|
||||
|
||||
The anbox source itself, if not stated differently in the relevant source files,
|
||||
The Anbox source itself, if not stated differently in the relevant source files,
|
||||
is licensed under the terms of the GPLv3 license.
|
||||
|
|
|
|||
92
cmake/FindGMock.cmake
Normal file
92
cmake/FindGMock.cmake
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
# Copyright (C) 2014 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 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 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/>.
|
||||
|
||||
# Build with system gmock and embedded gtest
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# find_package(GMock)
|
||||
#
|
||||
# ...
|
||||
#
|
||||
# target_link_libraries(
|
||||
# my-target
|
||||
# ${GTEST_BOTH_LIBRARIES}
|
||||
# )
|
||||
#
|
||||
# NOTE: Due to the way this package finder is implemented, do not attempt
|
||||
# to find the GMock package more than once.
|
||||
|
||||
find_package(Threads)
|
||||
|
||||
if (EXISTS "/usr/src/googletest")
|
||||
# As of version 1.8.0
|
||||
set(GMOCK_SOURCE_DIR "/usr/src/googletest/googlemock" CACHE PATH "gmock source directory")
|
||||
set(GMOCK_INCLUDE_DIRS "${GMOCK_SOURCE_DIR}/include" CACHE PATH "gmock source include directory")
|
||||
set(GTEST_INCLUDE_DIRS "/usr/src/googletest/googletest/include" CACHE PATH "gtest source include directory")
|
||||
else()
|
||||
set(GMOCK_SOURCE_DIR "/usr/src/gmock" CACHE PATH "gmock source directory")
|
||||
set(GMOCK_INCLUDE_DIRS "/usr/include" CACHE PATH "gmock source include directory")
|
||||
set(GTEST_INCLUDE_DIRS "/usr/include" CACHE PATH "gtest source include directory")
|
||||
endif()
|
||||
|
||||
# We add -g so we get debug info for the gtest stack frames with gdb.
|
||||
# The warnings are suppressed so we get a noise-free build for gtest and gmock if the caller
|
||||
# has these warnings enabled.
|
||||
set(findgmock_cxx_flags "${CMAKE_CXX_FLAGS} -g -Wno-old-style-cast -Wno-missing-field-initializers -Wno-ctor-dtor-privacy -Wno-switch-default")
|
||||
|
||||
set(findgmock_bin_dir "${CMAKE_CURRENT_BINARY_DIR}/gmock")
|
||||
set(findgmock_gtest_lib "${findgmock_bin_dir}/gtest/libgtest.a")
|
||||
set(findgmock_gtest_main_lib "${findgmock_bin_dir}/gtest/libgtest_main.a")
|
||||
set(findgmock_gmock_lib "${findgmock_bin_dir}/libgmock.a")
|
||||
set(findgmock_gmock_main_lib "${findgmock_bin_dir}/libgmock_main.a")
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(GMock SOURCE_DIR "${GMOCK_SOURCE_DIR}"
|
||||
BINARY_DIR "${findgmock_bin_dir}"
|
||||
BUILD_BYPRODUCTS "${findgmock_gtest_lib}"
|
||||
"${findgmock_gtest_main_lib}"
|
||||
"${findgmock_gmock_lib}"
|
||||
"${findgmock_gmock_main_lib}"
|
||||
INSTALL_COMMAND ""
|
||||
CMAKE_ARGS "-DCMAKE_CXX_FLAGS=${findgmock_cxx_flags}")
|
||||
|
||||
add_library(gtest INTERFACE)
|
||||
target_include_directories(gtest INTERFACE ${GTEST_INCLUDE_DIRS})
|
||||
target_link_libraries(gtest INTERFACE ${findgmock_gtest_lib} ${CMAKE_THREAD_LIBS_INIT})
|
||||
add_dependencies(gtest GMock)
|
||||
|
||||
add_library(gtest_main INTERFACE)
|
||||
target_include_directories(gtest_main INTERFACE ${GTEST_INCLUDE_DIRS})
|
||||
target_link_libraries(gtest_main INTERFACE ${findgmock_gtest_main_lib} gtest)
|
||||
|
||||
add_library(gmock INTERFACE)
|
||||
target_include_directories(gmock INTERFACE ${GMOCK_INCLUDE_DIRS})
|
||||
target_link_libraries(gmock INTERFACE ${findgmock_gmock_lib} gtest)
|
||||
|
||||
add_library(gmock_main INTERFACE)
|
||||
target_include_directories(gmock_main INTERFACE ${GMOCK_INCLUDE_DIRS})
|
||||
target_link_libraries(gmock_main INTERFACE ${findgmock_gmock_main_lib} gmock)
|
||||
|
||||
set(GTEST_LIBRARIES gtest)
|
||||
set(GTEST_MAIN_LIBRARIES gtest_main)
|
||||
set(GMOCK_LIBRARIES gmock gmock_main)
|
||||
set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
|
||||
|
||||
unset(findgmock_cxx_flags)
|
||||
unset(findgmock_bin_dir)
|
||||
unset(findgmock_gtest_lib)
|
||||
unset(findgmock_gtest_main_lib)
|
||||
unset(findgmock_gmock_lib)
|
||||
unset(findgmock_gmock_main_lib)
|
||||
|
|
@ -2,7 +2,11 @@
|
|||
Description=Anbox session manager
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=@SNAP_MOUNT_DIR@/anbox session-manager
|
||||
Restart=always
|
||||
StartLimitIntervalSec=3
|
||||
StartLimitBurst=1
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
|
|
|
|||
BIN
data/ui/loading-screen.png
Normal file
BIN
data/ui/loading-screen.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
1
debian/anbox-common.install
vendored
1
debian/anbox-common.install
vendored
|
|
@ -1,3 +1,4 @@
|
|||
etc/X11/Xsession.d/68anbox
|
||||
usr/share/upstart/sessions/anbox.conf
|
||||
usr/lib/systemd/user/anbox.service
|
||||
usr/lib/systemd/user/default.target.wants/anbox.service
|
||||
|
|
|
|||
7
debian/changelog
vendored
7
debian/changelog
vendored
|
|
@ -1,3 +1,10 @@
|
|||
anbox (6) artful; urgency=medium
|
||||
|
||||
* Add anbox-common package which ships any additional files needed for
|
||||
anbox but can't be installed with a snap as of today.
|
||||
|
||||
-- Simon Fels <morphis@gravedo.de> Sat, 29 Apr 2017 12:06:56 +0200
|
||||
|
||||
anbox (5) zesty; urgency=medium
|
||||
|
||||
* Rework packaging to also ship things we installed through the snap
|
||||
|
|
|
|||
2
debian/control
vendored
2
debian/control
vendored
|
|
@ -10,7 +10,7 @@ Vcs-Git: https://github.com/anbox/anbox.git
|
|||
|
||||
Package: anbox-common
|
||||
Architecture: all
|
||||
Depends: ${misc:Depends}
|
||||
Depends: ${misc:Depends}, dbus-user-session
|
||||
Description: Common files necessary for Anbox
|
||||
.
|
||||
This package contains necessary things which can't be shipped
|
||||
|
|
|
|||
3
debian/rules
vendored
3
debian/rules
vendored
|
|
@ -28,8 +28,9 @@ override_dh_install:
|
|||
install -d $(CURDIR)/debian/tmp/etc/modules-load.d
|
||||
install -m 0644 kernel/anbox.conf $(CURDIR)/debian/tmp/etc/modules-load.d
|
||||
|
||||
install -d $(CURDIR)/debian/tmp/usr/lib/systemd/user/
|
||||
install -d $(CURDIR)/debian/tmp/usr/lib/systemd/user/default.target.wants
|
||||
install -m 0644 data/anbox.service $(CURDIR)/debian/tmp/usr/lib/systemd/user/
|
||||
ln -sf /usr/lib/systemd/user/anbox.service $(CURDIR)/debian/tmp/usr/lib/systemd/user/default.target.wants/anbox.service
|
||||
|
||||
install -d $(CURDIR)/debian/tmp/usr/share/upstart/sessions/
|
||||
install -m 0644 data/anbox.conf $(CURDIR)/debian/tmp/usr/share/upstart/sessions/
|
||||
|
|
|
|||
|
|
@ -33,8 +33,15 @@ This will take quite some time depending on the speed of your internet connectio
|
|||
|
||||
## Build Android
|
||||
|
||||
When all sources are successfully downloaded you can start building Android
|
||||
itself. Initialize the build by
|
||||
When all sources are successfully downloaded you can start building Android itself.
|
||||
|
||||
Firstly initialize the environment with the ```envsetup.sh``` script.
|
||||
|
||||
```
|
||||
$ . build/envsetup.sh
|
||||
```
|
||||
|
||||
Then initialize the build using ```lunch```.
|
||||
|
||||
```
|
||||
$ lunch anbox_desktop_x86_64-userdebug
|
||||
|
|
@ -43,7 +50,7 @@ $ lunch anbox_desktop_x86_64-userdebug
|
|||
The complete list of supported build targets:
|
||||
|
||||
* anbox_desktop_x86_64-userdebug
|
||||
* anbox_desktop_armv7a_arm-userdebug
|
||||
* anbox_desktop_armv7a_neon-userdebug
|
||||
* anbox_desktop_arm64-userdebug
|
||||
|
||||
Now build everything with
|
||||
|
|
|
|||
|
|
@ -20,5 +20,5 @@ if ("${cmake_build_type_lower}" STREQUAL "trace")
|
|||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPENGL_DEBUG}")
|
||||
endif()
|
||||
|
||||
add_library(GLESv1_dec ${SOURCES} ${GENERATED_SOURCES})
|
||||
add_library(GLESv1_dec STATIC ${SOURCES} ${GENERATED_SOURCES})
|
||||
target_link_libraries(GLESv1_dec OpenglCodecCommon)
|
||||
|
|
|
|||
|
|
@ -20,5 +20,5 @@ if ("${cmake_build_type_lower}" STREQUAL "trace")
|
|||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPENGL_DEBUG}")
|
||||
endif()
|
||||
|
||||
add_library(GLESv2_dec ${SOURCES} ${GENERATED_SOURCES})
|
||||
add_library(GLESv2_dec STATIC ${SOURCES} ${GENERATED_SOURCES})
|
||||
target_link_libraries(GLESv2_dec OpenglCodecCommon)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@ set(SOURCES
|
|||
objectNameManager.cpp
|
||||
FramebufferData.cpp)
|
||||
|
||||
add_library(GLcommon ${SOURCES})
|
||||
add_library(GLcommon STATIC ${SOURCES})
|
||||
target_link_libraries(GLcommon
|
||||
emugl_common)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ set(SOURCES
|
|||
GLESv2Dispatch.cpp
|
||||
GLESv1Dispatch.cpp)
|
||||
|
||||
add_library(OpenGLESDispatch ${SOURCES} ${GENERATED_SOURCES})
|
||||
add_library(OpenGLESDispatch STATIC ${SOURCES} ${GENERATED_SOURCES})
|
||||
target_link_libraries(OpenGLESDispatch
|
||||
emugl_common
|
||||
GLESv2_dec
|
||||
|
|
|
|||
|
|
@ -16,5 +16,5 @@ if ("${cmake_build_type_lower}" STREQUAL "trace")
|
|||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPENGL_DEBUG}")
|
||||
endif()
|
||||
|
||||
add_library(renderControl_dec ${GENERATED_SOURCES})
|
||||
add_library(renderControl_dec STATIC ${GENERATED_SOURCES})
|
||||
target_link_libraries(renderControl_dec OpenglCodecCommon)
|
||||
|
|
|
|||
|
|
@ -12,4 +12,4 @@ set(SOURCES
|
|||
Makefile
|
||||
ProtocolUtils.h)
|
||||
|
||||
add_library(OpenglCodecCommon ${SOURCES})
|
||||
add_library(OpenglCodecCommon STATIC ${SOURCES})
|
||||
|
|
|
|||
|
|
@ -28,6 +28,6 @@ set(COMMON_SOURCES
|
|||
thread_unittest.cpp
|
||||
unique_integer_map.h)
|
||||
|
||||
add_library(emugl_common ${COMMON_SOURCES})
|
||||
add_library(emugl_common STATIC ${COMMON_SOURCES})
|
||||
target_link_libraries(emugl_common
|
||||
dl pthread)
|
||||
|
|
|
|||
|
|
@ -114,6 +114,12 @@ public:
|
|||
*/
|
||||
wait::Result wait_for(const wait::Flags& flags);
|
||||
|
||||
/**
|
||||
* @brief Mark the child process to not to be killed when the ChildProcess
|
||||
* instance goes away.
|
||||
*/
|
||||
void dont_kill_on_cleanup();
|
||||
|
||||
#ifndef ANDROID
|
||||
/**
|
||||
* @brief Access this process's stderr.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
# Authored by: Thomas Voss <thomas.voss@canonical.com>
|
||||
add_library(
|
||||
process-cpp
|
||||
|
||||
STATIC
|
||||
|
||||
core/posix/backtrace.h
|
||||
core/posix/backtrace.cpp
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ struct ChildProcess::Private
|
|||
~Private()
|
||||
{
|
||||
// Check if we are in the original parent process.
|
||||
if (original_parent_pid == getpid())
|
||||
if (original_parent_pid == getpid() && !dont_kill_on_cleanup)
|
||||
{
|
||||
// If so, check if we are considering a valid pid here.
|
||||
// If so, we kill the original child.
|
||||
|
|
@ -333,6 +333,8 @@ struct ChildProcess::Private
|
|||
// is called from the child process.
|
||||
pid_t original_parent_pid;
|
||||
pid_t original_child_pid;
|
||||
|
||||
bool dont_kill_on_cleanup = false;
|
||||
};
|
||||
|
||||
ChildProcess ChildProcess::invalid()
|
||||
|
|
@ -395,6 +397,11 @@ wait::Result ChildProcess::wait_for(const wait::Flags& flags)
|
|||
return result;
|
||||
}
|
||||
|
||||
void ChildProcess::dont_kill_on_cleanup()
|
||||
{
|
||||
d->dont_kill_on_cleanup = true;
|
||||
}
|
||||
|
||||
#ifndef ANDROID
|
||||
std::istream& ChildProcess::cerr()
|
||||
{
|
||||
|
|
|
|||
2
external/xdg/CMakeLists.txt
vendored
2
external/xdg/CMakeLists.txt
vendored
|
|
@ -11,7 +11,7 @@ include_directories(
|
|||
${Boost_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
add_library(xdg xdg.cpp)
|
||||
add_library(xdg STATIC xdg.cpp)
|
||||
set_property(TARGET xdg PROPERTY CXX_STANDARD 11)
|
||||
target_link_libraries(xdg ${Boost_LIBRARIES})
|
||||
|
||||
|
|
|
|||
1
external/xdg/xdg.cpp
vendored
1
external/xdg/xdg.cpp
vendored
|
|
@ -57,7 +57,6 @@ constexpr const char* xdg_data_dirs{"XDG_DATA_DIRS"};
|
|||
constexpr const char* xdg_config_home{"XDG_CONFIG_HOME"};
|
||||
constexpr const char* xdg_config_dirs{"XDG_CONFIG_DIRS"};
|
||||
constexpr const char* xdg_cache_home{"XDG_CACHE_HOME"};
|
||||
constexpr const char* xdg_runtime_dir{"XDG_RUNTIME_DIR"};
|
||||
}
|
||||
|
||||
namespace impl
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
PACKAGE_NAME="anbox-ashmem"
|
||||
PACKAGE_VERSION="1"
|
||||
CLEAN="make clean"
|
||||
MAKE[0]="make all KVERSION=$kernelver"
|
||||
MAKE[0]="make all KERNEL_SRC=/lib/modules/$kernelver/build"
|
||||
BUILT_MODULE_NAME[0]="ashmem_linux"
|
||||
DEST_MODULE_LOCATION[0]="/updates"
|
||||
AUTOINSTALL="yes"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
PACKAGE_NAME="anbox-binder"
|
||||
PACKAGE_VERSION="1"
|
||||
CLEAN="make clean"
|
||||
MAKE[0]="make all KVERSION=$kernelver"
|
||||
MAKE[0]="make all KERNEL_SRC=/lib/modules/$kernelver/build"
|
||||
BUILT_MODULE_NAME[0]="binder_linux"
|
||||
DEST_MODULE_LOCATION[0]="/updates"
|
||||
AUTOINSTALL="yes"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,185 @@
|
|||
From 8f8ac2552c4a411cf1b8c6328409f861248e8d0d Mon Sep 17 00:00:00 2001
|
||||
From: Oren Laadan <orenl@cellrox.com>
|
||||
Date: Sun, 22 Dec 2013 10:07:39 +0000
|
||||
Subject: [PATCH 1/2] ipc namespace: a generic per-ipc pointer and peripc_ops
|
||||
|
||||
Add a void * pointer to struct ipc_namespace. The access rules are:
|
||||
1. (un)register ops with (un)register_peripc_operations()
|
||||
2. call ipc_assign_generic() to put private data on the ipc_namespace
|
||||
3. call ipc_access_generic() to access the private data
|
||||
4. do not change the pointer during the lifetime of ipc_namespace
|
||||
|
||||
Modeled after generic net-ns pointers (commit dec827d), but simplified
|
||||
to accommodate a single user for now (reduce code churn):
|
||||
5. only one caller can register at a time
|
||||
6. caller must register at boot time (not to be used by modules)
|
||||
|
||||
Signed-off-by: Oren Laadan <orenl@cellrox.com>
|
||||
Signed-off-by: Amir Goldstein <cardoe@cardoe.com>
|
||||
---
|
||||
include/linux/ipc_namespace.h | 29 +++++++++++++++++++++
|
||||
ipc/namespace.c | 9 +++++++
|
||||
ipc/util.c | 60 +++++++++++++++++++++++++++++++++++++++++++
|
||||
ipc/util.h | 3 +++
|
||||
4 files changed, 101 insertions(+)
|
||||
|
||||
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
|
||||
index d6ad91f..535061a 100644
|
||||
--- a/include/linux/ipc_namespace.h
|
||||
+++ b/include/linux/ipc_namespace.h
|
||||
@@ -70,8 +70,37 @@ struct ipc_namespace {
|
||||
struct user_namespace *user_ns;
|
||||
|
||||
unsigned int proc_inum;
|
||||
+
|
||||
+ /* allow others to piggyback on ipc_namesspaces */
|
||||
+ void *gen; /* for others' private stuff */
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * To access to the per-ipc generic data:
|
||||
+ * 1. (un)register ops with (un)register_peripc_operations()
|
||||
+ * 2. call ipc_assign_generic() to put private data on the ipc_namespace
|
||||
+ * 3. call ipc_access_generic() to access the private data
|
||||
+ * 4. do not change the pointer during the lifetime of ipc_namespace
|
||||
+ *
|
||||
+ * Modeled after generic net-ns pointers (commit dec827d), simplified for
|
||||
+ * a single user case for now:
|
||||
+ * 5. only one caller can register at a time
|
||||
+ * 6. caller must register at boot time (not to be used by modules)
|
||||
+ */
|
||||
+struct peripc_operations {
|
||||
+ int (*init)(struct ipc_namespace *);
|
||||
+ void (*exit)(struct ipc_namespace *);
|
||||
+};
|
||||
+
|
||||
+static inline void ipc_assign_generic(struct ipc_namespace *ns, void *data)
|
||||
+{ ns->gen = data; }
|
||||
+
|
||||
+static inline void *ipc_access_generic(struct ipc_namespace *ns)
|
||||
+{ return ns->gen; }
|
||||
+
|
||||
+extern int register_peripc_ops(struct peripc_operations *ops);
|
||||
+extern void unregister_peripc_ops(struct peripc_operations *ops);
|
||||
+
|
||||
extern struct ipc_namespace init_ipc_ns;
|
||||
extern atomic_t nr_ipc_ns;
|
||||
|
||||
diff --git a/ipc/namespace.c b/ipc/namespace.c
|
||||
index aba9a58..575aeae 100644
|
||||
--- a/ipc/namespace.c
|
||||
+++ b/ipc/namespace.c
|
||||
@@ -33,9 +33,17 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
|
||||
}
|
||||
|
||||
atomic_set(&ns->count, 1);
|
||||
+
|
||||
+ err = init_peripc_ns(ns);
|
||||
+ if (err) {
|
||||
+ kfree(ns);
|
||||
+ return ERR_PTR(err);
|
||||
+ }
|
||||
+
|
||||
err = mq_init_ns(ns);
|
||||
if (err) {
|
||||
proc_free_inum(ns->proc_inum);
|
||||
+ exit_peripc_ns(ns);
|
||||
kfree(ns);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
@@ -111,6 +119,7 @@ static void free_ipc_ns(struct ipc_namespace *ns)
|
||||
sem_exit_ns(ns);
|
||||
msg_exit_ns(ns);
|
||||
shm_exit_ns(ns);
|
||||
+ exit_peripc_ns(ns);
|
||||
atomic_dec(&nr_ipc_ns);
|
||||
|
||||
/*
|
||||
diff --git a/ipc/util.c b/ipc/util.c
|
||||
index 7353425..533f8f9 100644
|
||||
--- a/ipc/util.c
|
||||
+++ b/ipc/util.c
|
||||
@@ -71,6 +71,66 @@ struct ipc_proc_iface {
|
||||
int (*show)(struct seq_file *, void *);
|
||||
};
|
||||
|
||||
+/* allow others to piggyback on ipc_namespace */
|
||||
+static DEFINE_MUTEX(peripc_mutex);
|
||||
+static struct peripc_operations *peripc_ops;
|
||||
+
|
||||
+/*
|
||||
+ * peripc_operations is a simplified pernet_operations:
|
||||
+ * - allow only one entity to register
|
||||
+ * - allow to register only at boot time (no modules)
|
||||
+ * (these assumptions make the code much simpler)
|
||||
+ */
|
||||
+
|
||||
+static int init_peripc_count;
|
||||
+
|
||||
+/* caller hold peripc_mutex */
|
||||
+int init_peripc_ns(struct ipc_namespace *ns)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (peripc_ops && peripc_ops->init)
|
||||
+ ret = peripc_ops->init(ns);
|
||||
+ if (ret == 0)
|
||||
+ init_peripc_count++;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/* caller hold peripc_mutex */
|
||||
+void exit_peripc_ns(struct ipc_namespace *ns)
|
||||
+{
|
||||
+ if (peripc_ops && peripc_ops->exit)
|
||||
+ peripc_ops->exit(ns);
|
||||
+ init_peripc_count--;
|
||||
+}
|
||||
+
|
||||
+int register_peripc_ops(struct peripc_operations *ops)
|
||||
+{
|
||||
+ int ret = -EBUSY;
|
||||
+
|
||||
+ mutex_lock(&peripc_mutex);
|
||||
+ /* must be first register, and only init ipc_namespace exists */
|
||||
+ if (peripc_ops == NULL && init_peripc_count == 0) {
|
||||
+ peripc_ops = ops;
|
||||
+ ret = init_peripc_ns(&init_ipc_ns);
|
||||
+ if (ret < 0)
|
||||
+ peripc_ops = NULL;
|
||||
+ }
|
||||
+ mutex_unlock(&peripc_mutex);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+void unregister_peripc_ops(struct peripc_operations *ops)
|
||||
+{
|
||||
+ mutex_lock(&peripc_mutex);
|
||||
+ /* sanity: be same as registered, and no other ipc ns (beyond init) */
|
||||
+ BUG_ON(peripc_ops != ops);
|
||||
+ BUG_ON(init_peripc_count != 1);
|
||||
+ if (ops->exit)
|
||||
+ exit_peripc_ns(&init_ipc_ns);
|
||||
+ peripc_ops = NULL;
|
||||
+ mutex_unlock(&peripc_mutex);
|
||||
+}
|
||||
static void ipc_memory_notifier(struct work_struct *work)
|
||||
{
|
||||
ipcns_notify(IPCNS_MEMCHANGED);
|
||||
diff --git a/ipc/util.h b/ipc/util.h
|
||||
index 59d78aa..daee0be 100644
|
||||
--- a/ipc/util.h
|
||||
+++ b/ipc/util.h
|
||||
@@ -47,6 +47,9 @@ static inline void msg_exit_ns(struct ipc_namespace *ns) { }
|
||||
static inline void shm_exit_ns(struct ipc_namespace *ns) { }
|
||||
#endif
|
||||
|
||||
+int init_peripc_ns(struct ipc_namespace *ns);
|
||||
+void exit_peripc_ns(struct ipc_namespace *ns);
|
||||
+
|
||||
struct ipc_rcu {
|
||||
struct rcu_head rcu;
|
||||
atomic_t refcount;
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -0,0 +1,428 @@
|
|||
From fcd9d70190dd7e6536878a6379122f06e3b90919 Mon Sep 17 00:00:00 2001
|
||||
From: Oren Laadan <orenl@cellrox.com>
|
||||
Date: Sun, 22 Dec 2013 10:07:40 +0000
|
||||
Subject: [PATCH 2/2] binder: implement namepsace support for Android binder
|
||||
driver
|
||||
|
||||
Add namespaces support for the Android binder driver.
|
||||
As binder is an IPC mechanism, tie its namespace to IPC_NS.
|
||||
|
||||
In binder, the first process to call BINDER_SET_CONTEXT_MGR ioctl
|
||||
becomes the manager with context 0, and thereafter IPC is realized
|
||||
through binder handles obtained from this manager.
|
||||
|
||||
For namespaces, associate a separate binder state with each namespace
|
||||
so each namespace has its own context manager. Binder users within a
|
||||
namespace interact only with the context manager there. This suffices
|
||||
because binder does not allow IPC not via the context manager.
|
||||
|
||||
Currently, statistics remain global, except for the list of processes
|
||||
that hold an open binder device (reported per namespace).
|
||||
|
||||
Signed-off-by: Oren Laadan <orenl@cellrox.com>
|
||||
Acked-by: Amir Goldstein <cardoe@cardoe.com>
|
||||
---
|
||||
drivers/android/Kconfig | 1 +
|
||||
drivers/android/binder.c | 172 ++++++++++++++++++++++++++++++++++++++---------
|
||||
2 files changed, 143 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig
|
||||
index bdfc6c6..739063d 100644
|
||||
--- a/drivers/android/Kconfig
|
||||
+++ b/drivers/android/Kconfig
|
||||
@@ -10,6 +10,7 @@ if ANDROID
|
||||
config ANDROID_BINDER_IPC
|
||||
bool "Android Binder IPC Driver"
|
||||
depends on MMU
|
||||
+ select SYSVIPC
|
||||
default n
|
||||
---help---
|
||||
Binder is used in Android for both communication between processes,
|
||||
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
|
||||
index fee479d..2a63e9b 100644
|
||||
--- a/drivers/android/binder.c
|
||||
+++ b/drivers/android/binder.c
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/slab.h>
|
||||
+#include <linux/ipc_namespace.h>
|
||||
#include <linux/pid_namespace.h>
|
||||
#include <linux/security.h>
|
||||
|
||||
@@ -47,19 +48,98 @@
|
||||
#include <uapi/linux/android/binder.h>
|
||||
#include "binder_trace.h"
|
||||
|
||||
+/*
|
||||
+ * Using a private context manager for each binder namespace is sufficient
|
||||
+ * to isolate between namespaces, because in binder all IPC must be realized
|
||||
+ * via hanldes obtained from the context manager.
|
||||
+ *
|
||||
+ * TODO: currently, most debugfs data is not tracked per binder namespaces.
|
||||
+ * Except for "procs" which are properly virtualized, everything else is
|
||||
+ * global, including stats, logs, and dead nodes.
|
||||
+ */
|
||||
+struct binder_namespace {
|
||||
+ struct kref kref;
|
||||
+
|
||||
+ struct binder_node *context_mgr_node;
|
||||
+ kuid_t context_mgr_uid;
|
||||
+ int last_id;
|
||||
+
|
||||
+ struct hlist_head procs;
|
||||
+};
|
||||
+
|
||||
+static struct binder_namespace *create_binder_ns(void)
|
||||
+{
|
||||
+ struct binder_namespace *binder_ns;
|
||||
+
|
||||
+ binder_ns = kzalloc(sizeof(struct binder_namespace), GFP_KERNEL);
|
||||
+ if (binder_ns) {
|
||||
+ kref_init(&binder_ns->kref);
|
||||
+ binder_ns->context_mgr_uid = INVALID_UID;
|
||||
+ INIT_HLIST_HEAD(&binder_ns->procs);
|
||||
+ }
|
||||
+ return binder_ns;
|
||||
+}
|
||||
+
|
||||
+static void free_binder_ns(struct kref *kref)
|
||||
+{
|
||||
+ kfree(container_of(kref, struct binder_namespace, kref));
|
||||
+}
|
||||
+
|
||||
+static void get_binder_ns(struct binder_namespace *binder_ns)
|
||||
+{
|
||||
+ kref_get(&binder_ns->kref);
|
||||
+}
|
||||
+
|
||||
+static void put_binder_ns(struct binder_namespace *binder_ns)
|
||||
+{
|
||||
+ kref_put(&binder_ns->kref, free_binder_ns);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Binder is an IPC mechanism, so tie its namespace to IPC_NS
|
||||
+ * using the generic data pointer and per-ipc operations.
|
||||
+ */
|
||||
+static struct binder_namespace *current_binder_ns(void)
|
||||
+{
|
||||
+ return ipc_access_generic(current->nsproxy->ipc_ns);
|
||||
+}
|
||||
+
|
||||
+int binder_init_ns(struct ipc_namespace *ipcns)
|
||||
+{
|
||||
+ struct binder_namespace *binder_ns;
|
||||
+ int ret = -ENOMEM;
|
||||
+
|
||||
+ binder_ns = create_binder_ns();
|
||||
+ if (binder_ns) {
|
||||
+ ipc_assign_generic(ipcns, binder_ns);
|
||||
+ ret = 0;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+void binder_exit_ns(struct ipc_namespace *ipcns)
|
||||
+{
|
||||
+ struct binder_namespace *binder_ns;
|
||||
+
|
||||
+ binder_ns = ipc_access_generic(ipcns);
|
||||
+ if (binder_ns)
|
||||
+ put_binder_ns(binder_ns);
|
||||
+}
|
||||
+
|
||||
+struct peripc_operations binder_peripc_ops = {
|
||||
+ .init = binder_init_ns,
|
||||
+ .exit = binder_exit_ns,
|
||||
+};
|
||||
+
|
||||
static DEFINE_RT_MUTEX(binder_main_lock);
|
||||
static DEFINE_MUTEX(binder_deferred_lock);
|
||||
static DEFINE_MUTEX(binder_mmap_lock);
|
||||
|
||||
-static HLIST_HEAD(binder_procs);
|
||||
static HLIST_HEAD(binder_deferred_list);
|
||||
static HLIST_HEAD(binder_dead_nodes);
|
||||
|
||||
static struct dentry *binder_debugfs_dir_entry_root;
|
||||
static struct dentry *binder_debugfs_dir_entry_proc;
|
||||
-static struct binder_node *binder_context_mgr_node;
|
||||
-static kuid_t binder_context_mgr_uid = INVALID_UID;
|
||||
-static int binder_last_id;
|
||||
static struct workqueue_struct *binder_deferred_workqueue;
|
||||
|
||||
#define BINDER_DEBUG_ENTRY(name) \
|
||||
@@ -327,6 +407,8 @@ struct binder_proc {
|
||||
int ready_threads;
|
||||
long default_priority;
|
||||
struct dentry *debugfs_entry;
|
||||
+
|
||||
+ struct binder_namespace *binder_ns;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -910,7 +992,7 @@ static struct binder_node *binder_new_node(struct binder_proc *proc,
|
||||
binder_stats_created(BINDER_STAT_NODE);
|
||||
rb_link_node(&node->rb_node, parent, p);
|
||||
rb_insert_color(&node->rb_node, &proc->nodes);
|
||||
- node->debug_id = ++binder_last_id;
|
||||
+ node->debug_id = ++proc->binder_ns->last_id;
|
||||
node->proc = proc;
|
||||
node->ptr = ptr;
|
||||
node->cookie = cookie;
|
||||
@@ -931,7 +1013,7 @@ static int binder_inc_node(struct binder_node *node, int strong, int internal,
|
||||
if (internal) {
|
||||
if (target_list == NULL &&
|
||||
node->internal_strong_refs == 0 &&
|
||||
- !(node == binder_context_mgr_node &&
|
||||
+ !(node == node->proc->binder_ns->context_mgr_node &&
|
||||
node->has_strong_ref)) {
|
||||
pr_err("invalid inc strong node for %d\n",
|
||||
node->debug_id);
|
||||
@@ -1045,13 +1127,13 @@ static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
|
||||
if (new_ref == NULL)
|
||||
return NULL;
|
||||
binder_stats_created(BINDER_STAT_REF);
|
||||
- new_ref->debug_id = ++binder_last_id;
|
||||
+ new_ref->debug_id = ++proc->binder_ns->last_id;
|
||||
new_ref->proc = proc;
|
||||
new_ref->node = node;
|
||||
rb_link_node(&new_ref->rb_node_node, parent, p);
|
||||
rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node);
|
||||
|
||||
- new_ref->desc = (node == binder_context_mgr_node) ? 0 : 1;
|
||||
+ new_ref->desc = (node == proc->binder_ns->context_mgr_node) ? 0 : 1;
|
||||
for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
|
||||
ref = rb_entry(n, struct binder_ref, rb_node_desc);
|
||||
if (ref->desc > new_ref->desc)
|
||||
@@ -1391,7 +1473,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
}
|
||||
target_node = ref->node;
|
||||
} else {
|
||||
- target_node = binder_context_mgr_node;
|
||||
+ target_node = proc->binder_ns->context_mgr_node;
|
||||
if (target_node == NULL) {
|
||||
return_error = BR_DEAD_REPLY;
|
||||
goto err_no_context_mgr_node;
|
||||
@@ -1452,7 +1534,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
}
|
||||
binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
|
||||
|
||||
- t->debug_id = ++binder_last_id;
|
||||
+ t->debug_id = ++proc->binder_ns->last_id;
|
||||
e->debug_id = t->debug_id;
|
||||
|
||||
if (reply)
|
||||
@@ -1787,10 +1869,10 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||
if (get_user(target, (uint32_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(uint32_t);
|
||||
- if (target == 0 && binder_context_mgr_node &&
|
||||
+ if (target == 0 && proc->binder_ns->context_mgr_node &&
|
||||
(cmd == BC_INCREFS || cmd == BC_ACQUIRE)) {
|
||||
ref = binder_get_ref_for_node(proc,
|
||||
- binder_context_mgr_node);
|
||||
+ proc->binder_ns->context_mgr_node);
|
||||
if (ref->desc != target) {
|
||||
binder_user_error("%d:%d tried to acquire reference to desc 0, got %d instead\n",
|
||||
proc->pid, thread->pid,
|
||||
@@ -2696,9 +2778,10 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp)
|
||||
{
|
||||
int ret = 0;
|
||||
struct binder_proc *proc = filp->private_data;
|
||||
+ struct binder_namespace *binder_ns = proc->binder_ns;
|
||||
kuid_t curr_euid = current_euid();
|
||||
|
||||
- if (binder_context_mgr_node != NULL) {
|
||||
+ if (binder_ns->context_mgr_node != NULL) {
|
||||
pr_err("BINDER_SET_CONTEXT_MGR already set\n");
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
@@ -2706,27 +2789,27 @@ static int binder_ioctl_set_ctx_mgr(struct file *filp)
|
||||
ret = security_binder_set_context_mgr(proc->tsk);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
- if (uid_valid(binder_context_mgr_uid)) {
|
||||
- if (!uid_eq(binder_context_mgr_uid, curr_euid)) {
|
||||
+ if (uid_valid(binder_ns->context_mgr_uid)) {
|
||||
+ if (!uid_eq(binder_ns->context_mgr_uid, curr_euid)) {
|
||||
pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",
|
||||
from_kuid(&init_user_ns, curr_euid),
|
||||
from_kuid(&init_user_ns,
|
||||
- binder_context_mgr_uid));
|
||||
+ binder_ns->context_mgr_uid));
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
- binder_context_mgr_uid = curr_euid;
|
||||
+ binder_ns->context_mgr_uid = curr_euid;
|
||||
}
|
||||
- binder_context_mgr_node = binder_new_node(proc, 0, 0);
|
||||
- if (binder_context_mgr_node == NULL) {
|
||||
+ binder_ns->context_mgr_node = binder_new_node(proc, 0, 0);
|
||||
+ if (binder_ns->context_mgr_node == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
- binder_context_mgr_node->local_weak_refs++;
|
||||
- binder_context_mgr_node->local_strong_refs++;
|
||||
- binder_context_mgr_node->has_strong_ref = 1;
|
||||
- binder_context_mgr_node->has_weak_ref = 1;
|
||||
+ binder_ns->context_mgr_node->local_weak_refs++;
|
||||
+ binder_ns->context_mgr_node->local_strong_refs++;
|
||||
+ binder_ns->context_mgr_node->has_strong_ref = 1;
|
||||
+ binder_ns->context_mgr_node->has_weak_ref = 1;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@@ -2947,10 +3030,15 @@ err_bad_arg:
|
||||
static int binder_open(struct inode *nodp, struct file *filp)
|
||||
{
|
||||
struct binder_proc *proc;
|
||||
+ struct binder_namespace *binder_ns;
|
||||
|
||||
binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n",
|
||||
current->group_leader->pid, current->pid);
|
||||
|
||||
+ binder_ns = current_binder_ns();
|
||||
+ if (binder_ns == NULL)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
proc = kzalloc(sizeof(*proc), GFP_KERNEL);
|
||||
if (proc == NULL)
|
||||
return -ENOMEM;
|
||||
@@ -2960,10 +3048,13 @@ static int binder_open(struct inode *nodp, struct file *filp)
|
||||
init_waitqueue_head(&proc->wait);
|
||||
proc->default_priority = task_nice(current);
|
||||
|
||||
+ proc->binder_ns = binder_ns;
|
||||
+ get_binder_ns(binder_ns);
|
||||
+
|
||||
binder_lock(__func__);
|
||||
|
||||
binder_stats_created(BINDER_STAT_PROC);
|
||||
- hlist_add_head(&proc->proc_node, &binder_procs);
|
||||
+ hlist_add_head(&proc->proc_node, &binder_ns->procs);
|
||||
proc->pid = current->group_leader->pid;
|
||||
INIT_LIST_HEAD(&proc->delivered_death);
|
||||
filp->private_data = proc;
|
||||
@@ -3067,6 +3158,7 @@ static int binder_node_release(struct binder_node *node, int refs)
|
||||
|
||||
static void binder_deferred_release(struct binder_proc *proc)
|
||||
{
|
||||
+ struct binder_namespace *binder_ns = proc->binder_ns;
|
||||
struct binder_transaction *t;
|
||||
struct rb_node *n;
|
||||
int threads, nodes, incoming_refs, outgoing_refs, buffers,
|
||||
@@ -3077,11 +3169,12 @@ static void binder_deferred_release(struct binder_proc *proc)
|
||||
|
||||
hlist_del(&proc->proc_node);
|
||||
|
||||
- if (binder_context_mgr_node && binder_context_mgr_node->proc == proc) {
|
||||
+ if (binder_ns->context_mgr_node &&
|
||||
+ binder_ns->context_mgr_node->proc == proc) {
|
||||
binder_debug(BINDER_DEBUG_DEAD_BINDER,
|
||||
"%s: %d context_mgr_node gone\n",
|
||||
__func__, proc->pid);
|
||||
- binder_context_mgr_node = NULL;
|
||||
+ binder_ns->context_mgr_node = NULL;
|
||||
}
|
||||
|
||||
threads = 0;
|
||||
@@ -3160,6 +3253,7 @@ static void binder_deferred_release(struct binder_proc *proc)
|
||||
vfree(proc->buffer);
|
||||
}
|
||||
|
||||
+ put_binder_ns(proc->binder_ns);
|
||||
put_task_struct(proc->tsk);
|
||||
|
||||
binder_debug(BINDER_DEBUG_OPEN_CLOSE,
|
||||
@@ -3540,10 +3634,14 @@ static void print_binder_proc_stats(struct seq_file *m,
|
||||
|
||||
static int binder_state_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
+ struct binder_namespace *binder_ns = current_binder_ns();
|
||||
struct binder_proc *proc;
|
||||
struct binder_node *node;
|
||||
int do_lock = !binder_debug_no_lock;
|
||||
|
||||
+ if (binder_ns == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
if (do_lock)
|
||||
binder_lock(__func__);
|
||||
|
||||
@@ -3554,7 +3652,7 @@ static int binder_state_show(struct seq_file *m, void *unused)
|
||||
hlist_for_each_entry(node, &binder_dead_nodes, dead_node)
|
||||
print_binder_node(m, node);
|
||||
|
||||
- hlist_for_each_entry(proc, &binder_procs, proc_node)
|
||||
+ hlist_for_each_entry(proc, &binder_ns->procs, proc_node)
|
||||
print_binder_proc(m, proc, 1);
|
||||
if (do_lock)
|
||||
binder_unlock(__func__);
|
||||
@@ -3563,9 +3661,13 @@ static int binder_state_show(struct seq_file *m, void *unused)
|
||||
|
||||
static int binder_stats_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
+ struct binder_namespace *binder_ns = current_binder_ns();
|
||||
struct binder_proc *proc;
|
||||
int do_lock = !binder_debug_no_lock;
|
||||
|
||||
+ if (binder_ns == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
if (do_lock)
|
||||
binder_lock(__func__);
|
||||
|
||||
@@ -3573,7 +3675,7 @@ static int binder_stats_show(struct seq_file *m, void *unused)
|
||||
|
||||
print_binder_stats(m, "", &binder_stats);
|
||||
|
||||
- hlist_for_each_entry(proc, &binder_procs, proc_node)
|
||||
+ hlist_for_each_entry(proc, &binder_ns->procs, proc_node)
|
||||
print_binder_proc_stats(m, proc);
|
||||
if (do_lock)
|
||||
binder_unlock(__func__);
|
||||
@@ -3582,14 +3684,18 @@ static int binder_stats_show(struct seq_file *m, void *unused)
|
||||
|
||||
static int binder_transactions_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
+ struct binder_namespace *binder_ns = current_binder_ns();
|
||||
struct binder_proc *proc;
|
||||
int do_lock = !binder_debug_no_lock;
|
||||
|
||||
+ if (binder_ns == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
if (do_lock)
|
||||
binder_lock(__func__);
|
||||
|
||||
seq_puts(m, "binder transactions:\n");
|
||||
- hlist_for_each_entry(proc, &binder_procs, proc_node)
|
||||
+ hlist_for_each_entry(proc, &binder_ns->procs, proc_node)
|
||||
print_binder_proc(m, proc, 0);
|
||||
if (do_lock)
|
||||
binder_unlock(__func__);
|
||||
@@ -3661,9 +3767,15 @@ static int __init binder_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
+ ret = register_peripc_ops(&binder_peripc_ops);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
binder_deferred_workqueue = create_singlethread_workqueue("binder");
|
||||
- if (!binder_deferred_workqueue)
|
||||
+ if (!binder_deferred_workqueue) {
|
||||
+ unregister_peripc_ops(&binder_peripc_ops);
|
||||
return -ENOMEM;
|
||||
+ }
|
||||
|
||||
binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL);
|
||||
if (binder_debugfs_dir_entry_root)
|
||||
--
|
||||
2.7.4
|
||||
|
||||
|
|
@ -14,34 +14,21 @@
|
|||
# limitations under the License.
|
||||
|
||||
# Taken from https://github.com/lxc/lxd-pkg-ubuntu/blob/dpm-xenial/lxd-bridge/lxd-bridge
|
||||
# but modified for the use within anbox.
|
||||
|
||||
varrun="/run/anbox"
|
||||
varlib="/var/lib/anbox"
|
||||
|
||||
BRIDGE="anboxbr0"
|
||||
BRIDGE="anbox0"
|
||||
|
||||
# IPv4
|
||||
IPV4_ADDR="10.0.6.1"
|
||||
IPV4_ADDR="192.168.250.1"
|
||||
IPV4_NETMASK="255.255.255.0"
|
||||
IPV4_NETWORK="10.0.6.1/24"
|
||||
IPV4_DHCP_RANGE="10.0.6.2,10.0.6.254"
|
||||
IPV4_DHCP_MAX="252"
|
||||
IPV4_NETWORK="192.168.250.1/24"
|
||||
IPV4_NAT="true"
|
||||
|
||||
# IPv6
|
||||
IPV6_ADDR="fd9d:e4dc:4e00:9e98::1"
|
||||
IPV6_MASK="64"
|
||||
IPV6_NETWORK="fd9d:e4dc:4e00:9e98::1/64"
|
||||
IPV6_NAT="true"
|
||||
IPV6_PROXY="false"
|
||||
|
||||
use_iptables_lock="-w"
|
||||
iptables -w -L -n > /dev/null 2>&1 || use_iptables_lock=""
|
||||
|
||||
HAS_IPV6=false
|
||||
[ -e "/proc/sys/net/ipv6/conf/default/disable_ipv6" ] && \
|
||||
[ "$(cat /proc/sys/net/ipv6/conf/default/disable_ipv6)" = "0" ] && HAS_IPV6=true
|
||||
|
||||
_netmask2cidr () {
|
||||
# Assumes there's no "255." after a non-255 byte in the mask
|
||||
local x=${1##*255.}
|
||||
|
|
@ -88,11 +75,6 @@ start() {
|
|||
# set up the anbox network
|
||||
[ ! -d "/sys/class/net/${BRIDGE}" ] && ip link add dev "${BRIDGE}" type bridge
|
||||
|
||||
if [ "${HAS_IPV6}" = "true" ]; then
|
||||
echo 0 > "/proc/sys/net/ipv6/conf/${BRIDGE}/autoconf" || true
|
||||
echo 0 > "/proc/sys/net/ipv6/conf/${BRIDGE}/accept_dad" || true
|
||||
fi
|
||||
|
||||
# if we are run from systemd on a system with selinux enabled,
|
||||
# the mkdir will create /run/anbox as init_var_run_t which dnsmasq
|
||||
# can't write its pid into, so we restorecon it (to var_run_t)
|
||||
|
|
@ -103,13 +85,6 @@ start() {
|
|||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d "${varlib}" ]; then
|
||||
mkdir -p "${varlib}"
|
||||
if which restorecon >/dev/null 2>&1; then
|
||||
restorecon "${varlib}"
|
||||
fi
|
||||
fi
|
||||
|
||||
ifup "${BRIDGE}" "${IPV4_ADDR}" "${IPV4_NETMASK}"
|
||||
|
||||
IPV4_ARG=""
|
||||
|
|
@ -118,25 +93,6 @@ start() {
|
|||
if [ "${IPV4_NAT}" = "true" ]; then
|
||||
iptables "${use_iptables_lock}" -t nat -A POSTROUTING -s "${IPV4_NETWORK}" ! -d "${IPV4_NETWORK}" -j MASQUERADE -m comment --comment "managed by anbox-bridge"
|
||||
fi
|
||||
IPV4_ARG="--listen-address ${IPV4_ADDR} --dhcp-range ${IPV4_DHCP_RANGE} --dhcp-lease-max=${IPV4_DHCP_MAX}"
|
||||
fi
|
||||
|
||||
IPV6_ARG=""
|
||||
if [ "${HAS_IPV6}" = "true" ] && [ -n "${IPV6_ADDR}" ] && [ -n "${IPV6_MASK}" ] && [ -n "${IPV6_NETWORK}" ]; then
|
||||
# IPv6 sysctls don't respect the "all" path...
|
||||
for interface in /proc/sys/net/ipv6/conf/*; do
|
||||
echo 2 > "${interface}/accept_ra"
|
||||
done
|
||||
|
||||
for interface in /proc/sys/net/ipv6/conf/*; do
|
||||
echo 1 > "${interface}/forwarding"
|
||||
done
|
||||
|
||||
ip -6 addr add dev "${BRIDGE}" "${IPV6_ADDR}/${IPV6_MASK}"
|
||||
if [ "${IPV6_NAT}" = "true" ]; then
|
||||
ip6tables "${use_iptables_lock}" -t nat -A POSTROUTING -s "${IPV6_NETWORK}" ! -d "${IPV6_NETWORK}" -j MASQUERADE -m comment --comment "managed by anbox-bridge"
|
||||
fi
|
||||
IPV6_ARG="--dhcp-range=${IPV6_ADDR},ra-stateless,ra-names --listen-address ${IPV6_ADDR}"
|
||||
fi
|
||||
|
||||
iptables "${use_iptables_lock}" -I INPUT -i "${BRIDGE}" -p udp --dport 67 -j ACCEPT -m comment --comment "managed by anbox-bridge"
|
||||
|
|
@ -147,35 +103,6 @@ start() {
|
|||
iptables "${use_iptables_lock}" -I FORWARD -o "${BRIDGE}" -j ACCEPT -m comment --comment "managed by anbox-bridge"
|
||||
iptables "${use_iptables_lock}" -t mangle -A POSTROUTING -o "${BRIDGE}" -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill -m comment --comment "managed by anbox-bridge"
|
||||
|
||||
DOMAIN_ARG=""
|
||||
if [ -n "${DOMAIN}" ]; then
|
||||
DOMAIN_ARG="-s ${DOMAIN} -S /${DOMAIN}/"
|
||||
fi
|
||||
|
||||
CONFILE_ARG=""
|
||||
if [ -n "${CONFILE}" ]; then
|
||||
CONFILE_ARG="--conf-file=${CONFILE}"
|
||||
fi
|
||||
|
||||
# https://lists.linuxcontainers.org/pipermail/lxc-devel/2014-October/010561.html
|
||||
for DNSMASQ_USER in anbox dnsmasq nobody
|
||||
do
|
||||
if getent passwd "${DNSMASQ_USER}" >/dev/null; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "${IPV4_ADDR}" ] || [ -n "${IPV6_ADDR}" ]; then
|
||||
# shellcheck disable=SC2086
|
||||
dnsmasq ${CONFILE_ARG} ${DOMAIN_ARG} -u "${DNSMASQ_USER}" --strict-order --bind-interfaces --pid-file="${varrun}/dnsmasq.pid" --dhcp-no-override --except-interface=lo --interface="${BRIDGE}" --dhcp-leasefile="${varlib}/dnsmasq.${BRIDGE}.leases" --dhcp-authoritative ${IPV4_ARG} ${IPV6_ARG} || cleanup
|
||||
fi
|
||||
|
||||
if [ "${HAS_IPV6}" = "true" ] && [ "${IPV6_PROXY}" = "true" ]; then
|
||||
PATH="${PATH}:$(dirname "${0}")" anbox-bridge-proxy --addr="[fe80::1%${BRIDGE}]:13128" &
|
||||
PID=$!
|
||||
echo "${PID}" > "${varrun}/proxy.pid"
|
||||
fi
|
||||
|
||||
touch "${varrun}/network_up"
|
||||
FAILED=0
|
||||
}
|
||||
|
|
@ -197,20 +124,6 @@ stop() {
|
|||
iptables ${use_iptables_lock} -t nat -D POSTROUTING -s ${IPV4_NETWORK} ! -d ${IPV4_NETWORK} -j MASQUERADE -m comment --comment "managed by anbox-bridge"
|
||||
fi
|
||||
|
||||
if [ "${HAS_IPV6}" = "true" ] && [ -n "${IPV6_NETWORK}" ] && [ "${IPV6_NAT}" = "true" ]; then
|
||||
ip6tables ${use_iptables_lock} -t nat -D POSTROUTING -s ${IPV6_NETWORK} ! -d ${IPV6_NETWORK} -j MASQUERADE -m comment --comment "managed by anbox-bridge"
|
||||
fi
|
||||
|
||||
if [ -e "${varrun}/dnsmasq.pid" ]; then
|
||||
pid=$(cat "${varrun}/dnsmasq.pid" 2>/dev/null) && kill -9 "${pid}"
|
||||
rm -f "${varrun}/dnsmasq.pid"
|
||||
fi
|
||||
|
||||
if [ -e "${varrun}/proxy.pid" ]; then
|
||||
pid=$(cat "${varrun}/proxy.pid" 2>/dev/null) && kill -9 "${pid}"
|
||||
rm -f "${varrun}/proxy.pid"
|
||||
fi
|
||||
|
||||
# if ${BRIDGE} has attached interfaces, don't destroy the bridge
|
||||
ls /sys/class/net/${BRIDGE}/brif/* > /dev/null 2>&1 || ip link delete "${BRIDGE}"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ apt-get install -qq -y \
|
|||
libproperties-cpp-dev \
|
||||
libprotobuf-dev \
|
||||
libsdl2-dev \
|
||||
libsdl2-image-dev \
|
||||
lxc-dev \
|
||||
pkg-config \
|
||||
protobuf-compiler
|
||||
|
|
@ -40,14 +41,26 @@ apt-get clean
|
|||
|
||||
cd /anbox
|
||||
|
||||
# In cases where anbox comes directly from a checked out Android
|
||||
# build environment we miss some symlinks which are present on
|
||||
# the host and don't have a valid git repository in that case.
|
||||
git clean -fdx . || true
|
||||
git reset --hard || true
|
||||
cleanup() {
|
||||
# In cases where anbox comes directly from a checked out Android
|
||||
# build environment we miss some symlinks which are present on
|
||||
# the host and don't have a valid git repository in that case.
|
||||
if [ -d .git ] ; then
|
||||
git clean -fdx .
|
||||
git reset --hard
|
||||
fi
|
||||
}
|
||||
|
||||
cleanup
|
||||
|
||||
mkdir build || rm -rf build/*
|
||||
cd build
|
||||
cmake ..
|
||||
make -j10
|
||||
make test
|
||||
|
||||
cleanup
|
||||
|
||||
apt-get install -y build-essential curl devscripts gdebi-core dkms dh-systemd
|
||||
apt-get install -y $(gdebi --quiet --apt-line ./debian/control)
|
||||
debuild -us -uc
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ start() {
|
|||
|
||||
exec $AA_EXEC $SNAP/bin/anbox-wrapper.sh container-manager \
|
||||
--data-path=$DATA_PATH \
|
||||
--android-image=$ANDROID_IMG
|
||||
--android-image=$ANDROID_IMG \
|
||||
--daemon
|
||||
}
|
||||
|
||||
stop() {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,12 @@ export LIBGL_DRIVERS_PATH=$SNAP/usr/lib/$ARCH/dri
|
|||
# ensure the snappy gl libs win
|
||||
export LD_LIBRARY_PATH="$SNAP_LIBRARY_PATH:$LD_LIBRARY_PATH"
|
||||
|
||||
# Workaround in snapd for proprietary nVidia drivers mounts the drivers in
|
||||
# /var/lib/snapd/lib/gl that needs to be in LD_LIBRARY_PATH
|
||||
# Without that OpenGL using apps do not work with the nVidia drivers.
|
||||
# Ref.: https://bugs.launchpad.net/snappy/+bug/1588192
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/var/lib/snapd/lib/gl
|
||||
|
||||
# We set XDG_DATA_HOME to SNAP_USER_COMMON here as this will be the location we will
|
||||
# create all our application launchers in. The system application launcher will
|
||||
# be configured by our installer to look into this directory for available
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
name: anbox
|
||||
version: 1-dev
|
||||
version: 3
|
||||
version-script: |
|
||||
if [ "$SNAPCRAFT_GRADE" = "stable" ]; then
|
||||
echo $SNAPCRAFT_PROJECT_VERSION
|
||||
else
|
||||
echo $SNAPCRAFT_PROJECT_VERSION-$(git rev-parse --short HEAD)
|
||||
fi
|
||||
summary: Android in a Box
|
||||
description: |
|
||||
Runtime for Android applications which runs a full Android system
|
||||
|
|
@ -84,6 +90,7 @@ parts:
|
|||
# FIXME: Anbox currently has some paths with hard coded prefixes. Once
|
||||
# that is fixed we can avoid using a prefix here.
|
||||
- -DCMAKE_INSTALL_PREFIX:PATH=/usr
|
||||
- -DANBOX_VERSION=$SNAPCRAFT_PROJECT_VERSION
|
||||
build-packages:
|
||||
- build-essential
|
||||
- cmake
|
||||
|
|
@ -111,6 +118,7 @@ parts:
|
|||
- libprotobuf-dev
|
||||
- libproperties-cpp-dev
|
||||
- libsdl2-dev
|
||||
- libsdl2-image-dev
|
||||
- pkg-config
|
||||
- protobuf-compiler
|
||||
stage-packages:
|
||||
|
|
@ -123,4 +131,5 @@ parts:
|
|||
make test
|
||||
prime:
|
||||
- usr/bin/anbox
|
||||
- usr/share/anbox
|
||||
- usr/lib/*-linux-*/
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ include_directories(
|
|||
${DBUS_CPP_INCLUDE_DIRS}
|
||||
${DBUS_INCLUDE_DIRS}
|
||||
${SDL2_INCLUDE_DIRS}
|
||||
${SDL2_IMAGE_INCLUDE_DIRS}
|
||||
${PROPERTIES_CPP_INCLUDE_DIRS}
|
||||
${LXC_INCLUDE_DIRS}
|
||||
${MIRCLIENT_INCLUDE_DIRS}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
|
|
@ -41,6 +43,7 @@ protobuf_generate_cpp(
|
|||
|
||||
|
||||
add_library(anbox-protobuf
|
||||
STATIC
|
||||
${GENERATED_PROTOBUF_BRIDGE_SRCS}
|
||||
${GENERATED_PROTOBUF_BRIDGE_HDRS}
|
||||
${GENERATED_PROTOBUF_RPC_SRCS}
|
||||
|
|
@ -56,12 +59,15 @@ set(SOURCES
|
|||
anbox/utils.cpp
|
||||
anbox/cli.cpp
|
||||
anbox/runtime.cpp
|
||||
anbox/version.cpp
|
||||
anbox/daemon.cpp
|
||||
anbox/config.cpp
|
||||
anbox/not_reachable.cpp
|
||||
|
||||
anbox/build/version.cpp
|
||||
anbox/build/version.h.in
|
||||
|
||||
anbox/android/intent.cpp
|
||||
anbox/android/ip_config_builder.cpp
|
||||
|
||||
anbox/common/fd.cpp
|
||||
anbox/common/fd_sets.h
|
||||
|
|
@ -75,6 +81,7 @@ set(SOURCES
|
|||
anbox/common/loop_device.cpp
|
||||
anbox/common/loop_device_allocator.cpp
|
||||
anbox/common/mount_entry.cpp
|
||||
anbox/common/binary_writer.cpp
|
||||
|
||||
anbox/testing/gtest_utils.h
|
||||
|
||||
|
|
@ -203,11 +210,13 @@ set(SOURCES
|
|||
|
||||
anbox/utils/environment_file.cpp
|
||||
|
||||
anbox/ui/splash_screen.cpp
|
||||
|
||||
anbox/do_not_copy_or_move.h
|
||||
anbox/optional.h
|
||||
anbox/defer_action.h)
|
||||
|
||||
add_library(anbox-core ${SOURCES})
|
||||
add_library(anbox-core STATIC ${SOURCES})
|
||||
target_link_libraries(anbox-core
|
||||
${Boost_LDFLAGS}
|
||||
${Boost_LIBRARIES}
|
||||
|
|
@ -215,6 +224,8 @@ target_link_libraries(anbox-core
|
|||
${DBUS_CPP_LIBRARIES}
|
||||
${SDL2_LDFLAGS}
|
||||
${SDL2_LIBRARIES}
|
||||
${SDL2_IMAGE_LDFLAGS}
|
||||
${SDL2_IMAGE_LIBRARIES}
|
||||
${LXC_LDFLAGS}
|
||||
${LXC_LIBRARIES}
|
||||
${MIRCLIENT_LDFLAGS}
|
||||
|
|
|
|||
|
|
@ -21,17 +21,32 @@
|
|||
|
||||
namespace anbox {
|
||||
namespace android {
|
||||
bool Intent::valid() const {
|
||||
// At the moment we only support component+package for intents
|
||||
// (see android/service/android_api_skeleton.cpp for more details)
|
||||
return !(component.empty() && package.empty());
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const Intent &intent) {
|
||||
out << "["
|
||||
<< "action=" << intent.action << " "
|
||||
<< "uri=" << intent.uri << " "
|
||||
<< "type=" << intent.type << " "
|
||||
<< "flags=" << intent.flags << " "
|
||||
<< "package=" << intent.package << " "
|
||||
<< "component=" << intent.component << " "
|
||||
<< "categories=[ ";
|
||||
for (const auto &category : intent.categories) out << category << " ";
|
||||
out << "]]";
|
||||
out << "[";
|
||||
if (!intent.action.empty())
|
||||
out << " " << "action=" << intent.action << " ";
|
||||
if (!intent.uri.empty())
|
||||
out << " " << "uri=" << intent.uri << " ";
|
||||
if (!intent.type.empty())
|
||||
out << " " << "type=" << intent.type << " ";
|
||||
if (intent.flags > 0)
|
||||
out << " " << "flags=" << intent.flags << " ";
|
||||
if (!intent.package.empty())
|
||||
out << " " << "package=" << intent.package << " ";
|
||||
if (!intent.component.empty())
|
||||
out << "component=" << intent.component << " ";
|
||||
if (intent.categories.size() > 0) {
|
||||
out << "categories=[ ";
|
||||
for (const auto &category : intent.categories) out << category << " ";
|
||||
out << "] ";
|
||||
}
|
||||
out << "]";
|
||||
return out;
|
||||
}
|
||||
} // namespace android
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ struct Intent {
|
|||
std::string package;
|
||||
std::string component;
|
||||
std::vector<std::string> categories;
|
||||
|
||||
bool valid() const;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const Intent &intent);
|
||||
|
|
|
|||
114
src/anbox/android/ip_config_builder.cpp
Normal file
114
src/anbox/android/ip_config_builder.cpp
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (C) 2017 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/android/ip_config_builder.h"
|
||||
|
||||
#include <boost/endian/buffers.hpp>
|
||||
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace {
|
||||
constexpr const char *assignment_key{"ipAssignment"};
|
||||
constexpr const char *link_address_key{"linkAddress"};
|
||||
constexpr const char *gateway_key{"gateway"};
|
||||
constexpr const char *dns_key{"dns"};
|
||||
constexpr const char *id_key{"id"};
|
||||
constexpr const char *eos_key{"eos"};
|
||||
constexpr const char *assignment_static{"STATIC"};
|
||||
constexpr const char *assignment_dhcp{"DHCP"};
|
||||
constexpr const char *assignment_unknown{"UNKNOWN"};
|
||||
|
||||
constexpr const std::uint32_t is_default_gateway{0};
|
||||
constexpr const std::uint32_t gateway_is_present{1};
|
||||
|
||||
namespace aa = anbox::android;
|
||||
std::string assignment_to_string(const aa::IpConfigBuilder::Assignment &value) {
|
||||
switch (value) {
|
||||
case anbox::android::IpConfigBuilder::Assignment::Static:
|
||||
return assignment_static;
|
||||
break;
|
||||
case anbox::android::IpConfigBuilder::Assignment::DHCP:
|
||||
return assignment_dhcp;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return assignment_unknown;
|
||||
}
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
namespace android {
|
||||
std::size_t IpConfigBuilder::write(common::BinaryWriter &writer) {
|
||||
writer.set_byte_order(common::BinaryWriter::Order::Big);
|
||||
|
||||
// See http://androidxref.com/7.1.1_r6/xref/frameworks/base/services/core/java/com/android/server/net/IpConfigStore.java
|
||||
// for more details on the binary file format used here.
|
||||
|
||||
writer.write_uint32(static_cast<std::uint32_t>(version_));
|
||||
|
||||
writer.write_string_with_size(assignment_key);
|
||||
writer.write_string_with_size(assignment_to_string(assignment_));
|
||||
|
||||
writer.write_string_with_size(link_address_key);
|
||||
writer.write_string_with_size(link_.address);
|
||||
writer.write_uint32(link_.prefix_length);
|
||||
|
||||
writer.write_string_with_size(gateway_key);
|
||||
writer.write_uint32(is_default_gateway);
|
||||
writer.write_uint32(gateway_is_present);
|
||||
writer.write_string_with_size(gateway_);
|
||||
|
||||
writer.write_string_with_size(dns_key);
|
||||
for (const auto &server : dns_servers_)
|
||||
writer.write_string_with_size(server);
|
||||
|
||||
writer.write_string_with_size(id_key);
|
||||
writer.write_uint32(id_);
|
||||
|
||||
writer.write_string_with_size(eos_key);
|
||||
|
||||
return writer.bytes_written();
|
||||
}
|
||||
|
||||
void IpConfigBuilder::set_version(const Version &version) {
|
||||
version_ = version;
|
||||
}
|
||||
|
||||
void IpConfigBuilder::set_assignment(const Assignment &assignment) {
|
||||
assignment_ = assignment;
|
||||
}
|
||||
|
||||
void IpConfigBuilder::set_link_address(const std::string &address, uint32_t prefix_length) {
|
||||
link_.address = address;
|
||||
link_.prefix_length = prefix_length;
|
||||
}
|
||||
|
||||
void IpConfigBuilder::set_gateway(const std::string &gateway) {
|
||||
gateway_ = gateway;
|
||||
}
|
||||
|
||||
void IpConfigBuilder::set_dns_servers(const std::vector<std::string> &dns_servers) {
|
||||
dns_servers_ = dns_servers;
|
||||
}
|
||||
|
||||
void IpConfigBuilder::set_id(uint32_t id) {
|
||||
id_ = id;
|
||||
}
|
||||
} // namespace android
|
||||
} // namespace anbox
|
||||
66
src/anbox/android/ip_config_builder.h
Normal file
66
src/anbox/android/ip_config_builder.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Simon Fels <morphis@gravedo.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 3, as published
|
||||
* by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ANBOX_ANDROID_IPCONFIGBUILDER_H_
|
||||
#define ANBOX_ANDROID_IPCONFIGBUILDER_H_
|
||||
|
||||
#include "anbox/common/binary_writer.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace anbox {
|
||||
namespace android {
|
||||
class IpConfigBuilder {
|
||||
public:
|
||||
enum class Version : std::uint32_t {
|
||||
Version1 = 1,
|
||||
Version2 = 2,
|
||||
};
|
||||
|
||||
enum class Assignment {
|
||||
Static,
|
||||
DHCP,
|
||||
};
|
||||
|
||||
IpConfigBuilder() = default;
|
||||
|
||||
std::size_t write(common::BinaryWriter &writer);
|
||||
|
||||
void set_version(const Version &version);
|
||||
void set_assignment(const Assignment &assignment);
|
||||
void set_link_address(const std::string &address, std::uint32_t prefix_length);
|
||||
void set_gateway(const std::string &gateway);
|
||||
void set_dns_servers(const std::vector<std::string> &dns_servers);
|
||||
void set_id(std::uint32_t id);
|
||||
|
||||
private:
|
||||
Version version_;
|
||||
Assignment assignment_;
|
||||
struct {
|
||||
std::string address;
|
||||
std::uint32_t prefix_length;
|
||||
} link_;
|
||||
std::string gateway_;
|
||||
std::vector<std::string> dns_servers_;
|
||||
std::uint32_t id_;
|
||||
};
|
||||
} // namespace android
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
#ifndef ANBOX_BRIDGE_PLATFORM_SERVER_H_
|
||||
#define ANBOX_BRIDGE_PLATFORM_SERVER_H_
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace google {
|
||||
|
|
|
|||
39
src/anbox/build/version.cpp
Normal file
39
src/anbox/build/version.cpp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) 2017 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/build/version.h"
|
||||
#include "anbox/utils.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace anbox {
|
||||
namespace build {
|
||||
static std::string init_version_string() {
|
||||
std::string v;
|
||||
if (!version_suffix || std::strlen(version_suffix) == 0)
|
||||
v = utils::string_format("%s", version);
|
||||
else
|
||||
v = utils::string_format("%s-%s", version, version_suffix);
|
||||
return v;
|
||||
}
|
||||
|
||||
std::string print_version() {
|
||||
static const std::string v{init_version_string()};
|
||||
return v;
|
||||
}
|
||||
} // namespace build
|
||||
} // namespace anbox
|
||||
|
|
@ -17,11 +17,22 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "anbox/version.h"
|
||||
#ifndef ANBOX_VERSION_H_
|
||||
#define ANBOX_VERSION_H_
|
||||
|
||||
void anbox::version(std::uint32_t& major, std::uint32_t& minor,
|
||||
std::uint32_t& patch) {
|
||||
major = anbox::build::version_major;
|
||||
minor = anbox::build::version_minor;
|
||||
patch = anbox::build::version_patch;
|
||||
}
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace anbox {
|
||||
namespace build {
|
||||
/// @brief version marks the version
|
||||
static constexpr const char *version{"@ANBOX_VERSION@"};
|
||||
/// @brief version_suffix is an additional suffix which can be amended to
|
||||
/// the major version number to indicate a dev build for example.
|
||||
static constexpr const char *version_suffix{"@ANBOX_VERSION_SUFFIX@"};
|
||||
/// @brief version queries the version of Anbox
|
||||
std::string print_version();
|
||||
} // namespace build
|
||||
} // namespace anbox
|
||||
|
||||
#endif // ANBOX_VERSION_H_
|
||||
|
|
@ -48,11 +48,22 @@ anbox::cmds::ContainerManager::ContainerManager()
|
|||
flag(cli::make_flag(cli::Name{"privileged"},
|
||||
cli::Description{"Run Android container in privileged mode"},
|
||||
privileged_));
|
||||
flag(cli::make_flag(cli::Name{"daemon"},
|
||||
cli::Description{"Mark service as being started as systemd daemon"},
|
||||
daemon_));
|
||||
|
||||
action([&](const cli::Command::Context&) {
|
||||
try {
|
||||
if (getuid() != 0) {
|
||||
ERROR("You're not running the container-manager as root. Generally you don't");
|
||||
if (!daemon_) {
|
||||
WARNING("You are running the container manager manually which is most likely not");
|
||||
WARNING("what you want. The container manager is normally started by systemd or");
|
||||
WARNING("another init system. If you still want to run the container-manager");
|
||||
WARNING("you can get rid of this warning by starting with the --daemon option.");
|
||||
WARNING("");
|
||||
}
|
||||
|
||||
if (geteuid() != 0) {
|
||||
ERROR("You are not running the container-manager as root. Generally you don't");
|
||||
ERROR("want to run the container-manager manually unless you're a developer");
|
||||
ERROR("as it is started by the init system of your operating system.");
|
||||
return EXIT_FAILURE;
|
||||
|
|
@ -68,6 +79,9 @@ anbox::cmds::ContainerManager::ContainerManager()
|
|||
if (!data_path_.empty())
|
||||
SystemConfiguration::instance().set_data_path(data_path_);
|
||||
|
||||
if (!fs::exists(data_path_))
|
||||
fs::create_directories(data_path_);
|
||||
|
||||
if (!setup_mounts())
|
||||
return EXIT_FAILURE;
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ class ContainerManager : public cli::CommandWithFlagsAndAction {
|
|||
std::shared_ptr<common::LoopDevice> android_img_loop_dev_;
|
||||
std::vector<std::shared_ptr<common::MountEntry>> mounts_;
|
||||
bool privileged_ = false;
|
||||
bool daemon_ = false;
|
||||
};
|
||||
} // namespace cmds
|
||||
} // namespace anbox
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
#include "anbox/common/wait_handle.h"
|
||||
#include "anbox/dbus/stub/application_manager.h"
|
||||
#include "anbox/common/dispatcher.h"
|
||||
#include "anbox/ui/splash_screen.h"
|
||||
#include "anbox/config.h"
|
||||
#include "anbox/runtime.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
|
|
@ -26,12 +28,31 @@
|
|||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "core/posix/exec.h"
|
||||
#include "core/posix/fork.h"
|
||||
#include "core/posix/signal.h"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace {
|
||||
const boost::posix_time::seconds max_wait_timeout{30};
|
||||
const boost::posix_time::seconds max_wait_timeout{240};
|
||||
const int max_restart_attempts{3};
|
||||
const std::chrono::seconds restart_interval{5};
|
||||
}
|
||||
|
||||
bool anbox::cmds::Launch::try_launch_activity(const std::shared_ptr<dbus::stub::ApplicationManager> &stub) {
|
||||
try {
|
||||
DEBUG("Sending launch intent %s to Android ..", intent_);
|
||||
stub->launch(intent_, graphics::Rect::Invalid, stack_);
|
||||
} catch (const std::exception &err) {
|
||||
ERROR("Failed to launch activity: %s", err.what());
|
||||
return false;
|
||||
} catch (...) {
|
||||
ERROR("Failed to launch activity");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
anbox::cmds::Launch::Launch()
|
||||
|
|
@ -58,6 +79,11 @@ anbox::cmds::Launch::Launch()
|
|||
stack_));
|
||||
|
||||
action([this](const cli::Command::Context&) {
|
||||
if (!intent_.valid()) {
|
||||
ERROR("The intent you provided is invalid. Please provide a correct launch intent.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
auto trap = core::posix::trap_signals_for_process({core::posix::Signal::sig_term, core::posix::Signal::sig_int});
|
||||
trap->signal_raised().connect([trap](const core::posix::Signal& signal) {
|
||||
INFO("Signal %i received. Good night.", static_cast<int>(signal));
|
||||
|
|
@ -69,42 +95,95 @@ anbox::cmds::Launch::Launch()
|
|||
auto bus = std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::session);
|
||||
bus->install_executor(core::dbus::asio::make_executor(bus, rt->service()));
|
||||
|
||||
const auto snap_path = utils::get_env_value("SNAP");
|
||||
if (!snap_path.empty()) {
|
||||
const auto resource_path = fs::path(snap_path) / "usr" / "share" / "anbox";
|
||||
SystemConfiguration::instance().set_resource_path(resource_path);
|
||||
}
|
||||
|
||||
std::shared_ptr<ui::SplashScreen> ss;
|
||||
|
||||
// Instead of relying on the user session init system to start our
|
||||
// session manager process we also attempt to start it on our own
|
||||
// if not already running. This will help to mitigate problems with
|
||||
// a crashing or a not yet started session manager instance.
|
||||
std::shared_ptr<dbus::stub::ApplicationManager> stub;
|
||||
try {
|
||||
stub = dbus::stub::ApplicationManager::create_for_bus(bus);
|
||||
} catch (...) {
|
||||
ERROR("Anbox session manager service isn't running!");
|
||||
for (auto n = 0; n < max_restart_attempts; n++) {
|
||||
try {
|
||||
stub = dbus::stub::ApplicationManager::create_for_bus(bus);
|
||||
break;
|
||||
} catch (std::exception &err) {
|
||||
WARNING("Anbox session manager service isn't running, trying to start it.");
|
||||
|
||||
// Give us a splash screen as long as we're trying to connect
|
||||
// with the session manager so the user knows something is
|
||||
// happening after he started Anbox.
|
||||
if (!ss)
|
||||
ss = std::make_shared<ui::SplashScreen>();
|
||||
|
||||
std::vector<std::string> args = {"session-manager"};
|
||||
|
||||
std::map<std::string,std::string> env;
|
||||
core::posix::this_process::env::for_each([&](const std::string &name, const std::string &value) {
|
||||
env.insert({name, value});
|
||||
});
|
||||
|
||||
const auto exe_path = utils::process_get_exe_path(::getpid());
|
||||
if (!fs::exists(exe_path)) {
|
||||
ERROR("Can't find correct anbox executable to run. Found %s but does not exist", exe_path);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
try {
|
||||
auto flags = core::posix::StandardStream::stdout | core::posix::StandardStream::stderr;
|
||||
// If we have logging enable in debug mode then we allow the child process
|
||||
// to print to stdout/stderr too.
|
||||
if (Log().GetSeverity() == Logger::Severity::kDebug)
|
||||
flags = core::posix::StandardStream::empty;
|
||||
auto child = core::posix::fork([&]() {
|
||||
auto grandchild = core::posix::exec(exe_path, args, env, flags);
|
||||
grandchild.dont_kill_on_cleanup();
|
||||
return core::posix::exit::Status::success;
|
||||
}, flags);
|
||||
|
||||
// We don't wait for the grandchild but the child as we use double forking
|
||||
// here to break through the process hierarchy and make the grandchild a
|
||||
// direct child of the init process so it keeps running on its own and
|
||||
// indepent of our short living process here.
|
||||
child.wait_for(core::posix::wait::Flags::untraced);
|
||||
|
||||
DEBUG("Started session manager, will now try to connect ..");
|
||||
}
|
||||
catch (...) {
|
||||
ERROR("Failed to start session manager instance");
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(restart_interval);
|
||||
}
|
||||
}
|
||||
|
||||
if (!stub) {
|
||||
ERROR("Couldn't get a connection with the session manager");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
auto dispatcher = anbox::common::create_dispatcher_for_runtime(rt);
|
||||
|
||||
bool success = false;
|
||||
|
||||
auto dispatcher = anbox::common::create_dispatcher_for_runtime(rt);
|
||||
dispatcher->dispatch([&]() {
|
||||
if (stub->ready()) {
|
||||
try {
|
||||
stub->launch(intent_, graphics::Rect::Invalid, stack_);
|
||||
success = true;
|
||||
} catch (std::exception &err) {
|
||||
ERROR("err %s", err.what());
|
||||
}
|
||||
ss.reset();
|
||||
success = try_launch_activity(stub);
|
||||
trap->stop();
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG("Android hasn't fully booted yet. Waiting a bit..");
|
||||
DEBUG("Android hasn't fully booted yet. Waiting a bit ..");
|
||||
|
||||
stub->ready().changed().connect([&](bool ready) {
|
||||
if (!ready)
|
||||
return;
|
||||
try {
|
||||
stub->launch(intent_, graphics::Rect::Invalid, stack_);
|
||||
success = true;
|
||||
} catch (std::exception &err) {
|
||||
ERROR("Failed to launch activity: %s", err.what());
|
||||
success = false;
|
||||
}
|
||||
ss.reset();
|
||||
success = try_launch_activity(stub);
|
||||
trap->stop();
|
||||
});
|
||||
});
|
||||
|
|
@ -112,8 +191,10 @@ anbox::cmds::Launch::Launch()
|
|||
boost::asio::deadline_timer timer(rt->service());
|
||||
timer.expires_from_now(max_wait_timeout);
|
||||
timer.async_wait([&](const boost::system::error_code&) {
|
||||
WARNING("Stop waiting as we're already waiting for too long. Something is wrong");
|
||||
WARNING("with your setup and the container may have failed to boot.");
|
||||
WARNING("Stopped waiting as we've already waited for too long. Something");
|
||||
WARNING("is wrong with your setup or the container has failed to boot.");
|
||||
WARNING("If you think you found a bug please don't hesitate to file on");
|
||||
WARNING("at https://github.com/anbox/anbox/issues/new");
|
||||
trap->stop();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <memory>
|
||||
|
||||
#include "anbox/android/intent.h"
|
||||
#include "anbox/dbus/stub/application_manager.h"
|
||||
#include "anbox/wm/stack.h"
|
||||
#include "anbox/cli.h"
|
||||
|
||||
|
|
@ -33,6 +34,8 @@ class Launch : public cli::CommandWithFlagsAndAction {
|
|||
Launch();
|
||||
|
||||
private:
|
||||
bool try_launch_activity(const std::shared_ptr<dbus::stub::ApplicationManager> &stub);
|
||||
|
||||
android::Intent intent_;
|
||||
wm::Stack::Id stack_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -27,12 +27,17 @@
|
|||
#include "anbox/bridge/android_api_stub.h"
|
||||
#include "anbox/bridge/platform_api_skeleton.h"
|
||||
#include "anbox/bridge/platform_message_processor.h"
|
||||
#include "anbox/graphics/gl_renderer_server.h"
|
||||
|
||||
namespace {
|
||||
std::istream& operator>>(std::istream& in, anbox::graphics::GLRendererServer::Config::Driver& driver);
|
||||
}
|
||||
|
||||
#include "anbox/cmds/session_manager.h"
|
||||
#include "anbox/common/dispatcher.h"
|
||||
#include "anbox/config.h"
|
||||
#include "anbox/container/client.h"
|
||||
#include "anbox/dbus/skeleton/service.h"
|
||||
#include "anbox/graphics/gl_renderer_server.h"
|
||||
#include "anbox/input/manager.h"
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/network/published_socket_connector.h"
|
||||
|
|
@ -106,6 +111,12 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory)
|
|||
flag(cli::make_flag(cli::Name{"window-size"},
|
||||
cli::Description{"Size of the window in single window mode, e.g. --window-size=1024,768"},
|
||||
window_size_));
|
||||
flag(cli::make_flag(cli::Name{"standalone"},
|
||||
cli::Description{"Prevents the Container Manager from starting the default container (Experimental)"},
|
||||
standalone_));
|
||||
flag(cli::make_flag(cli::Name{"experimental"},
|
||||
cli::Description{"Allows users to use experimental features"},
|
||||
experimental_));
|
||||
|
||||
action([this](const cli::Command::Context &) {
|
||||
auto trap = core::posix::trap_signals_for_process(
|
||||
|
|
@ -115,6 +126,11 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory)
|
|||
trap->stop();
|
||||
});
|
||||
|
||||
if (standalone_ && !experimental_) {
|
||||
ERROR("Experimental features selected, but --experimental flag not set");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!fs::exists("/dev/binder") || !fs::exists("/dev/ashmem")) {
|
||||
ERROR("Failed to start as either binder or ashmem kernel drivers are not loaded");
|
||||
return EXIT_FAILURE;
|
||||
|
|
@ -135,11 +151,13 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory)
|
|||
auto rt = Runtime::create();
|
||||
auto dispatcher = anbox::common::create_dispatcher_for_runtime(rt);
|
||||
|
||||
container::Client container(rt);
|
||||
container.register_terminate_handler([&]() {
|
||||
WARNING("Lost connection to container manager, terminating.");
|
||||
trap->stop();
|
||||
});
|
||||
if (!standalone_) {
|
||||
container_ = std::make_shared<container::Client>(rt);
|
||||
container_->register_terminate_handler([&]() {
|
||||
WARNING("Lost connection to container manager, terminating.");
|
||||
trap->stop();
|
||||
});
|
||||
}
|
||||
|
||||
auto input_manager = std::make_shared<input::Manager>(rt);
|
||||
|
||||
|
|
@ -159,8 +177,6 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory)
|
|||
display_frame = window_size_;
|
||||
|
||||
auto policy = std::make_shared<ubuntu::PlatformPolicy>(input_manager, display_frame, single_window_);
|
||||
// FIXME this needs to be removed and solved differently behind the scenes
|
||||
registerDisplayManager(policy);
|
||||
|
||||
auto app_db = std::make_shared<application::Database>();
|
||||
|
||||
|
|
@ -213,7 +229,8 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory)
|
|||
}));
|
||||
|
||||
container::Configuration container_configuration;
|
||||
container_configuration.bind_mounts = {
|
||||
if (!standalone_) {
|
||||
container_configuration.bind_mounts = {
|
||||
{qemu_pipe_connector->socket_file(), "/dev/qemu_pipe"},
|
||||
{bridge_connector->socket_file(), "/dev/anbox_bridge"},
|
||||
{audio_server->socket_file(), "/dev/anbox_audio"},
|
||||
|
|
@ -221,9 +238,10 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory)
|
|||
{"/dev/binder", "/dev/binder"},
|
||||
{"/dev/ashmem", "/dev/ashmem"},
|
||||
{"/dev/fuse", "/dev/fuse"},
|
||||
};
|
||||
};
|
||||
|
||||
dispatcher->dispatch([&]() { container.start(container_configuration); });
|
||||
dispatcher->dispatch([&]() { container_->start(container_configuration); });
|
||||
}
|
||||
|
||||
auto bus = bus_factory_();
|
||||
bus->install_executor(core::dbus::asio::make_executor(bus, rt->service()));
|
||||
|
|
@ -233,9 +251,11 @@ anbox::cmds::SessionManager::SessionManager(const BusFactory &bus_factory)
|
|||
rt->start();
|
||||
trap->run();
|
||||
|
||||
// Stop the container which should close all open connections we have on
|
||||
// our side and should terminate all services.
|
||||
container.stop();
|
||||
if (!standalone_) {
|
||||
// Stop the container which should close all open connections we have on
|
||||
// our side and should terminate all services.
|
||||
container_->stop();
|
||||
}
|
||||
|
||||
rt->stop();
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@
|
|||
#include "anbox/graphics/rect.h"
|
||||
|
||||
namespace anbox {
|
||||
namespace container {
|
||||
class Client;
|
||||
} // namespace container
|
||||
namespace cmds {
|
||||
class SessionManager : public cli::CommandWithFlagsAndAction {
|
||||
public:
|
||||
|
|
@ -40,11 +43,14 @@ class SessionManager : public cli::CommandWithFlagsAndAction {
|
|||
SessionManager(const BusFactory& bus_factory = session_bus_factory());
|
||||
|
||||
private:
|
||||
std::shared_ptr<container::Client> container_;
|
||||
BusFactory bus_factory_;
|
||||
std::string desktop_file_hint_;
|
||||
graphics::GLRendererServer::Config::Driver gles_driver_;
|
||||
bool single_window_ = false;
|
||||
graphics::Rect window_size_;
|
||||
bool standalone_ = false;
|
||||
bool experimental_ = false;
|
||||
};
|
||||
} // namespace cmds
|
||||
} // namespace anbox
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@
|
|||
#include "anbox/graphics/emugl/RenderApi.h"
|
||||
#include "anbox/graphics/emugl/DispatchTables.h"
|
||||
#include "anbox/utils/environment_file.h"
|
||||
#include "anbox/version.h"
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/version.h"
|
||||
|
||||
#include "anbox/build/version.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
|
@ -34,9 +34,12 @@ namespace fs = boost::filesystem;
|
|||
|
||||
namespace {
|
||||
constexpr const char *os_release_path{"/etc/os-release"};
|
||||
constexpr const char *host_os_release_path{"/var/lib/snapd/hostfs/etc/os-release"};
|
||||
constexpr const char *proc_version_path{"/proc/version"};
|
||||
constexpr const char *binder_path{"/dev/binder"};
|
||||
constexpr const char *ashmem_path{"/dev/ashmem"};
|
||||
constexpr const char *os_release_name{"NAME"};
|
||||
constexpr const char *os_release_version{"VERSION"};
|
||||
|
||||
class SystemInformation {
|
||||
public:
|
||||
|
|
@ -50,12 +53,15 @@ class SystemInformation {
|
|||
std::stringstream s;
|
||||
|
||||
s << "version: "
|
||||
<< anbox::utils::string_format("%d.%d.%d",
|
||||
anbox::build::version_major,
|
||||
anbox::build::version_minor,
|
||||
anbox::build::version_patch)
|
||||
<< anbox::build::print_version()
|
||||
<< std::endl;
|
||||
|
||||
if (anbox::utils::is_env_set("SNAP_REVISION")) {
|
||||
s << "snap-revision: "
|
||||
<< anbox::utils::get_env_value("SNAP_REVISION")
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
s << "os:" << std::endl
|
||||
<< " name: " << os_info_.name << std::endl
|
||||
<< " version: " << os_info_.version << std::endl
|
||||
|
|
@ -96,15 +102,19 @@ class SystemInformation {
|
|||
|
||||
private:
|
||||
void collect_os_info() {
|
||||
os_info_.snap_based = (getenv("SNAP") != nullptr);
|
||||
if (fs::exists(os_release_path)) {
|
||||
anbox::utils::EnvironmentFile os_release(os_release_path);
|
||||
os_info_.name = os_release.value("NAME");
|
||||
os_info_.version = os_release.value("VERSION");
|
||||
} else if (os_info_.snap_based) {
|
||||
// As we can't read /etc/os-release and we're snap-based this is the best we can guess
|
||||
os_info_.name = "Ubuntu";
|
||||
os_info_.version = "16";
|
||||
os_info_.snap_based = !anbox::utils::get_env_value("SNAP").empty();
|
||||
fs::path path = os_release_path;
|
||||
// If we're running from within a snap the best we can do is to
|
||||
// access the hostfs and read the os-release file from there.
|
||||
if (os_info_.snap_based && fs::exists(host_os_release_path))
|
||||
path = host_os_release_path;
|
||||
|
||||
// Double check that there aren't any permission errors when trying
|
||||
// to access the file (e.g. because of snap confinement)
|
||||
if (fs::exists(path)) {
|
||||
anbox::utils::EnvironmentFile os_release(path);
|
||||
os_info_.name = os_release.value(os_release_name);
|
||||
os_info_.version = os_release.value(os_release_version);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,16 +18,15 @@
|
|||
*/
|
||||
|
||||
#include "anbox/cmds/version.h"
|
||||
#include "anbox/version.h"
|
||||
#include "anbox/build/version.h"
|
||||
#include "anbox/utils.h"
|
||||
|
||||
anbox::cmds::Version::Version()
|
||||
: CommandWithFlagsAndAction{
|
||||
cli::Name{"version"}, cli::Usage{"version"},
|
||||
cli::Description{"print the version of the daemon"}} {
|
||||
action([](const cli::Command::Context& ctxt) {
|
||||
std::uint32_t major, minor, patch;
|
||||
anbox::version(major, minor, patch);
|
||||
ctxt.cout << "anbox " << major << "." << minor << "." << patch << std::endl;
|
||||
ctxt.cout << "anbox " << build::print_version() << std::endl;
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
106
src/anbox/common/binary_writer.cpp
Normal file
106
src/anbox/common/binary_writer.cpp
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Thomas Voss <thomas.voss.bochum@gmail.com>
|
||||
* 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/common/binary_writer.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/endian/buffers.hpp>
|
||||
|
||||
namespace {
|
||||
bool is_little_endian() {
|
||||
static const std::uint32_t v = 1;
|
||||
return (*reinterpret_cast<const std::uint8_t*>(&v) == 1);
|
||||
}
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
namespace common {
|
||||
|
||||
BinaryWriter::BinaryWriter(std::vector<std::uint8_t>::iterator begin,
|
||||
std::vector<std::uint8_t>::iterator end) :
|
||||
begin_{begin}, current_{begin}, end_{end},
|
||||
byte_order_{is_little_endian() ? Order::Little : Order::Big} {}
|
||||
|
||||
void BinaryWriter::set_byte_order(Order order) {
|
||||
byte_order_ = order;
|
||||
}
|
||||
|
||||
void BinaryWriter::write_uint16(std::uint16_t value) {
|
||||
if (current_ + sizeof(value) > end_)
|
||||
throw std::out_of_range{"Write buffer exhausted"};
|
||||
|
||||
std::uint16_t v = value;
|
||||
switch (byte_order_) {
|
||||
case Order::Big:
|
||||
v = boost::endian::native_to_big(value);
|
||||
break;
|
||||
case Order::Little:
|
||||
v = boost::endian::native_to_little(value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
*reinterpret_cast<std::uint16_t*>(&(*current_)) = v;
|
||||
current_ += sizeof(v);
|
||||
}
|
||||
|
||||
void BinaryWriter::write_uint32(std::uint32_t value) {
|
||||
if (current_ + sizeof(value) > end_)
|
||||
throw std::out_of_range{"Write buffer exhausted"};
|
||||
|
||||
std::uint32_t v = value;
|
||||
switch (byte_order_) {
|
||||
case Order::Big:
|
||||
v = boost::endian::native_to_big(value);
|
||||
break;
|
||||
case Order::Little:
|
||||
v = boost::endian::native_to_little(value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
*reinterpret_cast<std::uint32_t*>(&(*current_)) = v;
|
||||
current_ += sizeof(v);
|
||||
}
|
||||
|
||||
void BinaryWriter::write_string(const char *s, std::size_t size) {
|
||||
if (current_ + size > end_)
|
||||
throw std::out_of_range{"Write buffer exhausted"};
|
||||
|
||||
memcpy(&(*current_), s, size);
|
||||
current_ += size;
|
||||
}
|
||||
|
||||
void BinaryWriter::write_string_with_size(const std::string &str) {
|
||||
write_string_with_size(str.c_str(), str.length());
|
||||
}
|
||||
|
||||
void BinaryWriter::write_string_with_size(const char *s, std::size_t size) {
|
||||
write_uint16(size);
|
||||
write_string(s, size);
|
||||
}
|
||||
|
||||
std::size_t BinaryWriter::bytes_written() const {
|
||||
return current_ - begin_;
|
||||
}
|
||||
} // namespace common
|
||||
} // namespace anbox
|
||||
57
src/anbox/common/binary_writer.h
Normal file
57
src/anbox/common/binary_writer.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Thomas Voss <thomas.voss.bochum@gmail.com>
|
||||
* 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_COMMON_BINARY_WRITER_H_
|
||||
#define ANBOX_COMMON_BINARY_WRITER_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace anbox {
|
||||
namespace common {
|
||||
class BinaryWriter {
|
||||
public:
|
||||
enum class Order {
|
||||
Big,
|
||||
Little,
|
||||
};
|
||||
|
||||
explicit BinaryWriter(std::vector<std::uint8_t>::iterator begin_,
|
||||
std::vector<std::uint8_t>::iterator end_);
|
||||
|
||||
void set_byte_order(Order order);
|
||||
|
||||
void write_uint16(std::uint16_t value);
|
||||
void write_uint32(std::uint32_t value);
|
||||
void write_string(const char *s, std::size_t size);
|
||||
void write_string_with_size(const std::string &str);
|
||||
void write_string_with_size(const char *s, std::size_t size);
|
||||
|
||||
std::size_t bytes_written() const;
|
||||
|
||||
private:
|
||||
std::vector<std::uint8_t>::iterator begin_;
|
||||
std::vector<std::uint8_t>::iterator current_;
|
||||
std::vector<std::uint8_t>::iterator end_;
|
||||
Order byte_order_;
|
||||
};
|
||||
} // namespace common
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
|
|
@ -41,6 +41,10 @@ void anbox::SystemConfiguration::set_data_path(const std::string &path) {
|
|||
data_path = path;
|
||||
}
|
||||
|
||||
void anbox::SystemConfiguration::set_resource_path(const fs::path &path) {
|
||||
resource_path = path;
|
||||
}
|
||||
|
||||
fs::path anbox::SystemConfiguration::data_dir() const {
|
||||
return data_path;
|
||||
}
|
||||
|
|
@ -76,6 +80,10 @@ std::string anbox::SystemConfiguration::application_item_dir() const {
|
|||
return dir.string();
|
||||
}
|
||||
|
||||
std::string anbox::SystemConfiguration::resource_dir() const {
|
||||
return resource_path.string();
|
||||
}
|
||||
|
||||
anbox::SystemConfiguration& anbox::SystemConfiguration::instance() {
|
||||
static SystemConfiguration config;
|
||||
return config;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ class SystemConfiguration {
|
|||
virtual ~SystemConfiguration() = default;
|
||||
|
||||
void set_data_path(const std::string &path);
|
||||
void set_resource_path(const boost::filesystem::path &path);
|
||||
|
||||
boost::filesystem::path data_dir() const;
|
||||
std::string rootfs_dir() const;
|
||||
|
|
@ -40,11 +41,13 @@ class SystemConfiguration {
|
|||
std::string container_socket_path() const;
|
||||
std::string input_device_dir() const;
|
||||
std::string application_item_dir() const;
|
||||
std::string resource_dir() const;
|
||||
|
||||
protected:
|
||||
SystemConfiguration() = default;
|
||||
|
||||
boost::filesystem::path data_path = "/var/lib/anbox";
|
||||
boost::filesystem::path resource_path = "/usr/share/anbox";
|
||||
|
||||
};
|
||||
} // namespace anbox
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "anbox/android/ip_config_builder.h"
|
||||
#include "anbox/container/lxc_container.h"
|
||||
#include "anbox/config.h"
|
||||
#include "anbox/logger.h"
|
||||
|
|
@ -22,6 +23,7 @@
|
|||
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <fstream>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
|
@ -30,9 +32,20 @@
|
|||
#include <sys/prctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace {
|
||||
constexpr unsigned int unprivileged_user_id{100000};
|
||||
constexpr const char *default_container_ip_address{"192.168.250.2"};
|
||||
constexpr const std::uint32_t default_container_ip_prefix_length{24};
|
||||
constexpr const char *default_host_ip_address{"192.168.250.1"};
|
||||
constexpr const char *default_dns_server{"8.8.8.8"};
|
||||
}
|
||||
|
||||
namespace anbox {
|
||||
namespace container {
|
||||
LxcContainer::LxcContainer(bool privileged, const network::Credentials &creds)
|
||||
|
|
@ -49,8 +62,7 @@ LxcContainer::~LxcContainer() {
|
|||
}
|
||||
|
||||
void LxcContainer::setup_id_maps() {
|
||||
// FIXME make these id sets configurable
|
||||
const auto base_id = 100000;
|
||||
const auto base_id = unprivileged_user_id;
|
||||
const auto max_id = 65536;
|
||||
|
||||
set_config_item("lxc.id_map",
|
||||
|
|
@ -76,6 +88,75 @@ void LxcContainer::setup_id_maps() {
|
|||
max_id - creds_.gid() - 1));
|
||||
}
|
||||
|
||||
void LxcContainer::setup_network() {
|
||||
if (!fs::exists("/sys/class/net/anbox0")) {
|
||||
WARNING("Anbox bridge interface 'anbox0' doesn't exist. Network functionality will not be available");
|
||||
return;
|
||||
}
|
||||
|
||||
set_config_item("lxc.network.type", "veth");
|
||||
set_config_item("lxc.network.flags", "up");
|
||||
set_config_item("lxc.network.link", "anbox0");
|
||||
|
||||
// Instead of relying on DHCP we will give Android a static IP configuration
|
||||
// for the virtual ethernet interface LXC creates for us. This will be bridged
|
||||
// to the host and will allows us to have reliable network connectivity and
|
||||
// not depend on any other system service.
|
||||
|
||||
android::IpConfigBuilder ip_conf;
|
||||
ip_conf.set_version(android::IpConfigBuilder::Version::Version2);
|
||||
ip_conf.set_assignment(android::IpConfigBuilder::Assignment::Static);
|
||||
ip_conf.set_link_address(default_container_ip_address, default_container_ip_prefix_length);
|
||||
ip_conf.set_gateway(default_host_ip_address);
|
||||
ip_conf.set_dns_servers({default_dns_server});
|
||||
ip_conf.set_id(0);
|
||||
|
||||
std::vector<std::uint8_t> buffer(512);
|
||||
common::BinaryWriter writer(buffer.begin(), buffer.end());
|
||||
const auto size = ip_conf.write(writer);
|
||||
|
||||
const auto data_ethernet_path = fs::path("data") / "misc" / "ethernet";
|
||||
const auto ip_conf_dir = SystemConfiguration::instance().data_dir() / data_ethernet_path;
|
||||
if (!fs::exists(ip_conf_dir))
|
||||
fs::create_directories(ip_conf_dir);
|
||||
|
||||
// We have to walk through the created directory hierachy now and
|
||||
// ensure the permissions are set correctly. Otherwise the Android
|
||||
// system will fail to boot as it isn't allowed to write anything
|
||||
// into these directories. As previous versions of Anbox which were
|
||||
// published to our users did this incorrectly we need to check on
|
||||
// every startup if those directories are still owned by root and
|
||||
// if they are we move them over to the unprivileged user.
|
||||
auto path = SystemConfiguration::instance().data_dir();
|
||||
for (auto iter = data_ethernet_path.begin(); iter != data_ethernet_path.end(); iter++) {
|
||||
path /= *iter;
|
||||
|
||||
struct stat st;
|
||||
if (stat(path.c_str(), &st) < 0) {
|
||||
WARNING("Cannot retrieve permissions of path %s", path);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (st.st_uid != 0 && st.st_gid != 0)
|
||||
continue;
|
||||
|
||||
if (::chown(path.c_str(), unprivileged_user_id, unprivileged_user_id) < 0)
|
||||
WARNING("Failed to set owner for path '%s'", path);
|
||||
}
|
||||
|
||||
const auto ip_conf_path = ip_conf_dir / "ipconfig.txt";
|
||||
if (fs::exists(ip_conf_path))
|
||||
fs::remove(ip_conf_path);
|
||||
|
||||
std::ofstream f(ip_conf_path.string(), std::ofstream::binary);
|
||||
if (f.is_open()) {
|
||||
f.write(reinterpret_cast<const char*>(buffer.data()), size);
|
||||
f.close();
|
||||
} else {
|
||||
ERROR("Failed to write IP configuration. Network functionality will not be available.");
|
||||
}
|
||||
}
|
||||
|
||||
void LxcContainer::start(const Configuration &configuration) {
|
||||
if (getuid() != 0)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("You have to start the container as root"));
|
||||
|
|
@ -131,11 +212,7 @@ void LxcContainer::start(const Configuration &configuration) {
|
|||
const auto log_path = SystemConfiguration::instance().log_dir();
|
||||
set_config_item("lxc.logfile", utils::string_format("%s/container.log", log_path).c_str());
|
||||
|
||||
if (fs::exists("/sys/class/net/anboxbr0")) {
|
||||
set_config_item("lxc.network.type", "veth");
|
||||
set_config_item("lxc.network.flags", "up");
|
||||
set_config_item("lxc.network.link", "anboxbr0");
|
||||
}
|
||||
setup_network();
|
||||
|
||||
#if 0
|
||||
// Android uses namespaces as well so we have to allow nested namespaces for LXC
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ class LxcContainer : public Container {
|
|||
private:
|
||||
void set_config_item(const std::string &key, const std::string &value);
|
||||
void setup_id_maps();
|
||||
void setup_network();
|
||||
|
||||
State state_;
|
||||
lxc_container *container_;
|
||||
|
|
|
|||
|
|
@ -25,10 +25,8 @@ namespace skeleton {
|
|||
std::shared_ptr<Service> Service::create_for_bus(
|
||||
const core::dbus::Bus::Ptr &bus,
|
||||
const std::shared_ptr<anbox::application::Manager> &application_manager) {
|
||||
auto service = core::dbus::Service::add_service(
|
||||
bus, anbox::dbus::interface::Service::name());
|
||||
auto object =
|
||||
service->add_object_for_path(anbox::dbus::interface::Service::path());
|
||||
auto service = core::dbus::Service::add_service(bus, anbox::dbus::interface::Service::name());
|
||||
auto object = service->add_object_for_path(anbox::dbus::interface::Service::path());
|
||||
return std::make_shared<Service>(bus, service, object, application_manager);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace dbus {
|
|||
namespace stub {
|
||||
std::shared_ptr<ApplicationManager> ApplicationManager::create_for_bus(const core::dbus::Bus::Ptr &bus) {
|
||||
auto service = core::dbus::Service::use_service_or_throw_if_not_available(bus, anbox::dbus::interface::Service::name());
|
||||
auto object = service->add_object_for_path(anbox::dbus::interface::Service::path());
|
||||
auto object = service->object_for_path(anbox::dbus::interface::Service::path());
|
||||
return std::make_shared<ApplicationManager>(bus, service, object);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,17 +13,16 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "ColorBuffer.h"
|
||||
|
||||
#include "DispatchTables.h"
|
||||
#include "RenderThreadInfo.h"
|
||||
#include "TextureDraw.h"
|
||||
#include "TextureResize.h"
|
||||
|
||||
#include "OpenGLESDispatch/EGLDispatch.h"
|
||||
|
||||
#include "anbox/graphics/emugl/ColorBuffer.h"
|
||||
#include "anbox/graphics/emugl/DispatchTables.h"
|
||||
#include "anbox/graphics/emugl/RenderThreadInfo.h"
|
||||
#include "anbox/graphics/emugl/TextureDraw.h"
|
||||
#include "anbox/graphics/emugl/TextureResize.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include "external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace {
|
||||
|
|
@ -35,22 +34,6 @@ inline void* SafePointerFromUInt(unsigned int handle) {
|
|||
return reinterpret_cast<void*>(static_cast<uintptr_t>(handle));
|
||||
}
|
||||
|
||||
inline unsigned int SafeUIntFromPointer(const void* ptr) {
|
||||
#if 1
|
||||
// Ignore the assert below to avoid crashing when running older
|
||||
// system images, which might have buggy encoder libraries. Print
|
||||
// an error message though.
|
||||
if (reinterpret_cast<uintptr_t>(ptr) != static_cast<unsigned int>(reinterpret_cast<uintptr_t>(ptr))) {
|
||||
WARNING("Bad generic pointer %p", ptr);
|
||||
}
|
||||
#else
|
||||
// Assertion error if the pointer contains a value that does not fit
|
||||
// in an unsigned integer!
|
||||
assert((uintptr_t)(ptr) == (unsigned int)(uintptr_t)(ptr));
|
||||
#endif
|
||||
return static_cast<unsigned int>(reinterpret_cast<uintptr_t>(ptr));
|
||||
}
|
||||
|
||||
// Lazily create and bind a framebuffer object to the current host context.
|
||||
// |fbo| is the address of the framebuffer object name.
|
||||
// |tex| is the name of a texture that is attached to the framebuffer object
|
||||
|
|
@ -251,7 +234,7 @@ void ColorBuffer::subUpdate(int x, int y, int width, int height,
|
|||
|
||||
bool ColorBuffer::blitFromCurrentReadBuffer() {
|
||||
RenderThreadInfo* tInfo = RenderThreadInfo::get();
|
||||
if (!tInfo->currContext.Ptr()) {
|
||||
if (!tInfo->currContext) {
|
||||
// no Current context
|
||||
return false;
|
||||
}
|
||||
|
|
@ -312,7 +295,7 @@ bool ColorBuffer::bindToTexture() {
|
|||
return false;
|
||||
}
|
||||
RenderThreadInfo* tInfo = RenderThreadInfo::get();
|
||||
if (!tInfo->currContext.Ptr()) {
|
||||
if (!tInfo->currContext) {
|
||||
return false;
|
||||
}
|
||||
if (tInfo->currContext->isGL2()) {
|
||||
|
|
@ -328,7 +311,7 @@ bool ColorBuffer::bindToRenderbuffer() {
|
|||
return false;
|
||||
}
|
||||
RenderThreadInfo* tInfo = RenderThreadInfo::get();
|
||||
if (!tInfo->currContext.Ptr()) {
|
||||
if (!tInfo->currContext) {
|
||||
return false;
|
||||
}
|
||||
if (tInfo->currContext->isGL2()) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <GLES/gl.h>
|
||||
#include "emugl/common/smart_ptr.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
|
@ -135,6 +134,6 @@ class ColorBuffer {
|
|||
TextureResize* m_resizer;
|
||||
};
|
||||
|
||||
typedef emugl::SmartPtr<ColorBuffer> ColorBufferPtr;
|
||||
typedef std::shared_ptr<ColorBuffer> ColorBufferPtr;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -17,22 +17,22 @@
|
|||
|
||||
#include "DisplayManager.h"
|
||||
|
||||
namespace {
|
||||
std::shared_ptr<DisplayManager> display_mgr;
|
||||
|
||||
class NullDisplayManager : public DisplayManager {
|
||||
public:
|
||||
DisplayInfo display_info() const override { return {1280, 720}; }
|
||||
};
|
||||
namespace anbox {
|
||||
namespace graphics {
|
||||
namespace emugl {
|
||||
std::shared_ptr<DisplayInfo> DisplayInfo::get() {
|
||||
static auto info = std::make_shared<DisplayInfo>();
|
||||
return info;
|
||||
}
|
||||
|
||||
DisplayManager::~DisplayManager() {}
|
||||
|
||||
std::shared_ptr<DisplayManager> DisplayManager::get() {
|
||||
if (!display_mgr) display_mgr = std::make_shared<NullDisplayManager>();
|
||||
return display_mgr;
|
||||
void DisplayInfo::set_resolution(const std::uint32_t &vertical, const std::uint32_t horizontal) {
|
||||
vertical_resolution_ = vertical;
|
||||
horizontal_resolution_ = horizontal;
|
||||
}
|
||||
|
||||
void registerDisplayManager(const std::shared_ptr<DisplayManager> &mgr) {
|
||||
display_mgr = mgr;
|
||||
}
|
||||
std::uint32_t DisplayInfo::vertical_resolution() const { return vertical_resolution_; }
|
||||
|
||||
std::uint32_t DisplayInfo::horizontal_resolution() const { return horizontal_resolution_; }
|
||||
} // namespace emugl
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
|
|
|||
|
|
@ -15,25 +15,32 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef DISPLAY_MANAGER_H_
|
||||
#define DISPLAY_MANAGER_H_
|
||||
#ifndef ANBOX_GRAPHICS_EMUGL_DISPLAY_INFO_H_
|
||||
#define ANBOX_GRAPHICS_EMUGL_DISPLAY_INFO_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
class DisplayManager {
|
||||
namespace anbox {
|
||||
namespace graphics {
|
||||
namespace emugl {
|
||||
class DisplayInfo {
|
||||
public:
|
||||
virtual ~DisplayManager();
|
||||
DisplayInfo() = default;
|
||||
|
||||
struct DisplayInfo {
|
||||
int horizontal_resolution;
|
||||
int vertical_resolution;
|
||||
};
|
||||
static std::shared_ptr<DisplayInfo> get();
|
||||
|
||||
virtual DisplayInfo display_info() const = 0;
|
||||
void set_resolution(const std::uint32_t &vertical, const std::uint32_t horizontal);
|
||||
|
||||
static std::shared_ptr<DisplayManager> get();
|
||||
std::uint32_t vertical_resolution() const;
|
||||
std::uint32_t horizontal_resolution() const;
|
||||
|
||||
private:
|
||||
std::uint32_t vertical_resolution_ = 1280;
|
||||
std::uint32_t horizontal_resolution_ = 720;
|
||||
};
|
||||
|
||||
void registerDisplayManager(const std::shared_ptr<DisplayManager> &mgr);
|
||||
} // namespace emugl
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -13,13 +13,14 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "ReadBuffer.h"
|
||||
|
||||
#include "anbox/graphics/emugl/ReadBuffer.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "anbox/logger.h"
|
||||
|
||||
ReadBuffer::ReadBuffer(size_t bufsize) {
|
||||
m_size = bufsize;
|
||||
m_buf = static_cast<unsigned char*>(malloc(m_size * sizeof(unsigned char)));
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#ifndef _READ_BUFFER_H
|
||||
#define _READ_BUFFER_H
|
||||
|
||||
#include "IOStream.h"
|
||||
#include "external/android-emugl/host/include/libOpenglRender/IOStream.h"
|
||||
|
||||
class ReadBuffer {
|
||||
public:
|
||||
|
|
@ -34,4 +34,5 @@ class ReadBuffer {
|
|||
size_t m_size;
|
||||
size_t m_validData;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,15 +14,14 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "RenderApi.h"
|
||||
#include "anbox/graphics/emugl/RenderApi.h"
|
||||
#include "anbox/graphics/emugl/DispatchTables.h"
|
||||
|
||||
#include "DispatchTables.h"
|
||||
#include "external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h"
|
||||
#include "external/android-emugl/host/include/OpenGLESDispatch/GLESv1Dispatch.h"
|
||||
#include "external/android-emugl/host/include/OpenGLESDispatch/GLESv2Dispatch.h"
|
||||
|
||||
#include "OpenGLESDispatch/EGLDispatch.h"
|
||||
#include "OpenGLESDispatch/GLESv1Dispatch.h"
|
||||
#include "OpenGLESDispatch/GLESv2Dispatch.h"
|
||||
|
||||
#include "emugl/common/crash_reporter.h"
|
||||
#include "external/android-emugl/shared/emugl/common/crash_reporter.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include "emugl/common/logging.h"
|
||||
#include "external/android-emugl/shared/emugl/common/logging.h"
|
||||
|
||||
typedef struct {
|
||||
logger_t coarse;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "RenderContext.h"
|
||||
|
||||
#include "anbox/graphics/emugl/RenderContext.h"
|
||||
|
||||
#include "OpenGLESDispatch/EGLDispatch.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -13,14 +13,16 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LIBRENDER_RENDER_CONTEXT_H
|
||||
#define _LIBRENDER_RENDER_CONTEXT_H
|
||||
|
||||
#include "GLDecoderContextData.h"
|
||||
#include "emugl/common/smart_ptr.h"
|
||||
#include "external/android-emugl/shared/OpenglCodecCommon/GLDecoderContextData.h"
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
// A class used to model a guest EGLContext. This simply wraps a host
|
||||
// EGLContext, associated with an GLDecoderContextData instance that is
|
||||
// used to store copies of guest-side arrays.
|
||||
|
|
@ -60,6 +62,6 @@ class RenderContext {
|
|||
GLDecoderContextData mContextData;
|
||||
};
|
||||
|
||||
typedef emugl::SmartPtr<RenderContext> RenderContextPtr;
|
||||
typedef std::shared_ptr<RenderContext> RenderContextPtr;
|
||||
|
||||
#endif // _LIBRENDER_RENDER_CONTEXT_H
|
||||
|
|
|
|||
|
|
@ -13,20 +13,20 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "RenderControl.h"
|
||||
|
||||
#include "ChecksumCalculatorThreadInfo.h"
|
||||
#include "DispatchTables.h"
|
||||
#include "DisplayManager.h"
|
||||
#include "RenderThreadInfo.h"
|
||||
#include "Renderer.h"
|
||||
#include "RendererConfig.h"
|
||||
|
||||
#include "OpenGLESDispatch/EGLDispatch.h"
|
||||
|
||||
#include "anbox/graphics/emugl/RenderControl.h"
|
||||
#include "anbox/graphics/emugl/DispatchTables.h"
|
||||
#include "anbox/graphics/emugl/DisplayManager.h"
|
||||
#include "anbox/graphics/emugl/RenderThreadInfo.h"
|
||||
#include "anbox/graphics/emugl/Renderer.h"
|
||||
#include "anbox/graphics/emugl/RendererConfig.h"
|
||||
#include "anbox/graphics/layer_composer.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include "external/android-emugl/shared/OpenglCodecCommon/ChecksumCalculatorThreadInfo.h"
|
||||
#include "external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h"
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -169,10 +169,10 @@ static EGLint rcGetFBParam(EGLint param) {
|
|||
|
||||
switch (param) {
|
||||
case FB_WIDTH:
|
||||
ret = DisplayManager::get()->display_info().horizontal_resolution;
|
||||
ret = static_cast<EGLint>(anbox::graphics::emugl::DisplayInfo::get()->vertical_resolution());
|
||||
break;
|
||||
case FB_HEIGHT:
|
||||
ret = DisplayManager::get()->display_info().vertical_resolution;
|
||||
ret = static_cast<EGLint>(anbox::graphics::emugl::DisplayInfo::get()->horizontal_resolution());
|
||||
break;
|
||||
case FB_XDPI:
|
||||
ret = 72; // XXX: should be implemented
|
||||
|
|
@ -360,12 +360,12 @@ int rcGetNumDisplays() {
|
|||
|
||||
int rcGetDisplayWidth(uint32_t display_id) {
|
||||
(void)display_id;
|
||||
return DisplayManager::get()->display_info().horizontal_resolution;
|
||||
return static_cast<int>(anbox::graphics::emugl::DisplayInfo::get()->vertical_resolution());
|
||||
}
|
||||
|
||||
int rcGetDisplayHeight(uint32_t display_id) {
|
||||
(void)display_id;
|
||||
return DisplayManager::get()->display_info().vertical_resolution;
|
||||
return static_cast<int>(anbox::graphics::emugl::DisplayInfo::get()->horizontal_resolution());
|
||||
}
|
||||
|
||||
int rcGetDisplayDpiX(uint32_t display_id) {
|
||||
|
|
|
|||
|
|
@ -13,9 +13,11 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _RENDER_CONTROL_H
|
||||
#define _RENDER_CONTROL_H
|
||||
|
||||
// Generated with emugl at build time
|
||||
#include "renderControl_dec.h"
|
||||
|
||||
#include <memory>
|
||||
|
|
|
|||
|
|
@ -13,32 +13,31 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "RenderThread.h"
|
||||
|
||||
#include "ReadBuffer.h"
|
||||
#include "RenderControl.h"
|
||||
#include "RenderThreadInfo.h"
|
||||
#include "Renderer.h"
|
||||
#include "TimeUtils.h"
|
||||
|
||||
#include "../../../shared/OpenglCodecCommon/ChecksumCalculatorThreadInfo.h"
|
||||
#include "OpenGLESDispatch/EGLDispatch.h"
|
||||
#include "OpenGLESDispatch/GLESv1Dispatch.h"
|
||||
#include "OpenGLESDispatch/GLESv2Dispatch.h"
|
||||
|
||||
#include "anbox/graphics/emugl/RenderThread.h"
|
||||
#include "anbox/graphics/emugl/ReadBuffer.h"
|
||||
#include "anbox/graphics/emugl/RenderControl.h"
|
||||
#include "anbox/graphics/emugl/RenderThreadInfo.h"
|
||||
#include "anbox/graphics/emugl/Renderer.h"
|
||||
#include "anbox/graphics/emugl/TimeUtils.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include "external/android-emugl/shared/OpenglCodecCommon/ChecksumCalculatorThreadInfo.h"
|
||||
#include "external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h"
|
||||
#include "external/android-emugl/host/include/OpenGLESDispatch/GLESv1Dispatch.h"
|
||||
#include "external/android-emugl/host/include/OpenGLESDispatch/GLESv2Dispatch.h"
|
||||
|
||||
#define STREAM_BUFFER_SIZE 4 * 1024 * 1024
|
||||
|
||||
RenderThread::RenderThread(const std::shared_ptr<Renderer> &renderer, IOStream *stream, emugl::Mutex *lock)
|
||||
: emugl::Thread(), renderer_(renderer), m_lock(lock), m_stream(stream) {}
|
||||
RenderThread::RenderThread(const std::shared_ptr<Renderer> &renderer, IOStream *stream, std::mutex &m)
|
||||
: emugl::Thread(), renderer_(renderer), m_lock(m), m_stream(stream) {}
|
||||
|
||||
RenderThread::~RenderThread() {
|
||||
forceStop();
|
||||
}
|
||||
|
||||
RenderThread *RenderThread::create(const std::shared_ptr<Renderer> &renderer, IOStream *stream, emugl::Mutex *lock) {
|
||||
return new RenderThread(renderer, stream, lock);
|
||||
RenderThread *RenderThread::create(const std::shared_ptr<Renderer> &renderer, IOStream *stream, std::mutex &m) {
|
||||
return new RenderThread(renderer, stream, m);
|
||||
}
|
||||
|
||||
void RenderThread::forceStop() { m_stream->forceStop(); }
|
||||
|
|
@ -62,7 +61,8 @@ intptr_t RenderThread::main() {
|
|||
do {
|
||||
progress = false;
|
||||
|
||||
m_lock->lock();
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
size_t last =
|
||||
threadInfo.m_glDec.decode(readBuf.buf(), readBuf.validData(), m_stream);
|
||||
if (last > 0) {
|
||||
|
|
@ -83,8 +83,6 @@ intptr_t RenderThread::main() {
|
|||
progress = true;
|
||||
}
|
||||
|
||||
m_lock->unlock();
|
||||
|
||||
} while (progress);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,15 +13,16 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LIB_OPENGL_RENDER_RENDER_THREAD_H
|
||||
#define _LIB_OPENGL_RENDER_RENDER_THREAD_H
|
||||
|
||||
#include "IOStream.h"
|
||||
#include "external/android-emugl/host/include/libOpenglRender/IOStream.h"
|
||||
|
||||
#include "emugl/common/mutex.h"
|
||||
#include "emugl/common/thread.h"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
class Renderer;
|
||||
|
||||
|
|
@ -36,7 +37,7 @@ class RenderThread : public emugl::Thread {
|
|||
// decoding operations between all threads.
|
||||
// TODO(digit): Why is this needed here? Shouldn't this be handled
|
||||
// by the decoders themselves or at a lower-level?
|
||||
static RenderThread* create(const std::shared_ptr<Renderer>& renderer, IOStream* stream, emugl::Mutex* mutex);
|
||||
static RenderThread* create(const std::shared_ptr<Renderer>& renderer, IOStream* stream, std::mutex &m);
|
||||
|
||||
// Destructor.
|
||||
virtual ~RenderThread();
|
||||
|
|
@ -51,12 +52,12 @@ class RenderThread : public emugl::Thread {
|
|||
private:
|
||||
RenderThread(); // No default constructor
|
||||
|
||||
RenderThread(const std::shared_ptr<Renderer>& renderer, IOStream* stream, emugl::Mutex* mutex);
|
||||
RenderThread(const std::shared_ptr<Renderer>& renderer, IOStream* stream, std::mutex &m);
|
||||
|
||||
virtual intptr_t main();
|
||||
|
||||
std::shared_ptr<Renderer> renderer_;
|
||||
emugl::Mutex* m_lock;
|
||||
std::mutex &m_lock;
|
||||
IOStream* m_stream;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "RenderThreadInfo.h"
|
||||
#include "anbox/graphics/emugl/RenderThreadInfo.h"
|
||||
|
||||
#include "emugl/common/lazy_instance.h"
|
||||
#include "emugl/common/thread_store.h"
|
||||
#include "external/android-emugl/shared/emugl/common/lazy_instance.h"
|
||||
#include "external/android-emugl/shared/emugl/common/thread_store.h"
|
||||
|
||||
namespace {
|
||||
class ThreadInfoStore : public ::emugl::ThreadStore {
|
||||
|
|
|
|||
|
|
@ -13,13 +13,17 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LIB_OPENGL_RENDER_THREAD_INFO_H
|
||||
#define _LIB_OPENGL_RENDER_THREAD_INFO_H
|
||||
|
||||
#include "GLESv1Decoder.h"
|
||||
#include "GLESv2Decoder.h"
|
||||
#include "RenderContext.h"
|
||||
#include "WindowSurface.h"
|
||||
#include "anbox/graphics/emugl/RenderContext.h"
|
||||
#include "anbox/graphics/emugl/WindowSurface.h"
|
||||
|
||||
#include "external/android-emugl/host/libs/GLESv1_dec/GLESv1Decoder.h"
|
||||
#include "external/android-emugl/host/libs/GLESv2_dec/GLESv2Decoder.h"
|
||||
|
||||
// Generated with emugl at build time
|
||||
#include "renderControl_dec.h"
|
||||
|
||||
#include <set>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "Renderable.h"
|
||||
#include "anbox/graphics/emugl/Renderable.h"
|
||||
|
||||
Renderable::Renderable(const std::string &name, const std::uint32_t &buffer,
|
||||
const anbox::graphics::Rect &screen_position,
|
||||
|
|
|
|||
|
|
@ -14,19 +14,18 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "Renderer.h"
|
||||
|
||||
#include "DispatchTables.h"
|
||||
#include "RenderThreadInfo.h"
|
||||
#include "TimeUtils.h"
|
||||
#include "gles2_dec.h"
|
||||
|
||||
#include "OpenGLESDispatch/EGLDispatch.h"
|
||||
|
||||
#include "anbox/graphics/emugl/Renderer.h"
|
||||
#include "anbox/graphics/emugl/DispatchTables.h"
|
||||
#include "anbox/graphics/emugl/RenderThreadInfo.h"
|
||||
#include "anbox/graphics/emugl/TimeUtils.h"
|
||||
#include "anbox/graphics/gl_extensions.h"
|
||||
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include "external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h"
|
||||
|
||||
// Generated with emugl at build time
|
||||
#include "gles2_dec.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
|
@ -361,13 +360,14 @@ HandleType Renderer::genHandle() {
|
|||
|
||||
HandleType Renderer::createColorBuffer(int p_width, int p_height,
|
||||
GLenum p_internalFormat) {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
HandleType ret = 0;
|
||||
|
||||
ColorBufferPtr cb(ColorBuffer::create(
|
||||
getDisplay(), p_width, p_height, p_internalFormat,
|
||||
getCaps().has_eglimage_texture_2d, m_colorBufferHelper));
|
||||
if (cb.Ptr() != NULL) {
|
||||
if (cb) {
|
||||
ret = genHandle();
|
||||
m_colorbuffers[ret].cb = cb;
|
||||
m_colorbuffers[ret].refcount = 1;
|
||||
|
|
@ -377,7 +377,8 @@ HandleType Renderer::createColorBuffer(int p_width, int p_height,
|
|||
|
||||
HandleType Renderer::createRenderContext(int p_config, HandleType p_share,
|
||||
bool p_isGL2) {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
HandleType ret = 0;
|
||||
|
||||
const RendererConfig *config = getConfigs()->get(p_config);
|
||||
|
|
@ -394,11 +395,11 @@ HandleType Renderer::createRenderContext(int p_config, HandleType p_share,
|
|||
share = (*s).second;
|
||||
}
|
||||
EGLContext sharedContext =
|
||||
share.Ptr() ? share->getEGLContext() : EGL_NO_CONTEXT;
|
||||
share ? share->getEGLContext() : EGL_NO_CONTEXT;
|
||||
|
||||
RenderContextPtr rctx(RenderContext::create(
|
||||
m_eglDisplay, config->getEglConfig(), sharedContext, p_isGL2));
|
||||
if (rctx.Ptr() != NULL) {
|
||||
if (rctx) {
|
||||
ret = genHandle();
|
||||
m_contexts[ret] = rctx;
|
||||
RenderThreadInfo *tinfo = RenderThreadInfo::get();
|
||||
|
|
@ -409,7 +410,7 @@ HandleType Renderer::createRenderContext(int p_config, HandleType p_share,
|
|||
|
||||
HandleType Renderer::createWindowSurface(int p_config, int p_width,
|
||||
int p_height) {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
HandleType ret = 0;
|
||||
|
||||
|
|
@ -420,7 +421,7 @@ HandleType Renderer::createWindowSurface(int p_config, int p_width,
|
|||
|
||||
WindowSurfacePtr win(WindowSurface::create(
|
||||
getDisplay(), config->getEglConfig(), p_width, p_height));
|
||||
if (win.Ptr() != NULL) {
|
||||
if (win) {
|
||||
ret = genHandle();
|
||||
m_windows[ret] = std::pair<WindowSurfacePtr, HandleType>(win, 0);
|
||||
RenderThreadInfo *tinfo = RenderThreadInfo::get();
|
||||
|
|
@ -431,7 +432,8 @@ HandleType Renderer::createWindowSurface(int p_config, int p_width,
|
|||
}
|
||||
|
||||
void Renderer::drainRenderContext() {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
RenderThreadInfo *tinfo = RenderThreadInfo::get();
|
||||
if (tinfo->m_contextSet.empty()) return;
|
||||
for (std::set<HandleType>::iterator it = tinfo->m_contextSet.begin();
|
||||
|
|
@ -443,7 +445,8 @@ void Renderer::drainRenderContext() {
|
|||
}
|
||||
|
||||
void Renderer::drainWindowSurface() {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
RenderThreadInfo *tinfo = RenderThreadInfo::get();
|
||||
if (tinfo->m_windowSet.empty()) return;
|
||||
for (std::set<HandleType>::iterator it = tinfo->m_windowSet.begin();
|
||||
|
|
@ -466,7 +469,8 @@ void Renderer::drainWindowSurface() {
|
|||
}
|
||||
|
||||
void Renderer::DestroyRenderContext(HandleType p_context) {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
m_contexts.erase(p_context);
|
||||
RenderThreadInfo *tinfo = RenderThreadInfo::get();
|
||||
if (tinfo->m_contextSet.empty()) return;
|
||||
|
|
@ -474,7 +478,8 @@ void Renderer::DestroyRenderContext(HandleType p_context) {
|
|||
}
|
||||
|
||||
void Renderer::DestroyWindowSurface(HandleType p_surface) {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
if (m_windows.find(p_surface) != m_windows.end()) {
|
||||
m_windows.erase(p_surface);
|
||||
RenderThreadInfo *tinfo = RenderThreadInfo::get();
|
||||
|
|
@ -484,7 +489,8 @@ void Renderer::DestroyWindowSurface(HandleType p_surface) {
|
|||
}
|
||||
|
||||
int Renderer::openColorBuffer(HandleType p_colorbuffer) {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
||||
if (c == m_colorbuffers.end()) {
|
||||
// bad colorbuffer handle
|
||||
|
|
@ -496,7 +502,8 @@ int Renderer::openColorBuffer(HandleType p_colorbuffer) {
|
|||
}
|
||||
|
||||
void Renderer::closeColorBuffer(HandleType p_colorbuffer) {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
||||
if (c == m_colorbuffers.end()) {
|
||||
// This is harmless: it is normal for guest system to issue
|
||||
|
|
@ -511,7 +518,7 @@ void Renderer::closeColorBuffer(HandleType p_colorbuffer) {
|
|||
}
|
||||
|
||||
bool Renderer::flushWindowSurfaceColorBuffer(HandleType p_surface) {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
WindowSurfaceMap::iterator w(m_windows.find(p_surface));
|
||||
if (w == m_windows.end()) {
|
||||
|
|
@ -521,7 +528,10 @@ bool Renderer::flushWindowSurfaceColorBuffer(HandleType p_surface) {
|
|||
return false;
|
||||
}
|
||||
|
||||
WindowSurface *surface = (*w).second.first.Ptr();
|
||||
auto surface = (*w).second.first;
|
||||
if (!surface)
|
||||
return false;
|
||||
|
||||
surface->flushColorBuffer();
|
||||
|
||||
return true;
|
||||
|
|
@ -529,7 +539,7 @@ bool Renderer::flushWindowSurfaceColorBuffer(HandleType p_surface) {
|
|||
|
||||
bool Renderer::setWindowSurfaceColorBuffer(HandleType p_surface,
|
||||
HandleType p_colorbuffer) {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
WindowSurfaceMap::iterator w(m_windows.find(p_surface));
|
||||
if (w == m_windows.end()) {
|
||||
|
|
@ -553,7 +563,7 @@ bool Renderer::setWindowSurfaceColorBuffer(HandleType p_surface,
|
|||
void Renderer::readColorBuffer(HandleType p_colorbuffer, int x, int y,
|
||||
int width, int height, GLenum format,
|
||||
GLenum type, void *pixels) {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
||||
if (c == m_colorbuffers.end()) {
|
||||
|
|
@ -567,7 +577,7 @@ void Renderer::readColorBuffer(HandleType p_colorbuffer, int x, int y,
|
|||
bool Renderer::updateColorBuffer(HandleType p_colorbuffer, int x, int y,
|
||||
int width, int height, GLenum format,
|
||||
GLenum type, void *pixels) {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
||||
if (c == m_colorbuffers.end()) {
|
||||
|
|
@ -581,7 +591,7 @@ bool Renderer::updateColorBuffer(HandleType p_colorbuffer, int x, int y,
|
|||
}
|
||||
|
||||
bool Renderer::bindColorBufferToTexture(HandleType p_colorbuffer) {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
||||
if (c == m_colorbuffers.end()) {
|
||||
|
|
@ -593,7 +603,7 @@ bool Renderer::bindColorBufferToTexture(HandleType p_colorbuffer) {
|
|||
}
|
||||
|
||||
bool Renderer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
ColorBufferMap::iterator c(m_colorbuffers.find(p_colorbuffer));
|
||||
if (c == m_colorbuffers.end()) {
|
||||
|
|
@ -606,7 +616,7 @@ bool Renderer::bindColorBufferToRenderbuffer(HandleType p_colorbuffer) {
|
|||
|
||||
bool Renderer::bindContext(HandleType p_context, HandleType p_drawSurface,
|
||||
HandleType p_readSurface) {
|
||||
emugl::Mutex::AutoLock mutex(m_lock);
|
||||
std::unique_lock<std::mutex> l(m_lock);
|
||||
|
||||
WindowSurfacePtr draw(NULL), read(NULL);
|
||||
RenderContextPtr ctx(NULL);
|
||||
|
|
@ -654,7 +664,7 @@ bool Renderer::bindContext(HandleType p_context, HandleType p_drawSurface,
|
|||
//
|
||||
RenderThreadInfo *tinfo = RenderThreadInfo::get();
|
||||
WindowSurfacePtr bindDraw, bindRead;
|
||||
if (draw.Ptr() == NULL && read.Ptr() == NULL) {
|
||||
if (!draw && !read) {
|
||||
// Unbind the current read and draw surfaces from the context
|
||||
bindDraw = tinfo->currDrawSurf;
|
||||
bindRead = tinfo->currReadSurf;
|
||||
|
|
@ -663,8 +673,8 @@ bool Renderer::bindContext(HandleType p_context, HandleType p_drawSurface,
|
|||
bindRead = read;
|
||||
}
|
||||
|
||||
if (bindDraw.Ptr() != NULL && bindRead.Ptr() != NULL) {
|
||||
if (bindDraw.Ptr() != bindRead.Ptr()) {
|
||||
if (bindDraw && bindRead) {
|
||||
if (bindDraw != bindRead) {
|
||||
bindDraw->bind(ctx, WindowSurface::BIND_DRAW);
|
||||
bindRead->bind(ctx, WindowSurface::BIND_READ);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -16,14 +16,12 @@
|
|||
#ifndef _LIBRENDER_FRAMEBUFFER_H
|
||||
#define _LIBRENDER_FRAMEBUFFER_H
|
||||
|
||||
#include "ColorBuffer.h"
|
||||
#include "RenderContext.h"
|
||||
#include "RendererConfig.h"
|
||||
#include "TextureDraw.h"
|
||||
#include "WindowSurface.h"
|
||||
#include "emugl/common/mutex.h"
|
||||
|
||||
#include "Renderable.h"
|
||||
#include "anbox/graphics/emugl/ColorBuffer.h"
|
||||
#include "anbox/graphics/emugl/RenderContext.h"
|
||||
#include "anbox/graphics/emugl/RendererConfig.h"
|
||||
#include "anbox/graphics/emugl/TextureDraw.h"
|
||||
#include "anbox/graphics/emugl/WindowSurface.h"
|
||||
#include "anbox/graphics/emugl/Renderable.h"
|
||||
|
||||
#include "anbox/graphics/primitives.h"
|
||||
#include "anbox/graphics/program_family.h"
|
||||
|
|
@ -32,6 +30,7 @@
|
|||
#include <EGL/egl.h>
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
|
@ -257,7 +256,7 @@ class Renderer : public anbox::graphics::Renderer {
|
|||
private:
|
||||
static Renderer* s_renderer;
|
||||
static HandleType s_nextHandle;
|
||||
emugl::Mutex m_lock;
|
||||
std::mutex m_lock;
|
||||
RendererConfigList* m_configs;
|
||||
RendererCaps m_caps;
|
||||
EGLDisplay m_eglDisplay;
|
||||
|
|
|
|||
|
|
@ -12,15 +12,14 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "RendererConfig.h"
|
||||
#include "anbox/graphics/emugl/RendererConfig.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include "OpenGLESDispatch/EGLDispatch.h"
|
||||
#include "external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "anbox/logger.h"
|
||||
|
||||
namespace {
|
||||
const GLuint kConfigAttributes[] = {
|
||||
EGL_DEPTH_SIZE, // must be first - see getDepthSize()
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "TextureDraw.h"
|
||||
|
||||
#include "DispatchTables.h"
|
||||
#include "anbox/graphics/emugl/TextureDraw.h"
|
||||
#include "anbox/graphics/emugl/DispatchTables.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
|
@ -22,8 +22,6 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "anbox/logger.h"
|
||||
|
||||
// M_PI isn't defined in C++ (when strict ISO compliance is enabled)
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846264338327
|
||||
|
|
@ -97,16 +95,13 @@ const GLint kIndicesLen = sizeof(kIndices) / sizeof(kIndices[0]);
|
|||
|
||||
} // namespace
|
||||
|
||||
TextureDraw::TextureDraw(EGLDisplay display)
|
||||
: mDisplay(display),
|
||||
mVertexShader(0),
|
||||
TextureDraw::TextureDraw(EGLDisplay)
|
||||
: mVertexShader(0),
|
||||
mFragmentShader(0),
|
||||
mProgram(0),
|
||||
mPositionSlot(-1),
|
||||
mInCoordSlot(-1),
|
||||
mTextureSlot(-1),
|
||||
mRotationSlot(-1),
|
||||
mTranslationSlot(-1) {
|
||||
mTextureSlot(-1) {
|
||||
// Create shaders and program.
|
||||
mVertexShader = createShader(GL_VERTEX_SHADER, kVertexShaderSource);
|
||||
mFragmentShader = createShader(GL_FRAGMENT_SHADER, kFragmentShaderSource);
|
||||
|
|
|
|||
|
|
@ -42,15 +42,12 @@ class TextureDraw {
|
|||
bool draw(GLuint texture);
|
||||
|
||||
private:
|
||||
EGLDisplay mDisplay;
|
||||
GLuint mVertexShader;
|
||||
GLuint mFragmentShader;
|
||||
GLuint mProgram;
|
||||
GLint mPositionSlot;
|
||||
GLint mInCoordSlot;
|
||||
GLint mTextureSlot;
|
||||
GLint mRotationSlot;
|
||||
GLint mTranslationSlot;
|
||||
GLuint mVertexBuffer;
|
||||
GLuint mIndexBuffer;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,17 +13,16 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "TextureResize.h"
|
||||
|
||||
#include "DispatchTables.h"
|
||||
#include "anbox/graphics/emugl/TextureResize.h"
|
||||
#include "anbox/graphics/emugl/DispatchTables.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#define MAX_FACTOR_POWER 4
|
||||
|
||||
static const char kCommonShaderSource[] =
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LIBRENDER_TEXTURERESIZE_H
|
||||
#define _LIBRENDER_TEXTURERESIZE_H
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "TimeUtils.h"
|
||||
|
||||
#include "anbox/graphics/emugl/TimeUtils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _TIME_UTILS_H
|
||||
#define _TIME_UTILS_H
|
||||
|
||||
|
|
|
|||
|
|
@ -13,17 +13,18 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "WindowSurface.h"
|
||||
#include "RendererConfig.h"
|
||||
|
||||
#include "OpenGLESDispatch/EGLDispatch.h"
|
||||
#include "anbox/graphics/emugl/WindowSurface.h"
|
||||
#include "anbox/graphics/emugl/RendererConfig.h"
|
||||
#include "anbox/logger.h"
|
||||
|
||||
#include "external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h"
|
||||
|
||||
#include <GLES/glext.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "anbox/logger.h"
|
||||
|
||||
WindowSurface::WindowSurface(EGLDisplay display, EGLConfig config)
|
||||
: mSurface(NULL),
|
||||
|
|
@ -84,7 +85,7 @@ void WindowSurface::bind(RenderContextPtr p_ctx, BindType p_bindType) {
|
|||
}
|
||||
|
||||
bool WindowSurface::flushColorBuffer() {
|
||||
if (!mAttachedColorBuffer.Ptr()) {
|
||||
if (!mAttachedColorBuffer) {
|
||||
return true;
|
||||
}
|
||||
if (!mWidth || !mHeight) {
|
||||
|
|
@ -98,7 +99,7 @@ bool WindowSurface::flushColorBuffer() {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!mDrawContext.Ptr()) {
|
||||
if (!mDrawContext) {
|
||||
ERROR("Draw context is NULL");
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,8 @@
|
|||
#ifndef _LIBRENDER_WINDOW_SURFACE_H
|
||||
#define _LIBRENDER_WINDOW_SURFACE_H
|
||||
|
||||
#include "ColorBuffer.h"
|
||||
#include "RenderContext.h"
|
||||
|
||||
#include "emugl/common/smart_ptr.h"
|
||||
#include "anbox/graphics/emugl/ColorBuffer.h"
|
||||
#include "anbox/graphics/emugl/RenderContext.h"
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES/gl.h>
|
||||
|
|
@ -94,6 +92,6 @@ class WindowSurface {
|
|||
EGLDisplay mDisplay;
|
||||
};
|
||||
|
||||
typedef emugl::SmartPtr<WindowSurface> WindowSurfacePtr;
|
||||
typedef std::shared_ptr<WindowSurface> WindowSurfacePtr;
|
||||
|
||||
#endif // _LIBRENDER_WINDOW_SURFACE_H
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
namespace anbox {
|
||||
namespace graphics {
|
||||
emugl::Mutex OpenGlesMessageProcessor::global_lock{};
|
||||
std::mutex OpenGlesMessageProcessor::global_lock{};
|
||||
|
||||
OpenGlesMessageProcessor::OpenGlesMessageProcessor(
|
||||
const std::shared_ptr<Renderer> &renderer,
|
||||
|
|
@ -43,7 +43,7 @@ OpenGlesMessageProcessor::OpenGlesMessageProcessor(
|
|||
boost::asio::buffer(&client_flags, sizeof(unsigned int)));
|
||||
if (err) ERROR("%s", err.message());
|
||||
|
||||
render_thread_.reset(RenderThread::create(renderer, stream_.get(), &global_lock));
|
||||
render_thread_.reset(RenderThread::create(renderer, stream_.get(), std::ref(global_lock)));
|
||||
if (!render_thread_->start())
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::runtime_error("Failed to start renderer thread"));
|
||||
|
|
|
|||
|
|
@ -18,16 +18,15 @@
|
|||
#ifndef ANBOX_GRAPHICS_OPENGLES_MESSAGE_PROCESSOR_H_
|
||||
#define ANBOX_GRAPHICS_OPENGLES_MESSAGE_PROCESSOR_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include "anbox/network/message_processor.h"
|
||||
#include "anbox/network/socket_connection.h"
|
||||
#include "anbox/network/socket_messenger.h"
|
||||
#include "anbox/runtime.h"
|
||||
|
||||
#include "external/android-emugl/shared/emugl/common/mutex.h"
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
class IOStream;
|
||||
class RenderThread;
|
||||
|
|
@ -45,7 +44,7 @@ class OpenGlesMessageProcessor : public network::MessageProcessor {
|
|||
bool process_data(const std::vector<std::uint8_t> &data) override;
|
||||
|
||||
private:
|
||||
static emugl::Mutex global_lock;
|
||||
static std::mutex global_lock;
|
||||
|
||||
std::shared_ptr<network::SocketMessenger> messenger_;
|
||||
std::shared_ptr<IOStream> stream_;
|
||||
|
|
|
|||
|
|
@ -64,6 +64,10 @@ struct BoostLogLogger : public anbox::Logger {
|
|||
severity_ = severity;
|
||||
}
|
||||
|
||||
Severity GetSeverity() override {
|
||||
return severity_;
|
||||
}
|
||||
|
||||
void Log(Severity severity, const std::string& message, const boost::optional<Location>& loc) override {
|
||||
if (!initialized_) Init();
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ class Logger : public DoNotCopyOrMove {
|
|||
|
||||
bool SetSeverityFromString(const std::string &severity);
|
||||
virtual void SetSeverity(const Severity& severity) = 0;
|
||||
virtual Severity GetSeverity() = 0;
|
||||
|
||||
virtual void Log(Severity severity, const std::string& message,
|
||||
const boost::optional<Location>& location) = 0;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ PublishedSocketConnector::PublishedSocketConnector(
|
|||
start_accept();
|
||||
}
|
||||
|
||||
PublishedSocketConnector::~PublishedSocketConnector() {}
|
||||
PublishedSocketConnector::~PublishedSocketConnector() noexcept {}
|
||||
|
||||
void PublishedSocketConnector::start_accept() {
|
||||
auto socket = std::make_shared<boost::asio::local::stream_protocol::socket>(runtime_->service());
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ TcpSocketConnector::TcpSocketConnector(
|
|||
start_accept();
|
||||
}
|
||||
|
||||
TcpSocketConnector::~TcpSocketConnector() { acceptor_.cancel(); }
|
||||
TcpSocketConnector::~TcpSocketConnector() noexcept { acceptor_.cancel(); }
|
||||
|
||||
void TcpSocketConnector::start_accept() {
|
||||
auto socket =
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@
|
|||
*/
|
||||
|
||||
#include "anbox/qemu/adb_message_processor.h"
|
||||
#include "anbox/logger.h"
|
||||
#include "anbox/network/delegate_connection_creator.h"
|
||||
#include "anbox/network/delegate_message_processor.h"
|
||||
#include "anbox/network/tcp_socket_messenger.h"
|
||||
#include "anbox/utils.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
|
|
@ -27,18 +27,23 @@
|
|||
namespace {
|
||||
const unsigned short default_adb_client_port{5037};
|
||||
const unsigned short default_host_listen_port{6664};
|
||||
constexpr const char *loopback_address{"127.0.0.1"};
|
||||
const std::string accept_command{"accept"};
|
||||
const std::string ok_command{"ok"};
|
||||
const std::string ko_command{"ko"};
|
||||
const std::string start_command{"start"};
|
||||
// This timeount should be too high to not cause a too long wait time for the
|
||||
// user until we connect to the adb host instance after it appeared and not
|
||||
// too short to not put unnecessary burden on the CPU.
|
||||
const boost::posix_time::seconds default_adb_wait_time{1};
|
||||
static std::mutex active_instance;
|
||||
}
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
namespace anbox {
|
||||
namespace qemu {
|
||||
std::mutex AdbMessageProcessor::active_instance_{};
|
||||
|
||||
AdbMessageProcessor::AdbMessageProcessor(
|
||||
const std::shared_ptr<Runtime> &rt,
|
||||
const std::shared_ptr<network::SocketMessenger> &messenger)
|
||||
|
|
@ -46,12 +51,14 @@ AdbMessageProcessor::AdbMessageProcessor(
|
|||
state_(waiting_for_guest_accept_command),
|
||||
expected_command_(accept_command),
|
||||
messenger_(messenger),
|
||||
host_notify_timer_(rt->service()) {}
|
||||
host_notify_timer_(rt->service()),
|
||||
lock_(active_instance_, std::defer_lock) {}
|
||||
|
||||
AdbMessageProcessor::~AdbMessageProcessor() {
|
||||
state_ = closed_by_host;
|
||||
|
||||
host_notify_timer_.cancel();
|
||||
host_connector_.reset();
|
||||
active_instance.unlock();
|
||||
}
|
||||
|
||||
void AdbMessageProcessor::advance_state() {
|
||||
|
|
@ -61,9 +68,10 @@ void AdbMessageProcessor::advance_state() {
|
|||
// running we don't have to do anything here until that one is done.
|
||||
// The container directly starts a second connection once the first
|
||||
// one is established but will not use it until the active one is closed.
|
||||
active_instance.lock();
|
||||
lock_.lock();
|
||||
|
||||
if (state_ == closed_by_host) {
|
||||
host_notify_timer_.cancel();
|
||||
host_connector_.reset();
|
||||
return;
|
||||
}
|
||||
|
|
@ -100,9 +108,12 @@ void AdbMessageProcessor::advance_state() {
|
|||
}
|
||||
|
||||
void AdbMessageProcessor::wait_for_host_connection() {
|
||||
if (state_ == closed_by_host || state_ == closed_by_container)
|
||||
return;
|
||||
|
||||
if (!host_connector_) {
|
||||
host_connector_ = std::make_shared<network::TcpSocketConnector>(
|
||||
boost::asio::ip::address_v4::from_string("127.0.0.1"),
|
||||
boost::asio::ip::address_v4::from_string(loopback_address),
|
||||
default_host_listen_port, runtime_,
|
||||
std::make_shared<
|
||||
network::DelegateConnectionCreator<boost::asio::ip::tcp>>(
|
||||
|
|
@ -113,18 +124,19 @@ void AdbMessageProcessor::wait_for_host_connection() {
|
|||
// Notify the adb host instance so that it knows on which port our
|
||||
// proxy is waiting for incoming connections.
|
||||
auto messenger = std::make_shared<network::TcpSocketMessenger>(
|
||||
boost::asio::ip::address_v4::from_string("127.0.0.1"),
|
||||
default_adb_client_port, runtime_);
|
||||
auto message =
|
||||
utils::string_format("host:emulator:%d", default_host_listen_port);
|
||||
auto handshake =
|
||||
utils::string_format("%04x%s", message.size(), message.c_str());
|
||||
boost::asio::ip::address_v4::from_string(loopback_address), default_adb_client_port, runtime_);
|
||||
auto message = utils::string_format("host:emulator:%d", default_host_listen_port);
|
||||
auto handshake = utils::string_format("%04x%s", message.size(), message.c_str());
|
||||
messenger->send(handshake.data(), handshake.size());
|
||||
} catch (std::exception &) {
|
||||
} catch (...) {
|
||||
// Try again later when the host adb service is maybe available
|
||||
host_notify_timer_.cancel();
|
||||
host_notify_timer_.expires_from_now(default_adb_wait_time);
|
||||
host_notify_timer_.async_wait(
|
||||
[&](const boost::system::error_code &) { wait_for_host_connection(); });
|
||||
host_notify_timer_.async_wait([this](const boost::system::error_code &err) {
|
||||
if (err)
|
||||
return;
|
||||
wait_for_host_connection();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -148,15 +160,13 @@ void AdbMessageProcessor::on_host_connection(std::shared_ptr<boost::asio::basic_
|
|||
|
||||
void AdbMessageProcessor::read_next_host_message() {
|
||||
auto callback = std::bind(&AdbMessageProcessor::on_host_read_size, this, _1, _2);
|
||||
host_messenger_->async_receive_msg(callback,
|
||||
boost::asio::buffer(host_buffer_));
|
||||
host_messenger_->async_receive_msg(callback, boost::asio::buffer(host_buffer_));
|
||||
}
|
||||
|
||||
void AdbMessageProcessor::on_host_read_size(
|
||||
const boost::system::error_code &error, std::size_t bytes_read) {
|
||||
void AdbMessageProcessor::on_host_read_size(const boost::system::error_code &error, std::size_t bytes_read) {
|
||||
if (error) {
|
||||
state_ = closed_by_host;
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(error.message()));
|
||||
return;
|
||||
}
|
||||
|
||||
messenger_->send(reinterpret_cast<const char *>(host_buffer_.data()), bytes_read);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace anbox {
|
||||
namespace qemu {
|
||||
class AdbMessageProcessor : public network::MessageProcessor {
|
||||
|
|
@ -66,6 +68,9 @@ class AdbMessageProcessor : public network::MessageProcessor {
|
|||
std::shared_ptr<network::TcpSocketMessenger> host_messenger_;
|
||||
std::array<std::uint8_t, 8192> host_buffer_;
|
||||
boost::asio::deadline_timer host_notify_timer_;
|
||||
std::unique_lock<std::mutex> lock_;
|
||||
|
||||
static std::mutex active_instance_;
|
||||
};
|
||||
} // namespace graphics
|
||||
} // namespace anbox
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#ifndef ANBOX_QEMU_AT_PARSER_H_
|
||||
#define ANBOX_QEMU_AT_PARSER_H_
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ PipeConnectionCreator::PipeConnectionCreator(const std::shared_ptr<Renderer> &re
|
|||
std::make_shared<network::Connections<network::SocketConnection>>()) {
|
||||
}
|
||||
|
||||
PipeConnectionCreator::~PipeConnectionCreator() {
|
||||
PipeConnectionCreator::~PipeConnectionCreator() noexcept {
|
||||
connections_->clear();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ ConnectionCreator::ConnectionCreator(const std::shared_ptr<Runtime>& rt,
|
|||
std::make_shared<network::Connections<network::SocketConnection>>()),
|
||||
message_processor_factory_(factory) {}
|
||||
|
||||
ConnectionCreator::~ConnectionCreator() {}
|
||||
ConnectionCreator::~ConnectionCreator() noexcept {}
|
||||
|
||||
void ConnectionCreator::create_connection_for(
|
||||
std::shared_ptr<boost::asio::local::stream_protocol::socket> const&
|
||||
|
|
@ -43,8 +43,7 @@ void ConnectionCreator::create_connection_for(
|
|||
socket->close();
|
||||
WARNING(
|
||||
"A second client tried to connect. Denied request as we already have "
|
||||
"one"
|
||||
"and only allow a single client");
|
||||
"one and only allow a single client");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ Runtime::Runtime(std::uint32_t pool_size)
|
|||
strand_{service_},
|
||||
keep_alive_{service_} {}
|
||||
|
||||
Runtime::~Runtime() {
|
||||
Runtime::~Runtime() noexcept(true) {
|
||||
try {
|
||||
stop();
|
||||
} catch (...) {
|
||||
|
|
|
|||
|
|
@ -68,8 +68,7 @@ PlatformPolicy::PlatformPolicy(
|
|||
window_size_immutable_ = true;
|
||||
}
|
||||
|
||||
display_info_.horizontal_resolution = display_frame.width();
|
||||
display_info_.vertical_resolution = display_frame.height();
|
||||
graphics::emugl::DisplayInfo::get()->set_resolution(display_frame.width(), display_frame.height());
|
||||
|
||||
pointer_ = input_manager->create_device();
|
||||
pointer_->set_name("anbox-pointer");
|
||||
|
|
@ -285,10 +284,6 @@ void PlatformPolicy::window_resized(const Window::Id &id,
|
|||
}
|
||||
}
|
||||
|
||||
DisplayManager::DisplayInfo PlatformPolicy::display_info() const {
|
||||
return display_info_;
|
||||
}
|
||||
|
||||
void PlatformPolicy::set_clipboard_data(const ClipboardData &data) {
|
||||
if (data.text.empty())
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -41,8 +41,7 @@ class Manager;
|
|||
namespace ubuntu {
|
||||
class PlatformPolicy : public std::enable_shared_from_this<PlatformPolicy>,
|
||||
public platform::Policy,
|
||||
public Window::Observer,
|
||||
public DisplayManager {
|
||||
public Window::Observer {
|
||||
public:
|
||||
PlatformPolicy(const std::shared_ptr<input::Manager> &input_manager,
|
||||
const graphics::Rect &static_display_frame = graphics::Rect::Invalid,
|
||||
|
|
@ -61,8 +60,6 @@ class PlatformPolicy : public std::enable_shared_from_this<PlatformPolicy>,
|
|||
void window_resized(const Window::Id &id, const std::int32_t &width,
|
||||
const std::int32_t &height) override;
|
||||
|
||||
DisplayInfo display_info() const override;
|
||||
|
||||
void set_renderer(const std::shared_ptr<Renderer> &renderer);
|
||||
void set_window_manager(const std::shared_ptr<wm::Manager> &window_manager);
|
||||
|
||||
|
|
@ -89,7 +86,6 @@ class PlatformPolicy : public std::enable_shared_from_this<PlatformPolicy>,
|
|||
bool event_thread_running_;
|
||||
std::shared_ptr<input::Device> pointer_;
|
||||
std::shared_ptr<input::Device> keyboard_;
|
||||
DisplayManager::DisplayInfo display_info_;
|
||||
bool window_size_immutable_ = false;
|
||||
bool single_window_ = false;
|
||||
};
|
||||
|
|
|
|||
90
src/anbox/ui/splash_screen.cpp
Normal file
90
src/anbox/ui/splash_screen.cpp
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (C) 2017 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/ui/splash_screen.h"
|
||||
#include "anbox/config.h"
|
||||
#include "anbox/utils.h"
|
||||
|
||||
#include <SDL2/SDL_image.h>
|
||||
|
||||
namespace anbox {
|
||||
namespace ui {
|
||||
SplashScreen::SplashScreen() {
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) {
|
||||
const auto message = utils::string_format("Failed to initialize SDL: %s", SDL_GetError());
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(message));
|
||||
}
|
||||
|
||||
const auto width = 1024, height = 768;
|
||||
window_ = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||
width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS);
|
||||
if (!window_) {
|
||||
const auto message = utils::string_format("Failed to create window: %s", SDL_GetError());
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(message));
|
||||
}
|
||||
|
||||
auto surface = SDL_GetWindowSurface(window_);
|
||||
if (!surface)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Could not retrieve surface for our window"));
|
||||
|
||||
SDL_FillRect(surface, nullptr, SDL_MapRGB(surface->format, 0xee, 0xee, 0xee));
|
||||
SDL_UpdateWindowSurface(window_);
|
||||
|
||||
auto renderer = SDL_CreateRenderer(window_, -1, SDL_RENDERER_ACCELERATED);
|
||||
if (!renderer)
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error("Could not create renderer"));
|
||||
|
||||
const auto icon_path = utils::string_format("%s/ui/loading-screen.png", SystemConfiguration::instance().resource_dir());
|
||||
auto img = IMG_LoadTexture(renderer, icon_path.c_str());
|
||||
if (!img) {
|
||||
const auto msg = utils::string_format("Failed to create texture from %s", icon_path);
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(msg));
|
||||
}
|
||||
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
SDL_Rect r{0, 0, width, height};
|
||||
SDL_RenderCopy(renderer, img, nullptr, &r);
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
SDL_ShowWindow(window_);
|
||||
|
||||
event_thread_ = std::thread(&SplashScreen::process_events, this);
|
||||
}
|
||||
|
||||
SplashScreen::~SplashScreen() {
|
||||
if (event_thread_running_) {
|
||||
event_thread_running_ = false;
|
||||
if (event_thread_.joinable())
|
||||
event_thread_.join();
|
||||
}
|
||||
|
||||
if (window_)
|
||||
SDL_DestroyWindow(window_);
|
||||
}
|
||||
|
||||
void SplashScreen::process_events() {
|
||||
event_thread_running_ = true;
|
||||
while (event_thread_running_) {
|
||||
SDL_Event event;
|
||||
while (SDL_WaitEventTimeout(&event, 100)) {
|
||||
// Keep running until we're terminated
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace ui
|
||||
} // namespace anbox
|
||||
42
src/anbox/ui/splash_screen.h
Normal file
42
src/anbox/ui/splash_screen.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2017 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_UI_SPLASH_SCREEN_H_
|
||||
#define ANBOX_UI_SPLASH_SCREEN_H_
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
namespace anbox {
|
||||
namespace ui {
|
||||
class SplashScreen {
|
||||
public:
|
||||
SplashScreen();
|
||||
~SplashScreen();
|
||||
|
||||
private:
|
||||
void process_events();
|
||||
|
||||
std::thread event_thread_;
|
||||
bool event_thread_running_;
|
||||
SDL_Window *window_;
|
||||
};
|
||||
} // namespace ui
|
||||
} // namespace anbox
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue