diff --git a/CMakeLists.txt b/CMakeLists.txt index 3901428..df9d6fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,8 @@ include(CTest) include(GNUInstallDirs) if (NOT CMAKE_BUILD_TYPE) - message(STATUS "No build type selected, default to release") - set(CMAKE_BUILD_TYPE "release") + message(STATUS "No build type selected, default to RelWithDebInfo") + set(CMAKE_BUILD_TYPE "RelWithDebInfo") endif() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) diff --git a/README.md b/README.md index a1a54f0..9639b5a 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ $ anbox-installer This will guide you through the installation process. -**NOTE:** Anbox is currently in a **pre-alpha development state**. Don't expect a +**NOTE:** Anbox is currently in a **alpha development state**. Don't expect a fully working system for a production system with all features you need. You will for sure see bugs and crashes. If you do so, please don't hestitate and report them! diff --git a/android/service/platform_service.cpp b/android/service/platform_service.cpp index 8e2c57a..0a19818 100644 --- a/android/service/platform_service.cpp +++ b/android/service/platform_service.cpp @@ -49,6 +49,7 @@ anbox::PlatformApiStub::WindowStateUpdate::Window PlatformService::unpack_window auto frame_bottom = data.readInt32(); auto task_id = data.readInt32(); auto stack_id = data.readInt32(); + auto rotation_angle = data.readInt32(); return anbox::PlatformApiStub::WindowStateUpdate::Window{ -1, // Display id will be added by the caller diff --git a/debian/compat b/debian/compat index 7f8f011..ec63514 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -7 +9 diff --git a/debian/control b/debian/control index 8696f8e..72e3872 100644 --- a/debian/control +++ b/debian/control @@ -2,8 +2,8 @@ Source: anbox Section: misc Priority: optional Maintainer: Simon Fels -Build-Depends: debhelper (>= 7), dkms, dh-systemd -Standards-Version: 3.9.7 +Build-Depends: debhelper (>= 9), dkms, dh-systemd +Standards-Version: 4.1.3 Homepage: http://anbox.io Vcs-Browser: https://github.com/anbox/anbox Vcs-Git: https://github.com/anbox/anbox.git diff --git a/external/android-emugl/host/libs/Translator/GLES_V2/.GLESv2Imp.cpp.swp b/external/android-emugl/host/libs/Translator/GLES_V2/.GLESv2Imp.cpp.swp deleted file mode 100644 index 8102470..0000000 Binary files a/external/android-emugl/host/libs/Translator/GLES_V2/.GLESv2Imp.cpp.swp and /dev/null differ diff --git a/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp b/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp index c49d4b7..91ff0b1 100644 --- a/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp +++ b/external/android-emugl/host/libs/Translator/GLES_V2/GLESv2Imp.cpp @@ -1048,8 +1048,10 @@ GL_APICALL void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params){ if (ctx->glGetIntegerv(pname,params)) { if (destroyCtx) + { deleteGLESContext(ctx); return; + } } bool es2 = ctx->getCaps()->GL_ARB_ES2_COMPATIBILITY; diff --git a/external/android-emugl/host/tools/emugen/ApiGen.cpp b/external/android-emugl/host/tools/emugen/ApiGen.cpp index cd3d67b..f912cb5 100644 --- a/external/android-emugl/host/tools/emugen/ApiGen.cpp +++ b/external/android-emugl/host/tools/emugen/ApiGen.cpp @@ -753,6 +753,10 @@ int ApiGen::genDecoderHeader(const std::string &filename) fprintf(fp, "#include \"IOStream.h\" \n"); fprintf(fp, "#include \"%s_%s_context.h\"\n\n\n", m_basename.c_str(), sideString(SERVER_SIDE)); + if (strcmp(classname.c_str(), "gles2_decoder_context_t") == 0) { + fprintf(fp, "\n#include \n"); + fprintf(fp, "\n#include \n"); + } fprintf(fp, "\n#include \"emugl/common/logging.h\"\n"); for (size_t i = 0; i < m_decoderHeaders.size(); i++) { @@ -763,6 +767,17 @@ int ApiGen::genDecoderHeader(const std::string &filename) fprintf(fp, "struct %s : public %s_%s_context_t {\n\n", classname.c_str(), m_basename.c_str(), sideString(SERVER_SIDE)); fprintf(fp, "\tsize_t decode(void *buf, size_t bufsize, IOStream *stream);\n"); + if (strcmp(classname.c_str(), "gles2_decoder_context_t") == 0){ + fprintf(fp, + "\tvoid freeShader(); \n\ + \tvoid freeProgram(); \n\ + \tstd::map m_programs; \n\ + \tstd::map m_shaders; \n\ + \tstd::mutex m_lock; \n\ + "); + + + } fprintf(fp, "\n};\n\n"); fprintf(fp, "#endif // GUARD_%s\n", classname.c_str()); @@ -835,6 +850,35 @@ int ApiGen::genDecoderImpl(const std::string &filename) // helper templates fprintf(fp, "using namespace emugl;\n\n"); + // glsl shader/program free; + if (strcmp(classname.c_str(), "gles2_decoder_context_t") == 0) { + fprintf(fp, "void %s::freeShader(){\n", classname.c_str()); + fprintf(fp, + " \n\ +\tauto it = m_shaders.begin();\n\ +\tm_lock.lock();\n\ +\twhile(it != m_shaders.end()) \n\ +\t{\n\ +\t\tthis->glDeleteShader(it->first);\n\ +\t\tit++;\n\ +\t}\n\ +\tm_lock.unlock();\n\ +}\n\n"); + + fprintf(fp, "void %s::freeProgram(){\n", classname.c_str()); + fprintf(fp, + " \n\ +\tauto it = m_programs.begin(); \n\ +\tm_lock.lock();\n\ +\twhile(it != m_programs.end()) \n\ +\t{\n\ +\t\tthis->glDeleteProgram(it->first);\n\ +\t\tit++;\n\ +\t}\n\ +\tm_lock.unlock();\n\ +}\n\n"); + } + // decoder switch; fprintf(fp, "size_t %s::decode(void *buf, size_t len, IOStream *stream)\n{\n", classname.c_str()); fprintf(fp, @@ -1114,8 +1158,7 @@ int ApiGen::genDecoderImpl(const std::string &filename) varoffset.c_str(), varoffset.c_str(), varoffset.c_str(), - classname.c_str(), - e->name().c_str() + classname.c_str() ); varoffset += " + 4"; @@ -1161,6 +1204,37 @@ int ApiGen::genDecoderImpl(const std::string &filename) } // pass; fprintf(fp, "\t\t\tSET_LASTCALL(\"%s\");\n", e->name().c_str()); + if (strcmp(m_basename.c_str(), "gles2") == 0) { + if (strcmp(e->name().c_str(), "glAttachShader") == 0){ + fprintf(fp, "\n\ + \t\t\tm_lock.lock();\n\ + m_shaders.insert({var_shader, 1});\n\ + m_lock.unlock();\n"); + } else if(strcmp(e->name().c_str(), "glDeleteProgram") == 0){ + fprintf(fp, + "\t\t\tm_lock.lock(); \n" + "\t\t\tauto pro = m_programs.find(var_program); \n" + "\t\t\tif (pro != m_programs.end()) \n" + "\t\t\t{ \n" + "\t\t\t\tm_programs.erase(pro); \n" + "\t\t\t}\n" + "\t\t\tm_lock.unlock();\n"); + } else if(strcmp(e->name().c_str(), "glDeleteShader") == 0){ + fprintf(fp, + "\t\t\tm_lock.lock(); \n\ + \t\t\tauto shader = m_shaders.find(var_shader); \n\ + \t\t\tif (shader != m_shaders.end()) \n\ + \t\t\t{ \n\ + \t\t\t\tm_shaders.erase(shader); \n\ + \t\t\t} \n\ + \t\t\tm_lock.unlock(); \n"); + } else if(strcmp(e->name().c_str(), "glLinkProgram") == 0){ + fprintf(fp, " \n\ + \t\t\tm_lock.lock();\n\ + \t\t\tm_programs.insert({var_program, 1});\n\ + \t\t\tm_lock.unlock();\n"); + } + } fprintf(fp, "\t\t\tbreak;\n"); fprintf(fp, "\t\t}\n"); diff --git a/external/android-emugl/host/tools/emugen/EntryPoint.cpp b/external/android-emugl/host/tools/emugen/EntryPoint.cpp index cc3bef1..8f91c83 100644 --- a/external/android-emugl/host/tools/emugen/EntryPoint.cpp +++ b/external/android-emugl/host/tools/emugen/EntryPoint.cpp @@ -99,7 +99,7 @@ bool EntryPoint::parse(unsigned int lc, const std::string & str) std::string vartype, varname; if (!parseParameterDeclaration(field, &vartype, &varname, &error)) { fprintf(stderr, - "line: %d: Parsing error in field <%s>\n", + "line: %d: Parsing error in field <%s>, error: %s\n", lc, field.c_str(), error.c_str()); diff --git a/external/process-cpp-minimal/src/core/posix/signal.cpp b/external/process-cpp-minimal/src/core/posix/signal.cpp index fd90047..43c10e0 100644 --- a/external/process-cpp-minimal/src/core/posix/signal.cpp +++ b/external/process-cpp-minimal/src/core/posix/signal.cpp @@ -204,7 +204,7 @@ private: } std::shared_ptr core::posix::trap_signals_for_process( - std::initializer_list blocked_signals) + std::initializer_list blocked_signals) { return std::make_shared( impl::SignalTrap::Scope::process, diff --git a/kernel/ashmem/ashmem.c b/kernel/ashmem/ashmem.c index c846db6..1831493 100644 --- a/kernel/ashmem/ashmem.c +++ b/kernel/ashmem/ashmem.c @@ -312,8 +312,14 @@ static ssize_t ashmem_read(struct file *file, char __user *buf, * once asma->file is set it will never be changed, and will not * be destroyed until all references to the file are dropped and * ashmem_release is called. + * + * kernel_read supersedes vfs_read from kernel version 3.9 */ - ret = __vfs_read(asma->file, buf, len, pos); + #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0) + ret = __vfs_read(asma->file, buf, len, pos); + #else + ret = kernel_read(asma->file, buf, len, pos); + #endif if (ret >= 0) /** Update backing file pos, since f_ops->read() doesn't */ asma->file->f_pos = *pos; diff --git a/kernel/binder/binder.c b/kernel/binder/binder.c index fb939e6..9ccadf1 100644 --- a/kernel/binder/binder.c +++ b/kernel/binder/binder.c @@ -137,7 +137,11 @@ static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait); static int binder_stop_on_user_error; static int binder_set_stop_on_user_error(const char *val, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) + const struct kernel_param *kp) +#else struct kernel_param *kp) +#endif { int ret; diff --git a/scripts/clean-build.sh b/scripts/clean-build.sh index d1041a4..3e1e766 100755 --- a/scripts/clean-build.sh +++ b/scripts/clean-build.sh @@ -56,8 +56,8 @@ cleanup mkdir build || rm -rf build/* cd build cmake .. -make -j10 -make test +VERBOSE=1 make -j10 +VERBOSE=1 make test cd .. cleanup diff --git a/scripts/gen-emugl-entries.py b/scripts/gen-emugl-entries.py index 23dcd61..b88137e 100755 --- a/scripts/gen-emugl-entries.py +++ b/scripts/gen-emugl-entries.py @@ -25,6 +25,7 @@ # # Anything else is an error. +from __future__ import print_function import re import sys import argparse @@ -32,6 +33,9 @@ import argparse re_func = re.compile(r"""^(.*[\* ])([A-Za-z_][A-Za-z0-9_]*)\((.*)\);$""") re_param = re.compile(r"""^(.*[\* ])([A-Za-z_][A-Za-z0-9_]*)$""") +def eprint(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + class Entry: """Small class used to model a single DLL entry point.""" def __init__(self, func_name, return_type, parameters): @@ -128,28 +132,28 @@ def gen_functions_header(entries, prefix_name, verbatim, filename, with_args): """ prefix_name = prefix_name.upper() - print "// Auto-generated with: %s" % banner_command(sys.argv) - print "// DO NOT EDIT THIS FILE" - print "" - print "#ifndef %s_FUNCTIONS_H" % prefix_name - print "#define %s_FUNCTIONS_H" % prefix_name - print "" + print("// Auto-generated with: %s" % banner_command(sys.argv)) + print("// DO NOT EDIT THIS FILE") + print("") + print("#ifndef %s_FUNCTIONS_H" % prefix_name) + print("#define %s_FUNCTIONS_H" % prefix_name) + print("") for line in verbatim: - print line + print(line) - print "#define LIST_%s_FUNCTIONS(X) \\" % prefix_name + print("#define LIST_%s_FUNCTIONS(X) \\" % prefix_name) for entry in entries: if with_args: - print " X(%s, %s, (%s), (%s)) \\" % \ + print(" X(%s, %s, (%s), (%s)) \\" % \ (entry.return_type, entry.func_name, entry.parameters, - entry.call) + entry.call)) else: - print " X(%s, %s, (%s)) \\" % \ - (entry.return_type, entry.func_name, entry.parameters) + print(" X(%s, %s, (%s)) \\" % \ + (entry.return_type, entry.func_name, entry.parameters)) - print "" - print "" - print "#endif // %s_FUNCTIONS_H" % prefix_name + print("") + print("") + print("#endif // %s_FUNCTIONS_H" % prefix_name) @@ -199,10 +203,10 @@ def gen_translator(entries): "glProgramUniform3ui": 1, "glProgramUniform4ui": 1, "glBindVertexBuffer": 1, - }; + } translator_nocontext_fail_codes = { "glClientWaitSync" : "GL_WAIT_FAILED", - }; + } def needExternC(entry): if translator_needexternc.has_key(entry.func_name): return "extern \"C\" " @@ -210,14 +214,14 @@ def gen_translator(entries): return "" def get_fail_code(entry): if translator_nocontext_fail_codes.has_key(entry.func_name): - return translator_nocontext_fail_codes[entry.func_name]; + return translator_nocontext_fail_codes[entry.func_name] else: return "0" def gen_cxt_getter(entry): if (entry.return_type == "void"): - print " GET_CTX_V2();" + print(" GET_CTX_V2();") else: - print " GET_CTX_V2_RET(%s);" % get_fail_code(entry) + print(" GET_CTX_V2_RET(%s);" % get_fail_code(entry)) def gen_validations_custom_impl(entry): isGen = entry.func_name.startswith("glGen") @@ -231,14 +235,14 @@ def gen_translator(entries): if entry.return_type == "void": return "SET_ERROR_IF(%s,%s)" % (condition, glerr); else: - return "RET_AND_SET_ERROR_IF(%s,%s,%s)" % (condition, glerr, get_fail_code(entry)); + return "RET_AND_SET_ERROR_IF(%s,%s,%s)" % (condition, glerr, get_fail_code(entry)) if (isGen or isDelete) and ("n" in entry.varnames): - print " %s;" % mySetError("n < 0", "GL_INVALID_VALUE"); + print(" %s;" % mySetError("n < 0", "GL_INVALID_VALUE")) if (isBufferOp and hasTargetArg): - print " %s;" % mySetError("!GLESv2Validate::bufferTarget(ctx, target)", "GL_INVALID_ENUM"); + print(" %s;" % mySetError("!GLESv2Validate::bufferTarget(ctx, target)", "GL_INVALID_ENUM")) if translator_custom_pre.has_key(entry.func_name): - print translator_custom_pre[entry.func_name], + print(translator_custom_pre[entry.func_name],) def gen_call_ret(entry): globalNameTypes = { @@ -262,53 +266,53 @@ def gen_translator(entries): needsShareGroup = True if needsShareGroup: - print " if (ctx->shareGroup().get()) {" + print(" if (ctx->shareGroup().get()) {") for key in zip(entry.vartypes, entry.varnames): vartype, varname = key if globalNames.has_key(key): - print " const GLuint %s = ctx->shareGroup()->getGlobalName(%s, %s);" % (globalNames[key], globalNameTypes[key], varname) + print(" const GLuint %s = ctx->shareGroup()->getGlobalName(%s, %s);" % (globalNames[key], globalNameTypes[key], varname)) globalCall = ", ".join(map(lambda k: globalNames.get(k, k[1]), zip(entry.vartypes, entry.varnames))) if needsShareGroup and translator_custom_share_processing.has_key(entry.func_name): - print translator_custom_share_processing[entry.func_name], + print(translator_custom_share_processing[entry.func_name]) if (entry.return_type == "void"): if (needsShareGroup): - print " ", + print(" "), if not translator_no_passthrough.has_key(entry.func_name): - print " ctx->dispatcher().%s(%s);" % (entry.func_name, globalCall) + print(" ctx->dispatcher().%s(%s);" % (entry.func_name, globalCall)) if needsShareGroup: - print " }" + print(" }") if translator_custom_post.has_key(entry.func_name): - print translator_custom_post[entry.func_name]; + print(translator_custom_post[entry.func_name]) else: if (needsShareGroup): - print " ", + print(" "), if not translator_no_passthrough.has_key(entry.func_name): - print " %s %s = ctx->dispatcher().%s(%s);" % (entry.return_type, entry.func_name + "RET", entry.func_name, globalCall) + print(" %s %s = ctx->dispatcher().%s(%s);" % (entry.return_type, entry.func_name + "RET", entry.func_name, globalCall)) else: - print " %s %s = %s" % (entry.return_type, entry_func_name + "RET", get_fail_code(entry)) + print(") %s %s = %s" % (entry.return_type, entry_func_name + "RET", get_fail_code(entry))) if translator_custom_post.has_key(entry.func_name): - print translator_custom_post[entry.func_name]; + print(translator_custom_post[entry.func_name]) - print " return %s;" % (entry.func_name + "RET"); + print(" return %s;" % (entry.func_name + "RET")) if needsShareGroup: - print " } else return %s;" % (get_fail_code(entry)) + print(" } else return %s;" % (get_fail_code(entry))) - print "// Auto-generated with: %s" % banner_command(sys.argv) - print "// This file is best left unedited." - print "// Try to make changes through gen_translator in gen-entries.py," - print "// and/or parcel out custom functionality in separate code." + print("// Auto-generated with: %s" % banner_command(sys.argv)) + print("// This file is best left unedited.") + print("// Try to make changes through gen_translator in gen-entries.py,") + print("// and/or parcel out custom functionality in separate code.") for entry in entries: - print "%sGL_APICALL %s GL_APIENTRY %s(%s) {" % (needExternC(entry), entry.return_type, entry.func_name, entry.parameters) - gen_cxt_getter(entry); - gen_validations_custom_impl(entry); - gen_call_ret(entry); - print "}\n" + print("%sGL_APICALL %s GL_APIENTRY %s(%s) {" % (needExternC(entry), entry.return_type, entry.func_name, entry.parameters)) + gen_cxt_getter(entry) + gen_validations_custom_impl(entry) + gen_call_ret(entry) + print("}\n") def gen_dll_wrapper(entries, prefix_name, verbatim, filename): """Generate a C source file that contains functions that act as wrappers @@ -322,77 +326,77 @@ def gen_dll_wrapper(entries, prefix_name, verbatim, filename): ENTRY_PREFIX = "__dll_" - print "// Auto-generated with: %s" % banner_command(sys.argv) - print "// DO NOT EDIT THIS FILE" - print "" - print "#include " + print("// Auto-generated with: %s" % banner_command(sys.argv)) + print("// DO NOT EDIT THIS FILE") + print("") + print("#include ") for line in verbatim: - print line + print(line) - print "" - print "///" - print "/// W R A P P E R P O I N T E R S" - print "///" - print "" + print("") + print("///") + print("/// W R A P P E R P O I N T E R S") + print("///") + print("") for entry in entries: ptr_name = ENTRY_PREFIX + entry.func_name - print "static %s (*%s)(%s) = 0;" % \ - (entry.return_type, ptr_name, entry.parameters) + print("static %s (*%s)(%s) = 0;" % \ + (entry.return_type, ptr_name, entry.parameters)) - print "" - print "///" - print "/// W R A P P E R F U N C T I O N S" - print "///" - print "" + print("") + print("///") + print("/// W R A P P E R F U N C T I O N S") + print("///") + print("") for entry in entries: - print "%s %s(%s) {" % \ - (entry.return_type, entry.func_name, entry.parameters) + print ("%s %s(%s) {" % \ + (entry.return_type, entry.func_name, entry.parameters)) ptr_name = ENTRY_PREFIX + entry.func_name if entry.return_type != "void": - print " return %s(%s);" % (ptr_name, entry.call) + print(" return %s(%s);" % (ptr_name, entry.call)) else: - print " %s(%s);" % (ptr_name, entry.call) - print "}\n" + print(" %s(%s);" % (ptr_name, entry.call)) + print("}\n") - print "" - print "///" - print "/// I N I T I A L I Z A T I O N F U N C T I O N" - print "///" - print "" + print("") + print("///") + print("/// I N I T I A L I Z A T I O N F U N C T I O N") + print("///") + print("") - print "int %s_dynlink_init(void* lib) {" % prefix_name + print("int %s_dynlink_init(void* lib) {" % prefix_name) for entry in entries: ptr_name = ENTRY_PREFIX + entry.func_name - print " %s = (%s(*)(%s))dlsym(lib, \"%s\");" % \ + print(" %s = (%s(*)(%s))dlsym(lib, \"%s\");" % \ (ptr_name, entry.return_type, entry.parameters, - entry.func_name) - print " if (!%s) return -1;" % ptr_name - print " return 0;" - print "}" + entry.func_name)) + print(" if (!%s) return -1;" % ptr_name) + print(" return 0;") + print("}") def gen_windows_def_file(entries): """Generate a windows DLL .def file. |entries| is a list of Entry instances. """ - print "EXPORTS" + print("EXPORTS") for entry in entries: - print " %s" % entry.func_name + print(" %s" % entry.func_name) def gen_unix_sym_file(entries): """Generate an ELF linker version file. |entries| is a list of Entry instances. """ - print "VERSION {" - print "\tglobal:" + print("VERSION {") + print("\tglobal:") for entry in entries: - print "\t\t%s;" % entry.func_name - print "\tlocal:" - print "\t\t*;" - print "};" + print("\t\t%s;" % entry.func_name) + print("\tlocal:") + print("\t\t*;") + print("};") def gen_symbols(entries, underscore): """Generate a list of symbols from |entries|, a list of Entry instances. @@ -403,7 +407,7 @@ def gen_symbols(entries, underscore): if underscore: prefix = "_" for entry in entries: - print "%s%s" % (prefix, entry.func_name) + print("%s%s" % (prefix, entry.func_name)) def parse_file(filename, lines, mode): """Generate one of possible outputs from |filename|. |lines| must be a list @@ -413,7 +417,7 @@ def parse_file(filename, lines, mode): entries, prefix_name, verbatim, errors = parse_entries_file(lines) if errors: for error in errors: - print >> sys.stderr, "ERROR: %s:%s" % (filename, error) + eprint("ERROR: %s:%s" % (filename, error), file=sys.stderr) sys.exit(1) if not prefix_name: @@ -466,7 +470,7 @@ parser.add_argument("file", help=".entries file path") args = parser.parse_args() if not args.mode: - print >> sys.stderr, "ERROR: Please use --mode=, see --help." + eprint("ERROR: Please use --mode=, see --help.", file=sys.stderr) sys.exit(1) if args.output: diff --git a/scripts/snap-wrapper.sh b/scripts/snap-wrapper.sh index 0ca2d83..b1f1e3b 100755 --- a/scripts/snap-wrapper.sh +++ b/scripts/snap-wrapper.sh @@ -35,6 +35,11 @@ export LD_LIBRARY_PATH="$SNAP_LIBRARY_PATH:$LD_LIBRARY_PATH" # Ref.: https://bugs.launchpad.net/snappy/+bug/1588192 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/var/lib/snapd/lib/gl +# With recent builds on Ubuntu 16.04 the snap does not find the path to +# libpulsecommon-8.0.so anymore so we have to teach the linker manually +# where it can be found +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SNAP/usr/lib/$ARCH/pulseaudio + # 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 diff --git a/src/anbox/cmds/session_manager.cpp b/src/anbox/cmds/session_manager.cpp index 4988967..165c043 100644 --- a/src/anbox/cmds/session_manager.cpp +++ b/src/anbox/cmds/session_manager.cpp @@ -176,7 +176,7 @@ anbox::cmds::SessionManager::SessionManager() input_manager, display_frame, single_window_); - if (!platform) + if (!platform) return EXIT_FAILURE; auto app_db = std::make_shared(); diff --git a/src/anbox/container/management_api_stub.cpp b/src/anbox/container/management_api_stub.cpp index 1806daf..ebe7632 100644 --- a/src/anbox/container/management_api_stub.cpp +++ b/src/anbox/container/management_api_stub.cpp @@ -24,6 +24,9 @@ namespace anbox { namespace container { + +const std::chrono::milliseconds ManagementApiStub::stop_waiting_timeout{3000}; + ManagementApiStub::ManagementApiStub( const std::shared_ptr &channel) : channel_(channel) {} @@ -75,7 +78,9 @@ void ManagementApiStub::stop_container() { channel_->call_method("stop_container", &message, c->response.get(), google::protobuf::NewCallback(this, &ManagementApiStub::container_stopped, c.get())); - c->wh.wait_for_all(); + // If container manager dies before session manager, the session manager + // cannot exit if it waits for all, so just wait for 3 seconds. + c->wh.wait_for_pending(stop_waiting_timeout); if (c->response->has_error()) throw std::runtime_error(c->response->error()); } diff --git a/src/anbox/container/management_api_stub.h b/src/anbox/container/management_api_stub.h index 11ebeeb..e40df94 100644 --- a/src/anbox/container/management_api_stub.h +++ b/src/anbox/container/management_api_stub.h @@ -56,6 +56,7 @@ class ManagementApiStub : public DoNotCopyOrMove { mutable std::mutex mutex_; std::shared_ptr channel_; + static const std::chrono::milliseconds stop_waiting_timeout; }; } // namespace container } // namespace anbox diff --git a/src/anbox/graphics/emugl/RenderControl.cpp b/src/anbox/graphics/emugl/RenderControl.cpp index 26e9559..2a2c453 100644 --- a/src/anbox/graphics/emugl/RenderControl.cpp +++ b/src/anbox/graphics/emugl/RenderControl.cpp @@ -26,9 +26,9 @@ #include "external/android-emugl/shared/OpenglCodecCommon/ChecksumCalculatorThreadInfo.h" #include "external/android-emugl/host/include/OpenGLESDispatch/EGLDispatch.h" - #include #include +#include static const GLint rendererVersion = 1; static std::shared_ptr composer; @@ -55,53 +55,61 @@ static EGLint rcGetEGLVersion(EGLint *major, EGLint *minor) { return EGL_TRUE; } -static EGLint rcQueryEGLString(EGLenum name, void *buffer, EGLint bufferSize) { +static std::string filter_extensions(const std::string& extensions, const std::vector& whitelist) { + std::stringstream approved_extensions; + auto extension_list = anbox::utils::string_split(extensions, ' '); + for (const auto& ext : extension_list) { + if (std::find(whitelist.begin(), whitelist.end(), ext) == whitelist.end()) + continue; + + if (approved_extensions.tellp() > 0) + approved_extensions << " "; + + approved_extensions << ext; + } + return approved_extensions.str(); +} + +static EGLint rcQueryEGLString(EGLenum name, void* buffer, EGLint bufferSize) { if (!renderer) return 0; - auto result = s_egl.eglQueryString(renderer->getDisplay(), name); - if (!result) + std::string result = s_egl.eglQueryString(renderer->getDisplay(), name); + if (result.empty()) return 0; - std::string approved_result = result; - - // We need to drop a few extensions from the list reported by the driver - // as not all are well enough support by our EGL/GLES stack. if (name == EGL_EXTENSIONS) { - std::vector common_unsupported_extensions = { - // Leads to crashes on the Android side when SurfaceFlinger initializes - // EGL/GLES and it queries surfaces for available attributes. - "EGL_EXT_buffer_age" + // We need to drop a few extensions from the list reported by the driver + // as not all are well enough support by our EGL implementation. + std::vector whitelisted_extensions = { + "EGL_KHR_image_base", + "EGL_KHR_gl_texture_2D_image", }; - - for (const auto &extension : common_unsupported_extensions) { - size_t start_pos = approved_result.find(extension); - if (start_pos == std::string::npos) continue; - approved_result.replace(start_pos, extension.length(), ""); - } + result = filter_extensions(result, whitelisted_extensions); } - int len = approved_result.length() + 1; + int len = result.length() + 1; if (!buffer || len > bufferSize) { return -len; } - strcpy(static_cast(buffer), approved_result.c_str()); + strcpy(static_cast(buffer), result.c_str()); return len; } -static EGLint rcGetGLString(EGLenum name, void *buffer, EGLint bufferSize) { - RenderThreadInfo *tInfo = RenderThreadInfo::get(); +static EGLint rcGetGLString(EGLenum name, void* buffer, EGLint bufferSize) { + RenderThreadInfo* tInfo = RenderThreadInfo::get(); std::string result; if (tInfo && tInfo->currContext) { - const char *str = nullptr; + const char* str = nullptr; if (tInfo->currContext->isGL2()) - str = reinterpret_cast(s_gles2.glGetString(name)); + str = reinterpret_cast(s_gles2.glGetString(name)); else - str = reinterpret_cast(s_gles1.glGetString(name)); + str = reinterpret_cast(s_gles1.glGetString(name)); - if (str) result += str; + if (str) + result += str; } // We're forcing version 2.0 no matter what the host provides as @@ -113,27 +121,37 @@ static EGLint rcGetGLString(EGLenum name, void *buffer, EGLint bufferSize) { if (name == GL_VERSION) result = "OpenGL ES 2.0"; else if (name == GL_EXTENSIONS) { - std::string approved_extensions = result; - std::vector unsupported_extensions = { - // Leaving this enabled gives crippeled text rendering when - // using the host mesa GLES drivers. - "GL_EXT_unpack_subimage", + // We need to drop a few extensions from the list reported by the driver + // as not all are well enough support by our GL implementation. + std::vector whitelisted_extensions = { + "GL_OES_EGL_image", + "GL_OES_EGL_image_external", + "GL_OES_depth24", + "GL_OES_depth32", + "GL_OES_element_index_uint", + "GL_OES_texture_float", + "GL_OES_texture_float_linear", + "GL_OES_compressed_paletted_texture", + "GL_OES_compressed_ETC1_RGB8_texture", + "GL_OES_depth_texture", + "GL_OES_texture_half_float", + "GL_OES_texture_half_float_linear", + "GL_OES_packed_depth_stencil", + "GL_OES_vertex_half_float", + "GL_OES_standard_derivatives", + "GL_OES_texture_npot", + "GL_OES_rgb8_rgba8", }; - for (const auto &extension : unsupported_extensions) { - size_t start_pos = approved_extensions.find(extension); - if (start_pos == std::string::npos) continue; - approved_extensions.replace(start_pos, extension.length(), ""); - } - - result = approved_extensions; + result = filter_extensions(result, whitelisted_extensions); } int nextBufferSize = result.size() + 1; - if (!buffer || nextBufferSize > bufferSize) return -nextBufferSize; + if (!buffer || nextBufferSize > bufferSize) + return -nextBufferSize; - snprintf(static_cast(buffer), nextBufferSize, "%s", result.c_str()); + snprintf(static_cast(buffer), nextBufferSize, "%s", result.c_str()); return nextBufferSize; } diff --git a/src/anbox/graphics/emugl/RenderThread.cpp b/src/anbox/graphics/emugl/RenderThread.cpp index 7e6dff7..7c8e4e6 100644 --- a/src/anbox/graphics/emugl/RenderThread.cpp +++ b/src/anbox/graphics/emugl/RenderThread.cpp @@ -84,8 +84,12 @@ intptr_t RenderThread::main() { } } while (progress); + } + threadInfo.m_gl2Dec.freeShader(); + threadInfo.m_gl2Dec.freeProgram(); + // Release references to the current thread's context/surfaces if any renderer_->bindContext(0, 0, 0); if (threadInfo.currContext || threadInfo.currDrawSurf || threadInfo.currReadSurf) diff --git a/src/anbox/graphics/emugl/Renderer.cpp b/src/anbox/graphics/emugl/Renderer.cpp index a807131..98d26cc 100644 --- a/src/anbox/graphics/emugl/Renderer.cpp +++ b/src/anbox/graphics/emugl/Renderer.cpp @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#define GLM_ENABLE_EXPERIMENTAL #include "anbox/graphics/emugl/Renderer.h" #include "anbox/graphics/emugl/DispatchTables.h" #include "anbox/graphics/emugl/RenderThreadInfo.h" diff --git a/src/anbox/network/base_socket_messenger.cpp b/src/anbox/network/base_socket_messenger.cpp index fb093f3..23efc78 100644 --- a/src/anbox/network/base_socket_messenger.cpp +++ b/src/anbox/network/base_socket_messenger.cpp @@ -138,7 +138,7 @@ unsigned short BaseSocketMessenger::local_port() const { template void BaseSocketMessenger::set_no_delay() { - const auto fd = socket->native(); + const auto fd = socket->native_handle(); int flag = 1; const auto ret = ::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, diff --git a/src/anbox/qemu/qemud_message_processor.cpp b/src/anbox/qemu/qemud_message_processor.cpp index c9d5b50..b47f078 100644 --- a/src/anbox/qemu/qemud_message_processor.cpp +++ b/src/anbox/qemu/qemud_message_processor.cpp @@ -51,7 +51,6 @@ void QemudMessageProcessor::process_commands() { unsigned int body_size = 0; ::sscanf(header, "%04x", &body_size); - if (body_size != buffer_.size() - header_size) break; std::string command; // Make sure we only copy as much bytes as we have to and not more @@ -71,7 +70,7 @@ void QemudMessageProcessor::process_commands() { void QemudMessageProcessor::send_header(const size_t &size) { char header[header_size + 1]; - std::snprintf(header, header_size + 1, "%04lx", size); + std::snprintf(header, header_size + 1, "%04zx", size); messenger_->send(header, header_size); } diff --git a/src/anbox/runtime.cpp b/src/anbox/runtime.cpp index cbfefa7..90c6768 100644 --- a/src/anbox/runtime.cpp +++ b/src/anbox/runtime.cpp @@ -53,7 +53,13 @@ std::shared_ptr Runtime::create(std::uint32_t pool_size) { Runtime::Runtime(std::uint32_t pool_size) : pool_size_{pool_size}, + + #if BOOST_VERSION >= 106600 + service_{static_cast(pool_size_)}, + #else service_{pool_size_}, + #endif + strand_{service_}, keep_alive_{service_} {} diff --git a/src/anbox/runtime.h b/src/anbox/runtime.h index 43065be..ea521e3 100644 --- a/src/anbox/runtime.h +++ b/src/anbox/runtime.h @@ -19,6 +19,7 @@ #define ANBOX_RUNTIME_H_ #include +#include #include #include