diff --git a/CMakeLists.txt b/CMakeLists.txt index b59987c..5cd7c13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,12 @@ pkg_check_modules(LXC lxc REQUIRED) pkg_check_modules(PROPERTIES_CPP properties-cpp REQUIRED) pkg_check_modules(LIBSYSTEMD libsystemd REQUIRED) +message(STATUS "LXC version: ${LXC_VERSION}") +if (${LXC_VERSION} VERSION_LESS 3.0) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_LXC2_SUPPORT") + message(STATUS "Building with LXC 2.x compatibility support") +endif() + option(ENABLE_WAYLAND "Enable wayland support" ON) if (ENABLE_WAYLAND) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWAYLAND_SUPPORT") diff --git a/android/camera/media_codecs.xml b/android/media/media_codecs.xml similarity index 98% rename from android/camera/media_codecs.xml rename to android/media/media_codecs.xml index 87d11f2..ee846da 100644 --- a/android/camera/media_codecs.xml +++ b/android/media/media_codecs.xml @@ -80,5 +80,6 @@ Only the three quirks included above are recognized at this point: + diff --git a/android/media/media_codecs_google_audio.xml b/android/media/media_codecs_google_audio.xml new file mode 100644 index 0000000..632088a --- /dev/null +++ b/android/media/media_codecs_google_audio.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/media/media_codecs_google_telephony.xml b/android/media/media_codecs_google_telephony.xml new file mode 100644 index 0000000..5ad90d9 --- /dev/null +++ b/android/media/media_codecs_google_telephony.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + diff --git a/android/media/media_codecs_google_tv.xml b/android/media/media_codecs_google_tv.xml new file mode 100644 index 0000000..330c6fb --- /dev/null +++ b/android/media/media_codecs_google_tv.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + diff --git a/android/media/media_codecs_google_video.xml b/android/media/media_codecs_google_video.xml new file mode 100644 index 0000000..829f403 --- /dev/null +++ b/android/media/media_codecs_google_video.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/camera/media_profiles.xml b/android/media/media_profiles.xml similarity index 100% rename from android/camera/media_profiles.xml rename to android/media/media_profiles.xml diff --git a/products/anbox.mk b/products/anbox.mk index 73fd1a9..6ab2330 100644 --- a/products/anbox.mk +++ b/products/anbox.mk @@ -43,8 +43,12 @@ PRODUCT_COPY_FILES += \ vendor/anbox/android/init.goldfish.rc:root/init.goldfish.rc \ vendor/anbox/android/init.goldfish.sh:system/etc/init.goldfish.sh \ vendor/anbox/android/ueventd.goldfish.rc:root/ueventd.goldfish.rc \ - vendor/anbox/android/camera/media_profiles.xml:system/etc/media_profiles.xml \ - vendor/anbox/android/camera/media_codecs.xml:system/etc/media_codecs.xml \ + vendor/anbox/android/media/media_profiles.xml:system/etc/media_profiles.xml \ + vendor/anbox/android/media/media_codecs.xml:system/etc/media_codecs.xml \ + vendor/anbox/android/media/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \ + vendor/anbox/android/media/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \ + vendor/anbox/android/media/media_codecs_google_tv.xml:system/etc/media_codecs_google_tv.xml \ + vendor/anbox/android/media/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \ hardware/libhardware_legacy/audio/audio_policy.conf:system/etc/audio_policy.conf PRODUCT_CHARACTERISTICS := emulator diff --git a/src/anbox/cmds/check_features.cpp b/src/anbox/cmds/check_features.cpp index 686277b..4b6f448 100644 --- a/src/anbox/cmds/check_features.cpp +++ b/src/anbox/cmds/check_features.cpp @@ -36,6 +36,14 @@ std::vector cpu_whitelist = { "M 460", // Intel Celeron N2840 "N2840", + // Intel Core i7 Q720 + "Q 720", + // Intel Pentium T4500 + "T4500", + // Intel Core i7 Q720 + "Q 720", + // Intel Xeon E5520 + "E5520" }; } // namespace @@ -44,7 +52,7 @@ anbox::cmds::CheckFeatures::CheckFeatures() cli::Name{"check-features"}, cli::Usage{"check-features"}, cli::Description{"Check that the host system supports all necessary features"}} { - action([](const cli::Command::Context&) { + action([this](const cli::Command::Context&) { #if defined(CPU_FEATURES_ARCH_X86) const auto info = cpu_features::GetX86Info(); std::vector missing_features; @@ -70,7 +78,7 @@ anbox::cmds::CheckFeatures::CheckFeatures() } } - if (missing_features.size() > 0 && !is_whitelisted) { + if (missing_features.size() > 0 && !is_whitelisted && !sanity_check_for_features()) { std::cerr << "The CPU of your computer (" << brand_string << ") does not support all" << std::endl << "features Anbox requires." << std::endl << "It is missing support for the following features: "; @@ -97,3 +105,32 @@ anbox::cmds::CheckFeatures::CheckFeatures() #endif }); } + +// In case that the CPU supports AVX we take the decision as from our analysis +// of the output from the cpu_features library. If it does not we have to check +// further via the compiler builtins if we the CPU supports all mandatory features +// or not. In case that any is missing we will fail the test. +// +// This uses the compiler builtin function __builtin_cpu_supports which allows us +// to detect certain CPU features. +// See https://gcc.gnu.org/onlinedocs/gcc/x86-Built-in-Functions.html +bool anbox::cmds::CheckFeatures::sanity_check_for_features() { +#if defined(CPU_FEATURES_ARCH_X86) + if (__builtin_cpu_supports("avx")) + return true; + + std::vector missing_features; + +#define CHECK_FEATURE(name) \ + if (!__builtin_cpu_supports(name)) \ + missing_features.push_back(name); + + CHECK_FEATURE("sse4.1"); + CHECK_FEATURE("sse4.2"); + CHECK_FEATURE("ssse3"); + + return missing_features.empty(); +#else + return true; +#endif +} diff --git a/src/anbox/cmds/check_features.h b/src/anbox/cmds/check_features.h index e6c6ff7..8402ca6 100644 --- a/src/anbox/cmds/check_features.h +++ b/src/anbox/cmds/check_features.h @@ -29,6 +29,9 @@ namespace cmds { class CheckFeatures : public cli::CommandWithFlagsAndAction { public: CheckFeatures(); + + private: + bool sanity_check_for_features(); }; } // namespace cmds } // namespace anbox diff --git a/src/anbox/container/lxc_container.cpp b/src/anbox/container/lxc_container.cpp index 2bcec12..6ab8c26 100644 --- a/src/anbox/container/lxc_container.cpp +++ b/src/anbox/container/lxc_container.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,36 @@ 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"}; +#ifdef ENABLE_LXC2_SUPPORT +constexpr const char *lxc_config_idmap_key{"lxc.id_map"}; +constexpr const char *lxc_config_net_type_key{"lxc.network.type"}; +constexpr const char *lxc_config_net_flags_key{"lxc.network.flags"}; +constexpr const char *lxc_config_net_link_key{"lxc.network.link"}; +constexpr const char *lxc_config_pty_max_key{"lxc.pts"}; +constexpr const char *lxc_config_tty_max_key{"lxc.tty"}; +constexpr const char *lxc_config_uts_name_key{"lxc.utsname"}; +constexpr const char *lxc_config_tty_dir_key{"lxc.devttydir"}; +constexpr const char *lxc_config_init_cmd_key{"lxc.init_cmd"}; +constexpr const char *lxc_config_rootfs_path_key{"lxc.rootfs"}; +constexpr const char *lxc_config_log_level_key{"lxc.loglevel"}; +constexpr const char *lxc_config_log_file_key{"lxc.logfile"}; +constexpr const char *lxc_config_apparmor_profile_key{"lxc.aa_profile"}; +#else +constexpr const char *lxc_config_idmap_key{"lxc.idmap"}; +constexpr const char *lxc_config_net_type_key{"lxc.net.0.type"}; +constexpr const char *lxc_config_net_flags_key{"lxc.net.0.flags"}; +constexpr const char *lxc_config_net_link_key{"lxc.net.0.link"}; +constexpr const char *lxc_config_pty_max_key{"lxc.pty.max"}; +constexpr const char *lxc_config_tty_max_key{"lxc.tty.max"}; +constexpr const char *lxc_config_uts_name_key{"lxc.uts.name"}; +constexpr const char *lxc_config_tty_dir_key{"lxc.tty.dir"}; +constexpr const char *lxc_config_init_cmd_key{"lxc.init.cmd"}; +constexpr const char *lxc_config_rootfs_path_key{"lxc.rootfs.path"}; +constexpr const char *lxc_config_log_level_key{"lxc.log.level"}; +constexpr const char *lxc_config_log_file_key{"lxc.log.file"}; +constexpr const char *lxc_config_apparmor_profile_key{"lxc.apparmor.profile"}; +#endif + constexpr int device_major(__dev_t dev) { return int(((dev >> 8) & 0xfff) | ((dev >> 32) & (0xfffff000))); } @@ -87,19 +118,19 @@ void LxcContainer::setup_id_map() { const auto base_id = unprivileged_uid; const auto max_id = 65536; - set_config_item("lxc.idmap", utils::string_format("u 0 %d %d", base_id, android_system_uid - 1)); - set_config_item("lxc.idmap", utils::string_format("g 0 %d %d", base_id, android_system_uid - 1)); + set_config_item(lxc_config_idmap_key, utils::string_format("u 0 %d %d", base_id, android_system_uid - 1)); + set_config_item(lxc_config_idmap_key, utils::string_format("g 0 %d %d", base_id, android_system_uid - 1)); // We need to bind the user id for the one running the client side // process as he is the owner of various socket files we bind mount // into the container. - set_config_item("lxc.idmap", utils::string_format("u %d %d 1", android_system_uid, creds_.uid())); - set_config_item("lxc.idmap", utils::string_format("g %d %d 1", android_system_uid, creds_.gid())); + set_config_item(lxc_config_idmap_key, utils::string_format("u %d %d 1", android_system_uid, creds_.uid())); + set_config_item(lxc_config_idmap_key, utils::string_format("g %d %d 1", android_system_uid, creds_.gid())); - set_config_item("lxc.idmap", utils::string_format("u %d %d %d", android_system_uid + 1, + set_config_item(lxc_config_idmap_key, utils::string_format("u %d %d %d", android_system_uid + 1, base_id + android_system_uid + 1, max_id - creds_.uid() - 1)); - set_config_item("lxc.idmap", utils::string_format("g %d %d %d", android_system_uid + 1, + set_config_item(lxc_config_idmap_key, utils::string_format("g %d %d %d", android_system_uid + 1, base_id + android_system_uid + 1, max_id - creds_.gid() - 1)); } @@ -110,9 +141,9 @@ void LxcContainer::setup_network() { return; } - set_config_item("lxc.net.0.type", "veth"); - set_config_item("lxc.net.0.flags", "up"); - set_config_item("lxc.net.0.link", "anbox0"); + set_config_item(lxc_config_net_type_key, "veth"); + set_config_item(lxc_config_net_flags_key, "up"); + set_config_item(lxc_config_net_link_key, "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 @@ -271,22 +302,21 @@ void LxcContainer::start(const Configuration &configuration) { set_config_item("lxc.mount.auto", "proc:mixed sys:mixed cgroup:mixed"); set_config_item("lxc.autodev", "1"); - set_config_item("lxc.pty.max", "1024"); - set_config_item("lxc.tty.max", "0"); - set_config_item("lxc.uts.name", "anbox"); + set_config_item(lxc_config_pty_max_key, "1024"); + set_config_item(lxc_config_tty_max_key, "0"); + set_config_item(lxc_config_uts_name_key, "anbox"); set_config_item("lxc.group.devices.deny", ""); set_config_item("lxc.group.devices.allow", ""); // We can't move bind-mounts, so don't use /dev/lxc/ - set_config_item("lxc.tty.dir", ""); + set_config_item(lxc_config_tty_dir_key, ""); - set_config_item("lxc.environment", - "PATH=/system/bin:/system/sbin:/system/xbin"); + set_config_item("lxc.environment", "PATH=/system/bin:/system/sbin:/system/xbin"); - set_config_item("lxc.init.cmd", "/anbox-init.sh"); + set_config_item(lxc_config_init_cmd_key, "/anbox-init.sh"); -#if ENABLE_SNAP_CONFINEMENT +#ifdef ENABLE_SNAP_CONFINEMENT // If we're running inside the snap environment snap-confine already created a // cgroup for us we need to use as otherwise presevering a namespace wont help. if (utils::is_env_set("SNAP")) @@ -298,25 +328,28 @@ void LxcContainer::start(const Configuration &configuration) { rootfs_path = SystemConfiguration::instance().combined_rootfs_dir(); DEBUG("Using rootfs path %s", rootfs_path); - set_config_item("lxc.rootfs.path", rootfs_path); + set_config_item(lxc_config_rootfs_path_key, rootfs_path); - set_config_item("lxc.log.level", "0"); + set_config_item(lxc_config_log_level_key, "0"); const auto log_path = SystemConfiguration::instance().log_dir(); - set_config_item("lxc.log.file", utils::string_format("%s/container.log", log_path).c_str()); + set_config_item(lxc_config_log_file_key, utils::string_format("%s/container.log", log_path).c_str()); + +#ifndef ENABLE_LXC2_SUPPORT + // Dump the console output to disk to have a chance to debug early boot problems + set_config_item("lxc.console.logfile", utils::string_format("%s/console.log", log_path).c_str()); + set_config_item("lxc.console.rotate", "1"); +#endif - // Dump the console output to disk to have a chance to debug early boot problems - set_config_item("lxc.console.logfile", utils::string_format("%s/console.log", log_path).c_str()); - set_config_item("lxc.console.rotate", "1"); setup_network(); -#if ENABLE_SNAP_CONFINEMENT +#ifdef ENABLE_SNAP_CONFINEMENT // We take the AppArmor profile snapd has defined for us as part of the // anbox-support interface. The container manager itself runs within a // child profile snap.anbox.container-manager//lxc too. set_config_item("lxc.apparmor.profile", "snap.anbox.container-manager//container"); #else - set_config_item("lxc.apparmor.profile", "unconfined"); + set_config_item(lxc_config_apparmor_profile_key, "unconfined"); #endif if (!privileged_) diff --git a/src/anbox/platform/sdl/window.cpp b/src/anbox/platform/sdl/window.cpp index a5806a9..752b13c 100644 --- a/src/anbox/platform/sdl/window.cpp +++ b/src/anbox/platform/sdl/window.cpp @@ -72,8 +72,9 @@ Window::Window(const std::shared_ptr &renderer, BOOST_THROW_EXCEPTION(std::runtime_error(message)); } - if (SDL_SetWindowHitTest(window_, &Window::on_window_hit, this) < 0) - BOOST_THROW_EXCEPTION(std::runtime_error("Failed to register for window hit test")); + if (utils::get_env_value("ANBOX_NO_SDL_WINDOW_HIT_TEST", "false") == "false") + if (SDL_SetWindowHitTest(window_, &Window::on_window_hit, this) < 0) + BOOST_THROW_EXCEPTION(std::runtime_error("Failed to register for window hit test")); SDL_SysWMinfo info; SDL_VERSION(&info.version);