diff --git a/nixos/modules/virtualisation/anbox.nix b/nixos/modules/virtualisation/anbox.nix index 7b096bd1a9fbb..65219c0739ba0 100644 --- a/nixos/modules/virtualisation/anbox.nix +++ b/nixos/modules/virtualisation/anbox.nix @@ -5,7 +5,11 @@ with lib; let cfg = config.virtualisation.anbox; - kernelPackages = config.boot.kernelPackages; + inherit (config.boot) kernelPackages; + inherit (kernelPackages) kernel; + + # Inverted condition from `meta.broken` on `kernelPackages.anbox`. + useAnboxModules = kernel.kernelAtLeast "4.4" && kernel.kernelOlder "5.5"; addrOpts = v: addr: pref: name: { address = mkOption { default = addr; @@ -25,6 +29,28 @@ let }; }; + finalImage = if cfg.imageModifications == "" then cfg.image else ( pkgs.callPackage ( + { runCommandNoCC, squashfsTools }: + + runCommandNoCC "${cfg.image.name}-modified.img" { + nativeBuildInputs = [ + squashfsTools + ]; + } '' + echo "→ Extracting Anbox root image..." + unsquashfs -dest rootfs ${cfg.image} + + echo "→ Modifying Anbox root image..." + ( + cd rootfs + ${cfg.imageModifications} + ) + + echo "→ Packing modified Anbox root image..." + mksquashfs rootfs $out -comp xz -no-xattrs -all-root + '' + ) { }); + in { @@ -42,6 +68,18 @@ in ''; }; + imageModifications = mkOption { + default = ""; + type = types.lines; + description = '' + Commands to edit the image filesystem. + + This can be used to e.g. bundle a privileged F-Droid. + + Commands are ran with PWD being at the root of the filesystem. + ''; + }; + extraInit = mkOption { type = types.lines; default = ""; @@ -67,19 +105,34 @@ in config = mkIf cfg.enable { assertions = singleton { - assertion = versionAtLeast (getVersion config.boot.kernelPackages.kernel) "4.18"; + assertion = kernelPackages.kernelAtLeast "4.18"; message = "Anbox needs user namespace support to work properly"; }; environment.systemPackages = with pkgs; [ anbox ]; - boot.kernelModules = [ "ashmem_linux" "binder_linux" ]; - boot.extraModulePackages = [ kernelPackages.anbox ]; - - services.udev.extraRules = '' - KERNEL=="ashmem", NAME="%k", MODE="0666" - KERNEL=="binder*", NAME="%k", MODE="0666" - ''; + # Mainline ashmem/binder drivers not available as modules + boot.kernelModules = optionals useAnboxModules [ "ashmem_linux" "binder_linux" ]; + boot.extraModulePackages = optional useAnboxModules kernelPackages.anbox; + + system.requiredKernelConfig = with config.lib.kernelConfig; mkIf (kernel.kernelOlder "5.5") [ + (isEnabled "ASHMEM") + (isEnabled "ANDROID") + (isEnabled "ANDROID_BINDER_IPC") + (isEnabled "ANDROID_BINDERFS") + # It is currently impossible to check for this with `lib.kernelConfig`. + # Though the default is fine: + # https://github.com/torvalds/linux/blob/f88cd3fb9df228e5ce4e13ec3dbad671ddb2146e/drivers/android/Kconfig#L35-L45 + # ANDROID_BINDER_DEVICES binder,hwbinder,vndbinder + ]; + + systemd.mounts = optional (!useAnboxModules) { + requiredBy = [ "anbox-container-manager.service" ]; + description = "Anbox Binder File System"; + what = "binder"; + where = "/dev/binderfs"; + type = "binder"; + }; virtualisation.lxc.enable = true; networking.bridges.anbox0.interfaces = []; @@ -90,6 +143,11 @@ in internalInterfaces = [ "anbox0" ]; }; + # Ensures NetworkManager doesn't touch anbox0 + networking.networkmanager.unmanaged = [ + "anbox0" + ]; + systemd.services.anbox-container-manager = let anboxloc = "/var/lib/anbox"; in { @@ -124,12 +182,13 @@ in ExecStart = '' ${pkgs.anbox}/bin/anbox container-manager \ --data-path=${anboxloc} \ - --android-image=${cfg.image} \ + --android-image=${finalImage} \ --container-network-address=${cfg.ipv4.container.address} \ --container-network-gateway=${cfg.ipv4.gateway.address} \ --container-network-dns-servers=${cfg.ipv4.dns} \ --use-rootfs-overlay \ - --privileged + --privileged \ + --daemon ''; }; }; diff --git a/nixos/tests/anbox.nix b/nixos/tests/anbox.nix new file mode 100644 index 0000000000000..6522720d9530a --- /dev/null +++ b/nixos/tests/anbox.nix @@ -0,0 +1,40 @@ +import ./make-test-python.nix ({ pkgs, ... }: + +{ + name = "anbox"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ mvnetbiz ]; + }; + + machine = { pkgs, config, ... }: { + imports = [ + ./common/user-account.nix + ./common/x11.nix + ]; + + environment.systemPackages = with pkgs; [ android-tools ]; + + test-support.displayManager.auto.user = "alice"; + + virtualisation.anbox.enable = true; + # The AArch64 anbox image will not start. + # Meanwhile the postmarketOS images work just fine. + virtualisation.anbox.image = pkgs.anbox-postmarketos-image; + virtualisation.memorySize = 2500; + }; + + testScript = { nodes, ... }: let + user = nodes.machine.config.users.users.alice; + bus = "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${toString user.uid}/bus"; + in '' + machine.wait_for_x() + + machine.wait_until_succeeds( + "sudo -iu alice ${bus} anbox wait-ready" + ) + + machine.wait_until_succeeds("adb shell true") + + print(machine.succeed("adb devices")) + ''; +}) diff --git a/pkgs/os-specific/linux/anbox/0001-NixOS-Use-anbox-from-PATH-in-desktop-files.patch b/pkgs/os-specific/linux/anbox/0001-NixOS-Use-anbox-from-PATH-in-desktop-files.patch new file mode 100644 index 0000000000000..1c3450238c7f6 --- /dev/null +++ b/pkgs/os-specific/linux/anbox/0001-NixOS-Use-anbox-from-PATH-in-desktop-files.patch @@ -0,0 +1,34 @@ +From cb61e856c4357d9787f7a2313bacb1c3b2133d36 Mon Sep 17 00:00:00 2001 +From: Samuel Dionne-Riel +Date: Fri, 4 Jun 2021 19:05:53 -0400 +Subject: [PATCH] [NixOS] Use `anbox` from PATH in desktop files + +--- + src/anbox/application/launcher_storage.cpp | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/src/anbox/application/launcher_storage.cpp b/src/anbox/application/launcher_storage.cpp +index d5053cf..a4be719 100644 +--- a/src/anbox/application/launcher_storage.cpp ++++ b/src/anbox/application/launcher_storage.cpp +@@ -69,9 +69,7 @@ void LauncherStorage::add_or_update(const Database::Item &item) { + auto package_name = item.package; + std::replace(package_name.begin(), package_name.end(), '.', '-'); + +- auto exe_path = utils::process_get_exe_path(getpid()); +- if (utils::get_env_value("SNAP").length() > 0) +- exe_path = snap_exe_path; ++ auto exe_path = "anbox"; + + std::string exec = utils::string_format("%s launch ", exe_path); + +@@ -121,4 +119,4 @@ void LauncherStorage::remove(const Database::Item &item) { + fs::remove(item_icon_path); + } + +-} +\ No newline at end of file ++} +-- +2.29.2 + diff --git a/pkgs/os-specific/linux/anbox/default.nix b/pkgs/os-specific/linux/anbox/default.nix index d684e24db9148..7a8118e38e5ec 100644 --- a/pkgs/os-specific/linux/anbox/default.nix +++ b/pkgs/os-specific/linux/anbox/default.nix @@ -1,4 +1,5 @@ { lib, stdenv, fetchFromGitHub, fetchurl +, fetchpatch , cmake, pkg-config, dbus, makeWrapper , boost , elfutils # for libdw @@ -22,7 +23,7 @@ , SDL2_image , systemd , writeText -, writeScript +, writeShellScript }: let @@ -33,29 +34,22 @@ let Exec=@out@/libexec/anbox-session-manager ''; - anbox-application-manager = writeScript "anbox-application-manager" '' - #!${runtimeShell} - - ${systemd}/bin/busctl --user call \ - org.freedesktop.DBus \ - /org/freedesktop/DBus \ - org.freedesktop.DBus \ - StartServiceByName "su" org.anbox 0 - - @out@/bin/anbox launch --package=org.anbox.appmgr --component=org.anbox.appmgr.AppViewActivity + anbox-application-manager = writeShellScript "anbox-application-manager" '' + exec @out@/bin/anbox launch --package=org.anbox.appmgr --component=org.anbox.appmgr.AppViewActivity ''; in stdenv.mkDerivation rec { pname = "anbox"; - version = "unstable-2020-11-29"; + version = "unstable-2021-05-26"; src = fetchFromGitHub { owner = pname; repo = pname; - rev = "6c10125a7f13908d2cbe56d2d9ab09872755f265"; - sha256 = "00bqssh4zcs0jj6w07b91719xkrpdw75vpcplwrvlhwsvl55f901"; + rev = "ad377ff25354d68b76e2b8da24a404850f8514c6"; + sha256 = "1bj07ixwbkli4ycjh41mnqdbsjz9haiwg2nhf9anbi29z1d0819w"; + fetchSubmodules = true; }; @@ -85,7 +79,7 @@ stdenv.mkDerivation rec { systemd ]; - patchPhase = '' + prePatch = '' patchShebangs scripts cat >cmake/FindGMock.cmake <<'EOF' @@ -113,8 +107,30 @@ stdenv.mkDerivation rec { EOF ''; + patches = [ + # Fixes compatibility with lxc 4 + (fetchpatch { + url = "https://git.alpinelinux.org/aports/plain/community/anbox/lxc4.patch?id=64243590a16aee8d4e72061886fc1b15256492c3"; + sha256 = "1da5xyzyjza1g2q9nbxb4p3njj2sf3q71vkpvmmdphia5qnb0gk5"; + }) + # Wait 10× more time when starting + # Not *strictly* needed, but helps a lot on slower hardware + (fetchpatch { + url = "https://git.alpinelinux.org/aports/plain/community/anbox/give-more-time-to-start.patch?id=058b56d4b332ef3379551b343bf31e0f2004321a"; + sha256 = "0iiz3c7fgfgl0dvx8sf5hv7a961xqnihwpz6j8r0ib9v8piwxh9a"; + }) + # Ensures generated desktop files work on store path change + ./0001-NixOS-Use-anbox-from-PATH-in-desktop-files.patch + # Provide window icons + (fetchpatch { + url = "https://github.com/samueldr/anbox/commit/2387f4fcffc0e19e52e58fb6f8264fbe87aafe4d.patch"; + sha256 = "12lmr0kxw1n68g3abh1ak5awmpczfh75c26f53jc8qpvdvv1ywha"; + }) + ]; + postInstall = '' wrapProgram $out/bin/anbox \ + --set SDL_VIDEO_X11_WMCLASS "anbox" \ --prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [libGL libglvnd]} \ --prefix PATH : ${git}/bin @@ -128,6 +144,7 @@ stdenv.mkDerivation rec { substitute ${anbox-application-manager} $out/bin/anbox-application-manager \ --subst-var out + chmod +x $out/bin/anbox-application-manager ''; passthru.image = let @@ -152,7 +169,7 @@ stdenv.mkDerivation rec { homepage = "https://anbox.io"; description = "Android in a box"; license = licenses.gpl2; - maintainers = with maintainers; [ edwtjo ]; + maintainers = with maintainers; [ edwtjo samueldr ]; platforms = [ "armv7l-linux" "aarch64-linux" "x86_64-linux" ]; }; diff --git a/pkgs/os-specific/linux/anbox/postmarketos-image.nix b/pkgs/os-specific/linux/anbox/postmarketos-image.nix new file mode 100644 index 0000000000000..d11ac5d722639 --- /dev/null +++ b/pkgs/os-specific/linux/anbox/postmarketos-image.nix @@ -0,0 +1,19 @@ +{ stdenv, fetchurl }: + +let + imgroot = "http://anbox.postmarketos.org"; +in + { + armv7l-linux = fetchurl { + url = imgroot + "/android-7.1.2_r39.1-anbox_armv7a_neon-userdebug.img"; + sha256 = "1bgzqw4yp52a2q40dr1jlay1nh73jl5mx6wqsxvpb09xghxsng0a"; + }; + aarch64-linux = fetchurl { + url = imgroot + "/android-7.1.2_r39-anbox_arm64-userdebug.img"; + sha256 = "0dx8mhfcjbkak982zfh65bvy35slz5jk31yl4ara50ryrxsp32nx"; + }; + x86_64-linux = fetchurl { + url = imgroot + "/android-7.1.2_r39-anbox_x86_64-userdebug.img"; + sha256 = "16vmiz5al2r19wjpd44nagvz7d901ljxdms8gjp2w4xz1d91vzpm"; + }; + }.${stdenv.system} diff --git a/pkgs/os-specific/linux/kernel/common-config.nix b/pkgs/os-specific/linux/kernel/common-config.nix index 776a422df735b..c887134108258 100644 --- a/pkgs/os-specific/linux/kernel/common-config.nix +++ b/pkgs/os-specific/linux/kernel/common-config.nix @@ -845,6 +845,12 @@ let X86_AMD_PLATFORM_DEVICE = yes; + ASHMEM = { optional = true; tristate = whenAtLeast "5.0" "y";}; + ANDROID = { optional = true; tristate = whenAtLeast "5.0" "y";}; + ANDROID_BINDER_IPC = { optional = true; tristate = whenAtLeast "5.0" "y";}; + ANDROID_BINDERFS = { optional = true; tristate = whenAtLeast "5.0" "y";}; + ANDROID_BINDER_DEVICES = { optional = true; freeform = whenAtLeast "5.0" "binder,hwbinder,vndbinder";}; + } // optionalAttrs (stdenv.hostPlatform.system == "x86_64-linux" || stdenv.hostPlatform.system == "aarch64-linux") { # Enable CPU/memory hotplug support # Allows you to dynamically add & remove CPUs/memory to a VM client running NixOS without requiring a reboot diff --git a/pkgs/os-specific/linux/lxc/default.nix b/pkgs/os-specific/linux/lxc/default.nix index bad7622771aaa..8870be0159089 100644 --- a/pkgs/os-specific/linux/lxc/default.nix +++ b/pkgs/os-specific/linux/lxc/default.nix @@ -1,4 +1,4 @@ -{ lib, stdenv, fetchurl, autoreconfHook, pkg-config, perl, docbook2x +{ lib, stdenv, fetchpatch, fetchurl, autoreconfHook, pkg-config, perl, docbook2x , docbook_xml_dtd_45, python3Packages, pam # Optional Dependencies @@ -26,6 +26,13 @@ stdenv.mkDerivation rec { patches = [ ./support-db2x.patch + + # 4.0.10 hopefully will have the patch... + # https://github.com/lxc/lxc/pull/3844 + (fetchpatch { + url = "https://github.com/lxc/lxc/commit/e859a5ee2cdee5111185a6a629f891aa40b2ffd6.patch"; + sha256 = "076q3rdrs2pixzj85837frkr9ahhlcvp5bcnigjpj8g04siywg97"; + }) ]; postPatch = '' diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 03b740db2fa60..b9909da03ed9d 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -1707,6 +1707,8 @@ in anbox = callPackage ../os-specific/linux/anbox { }; + anbox-postmarketos-image = callPackage ../os-specific/linux/anbox/postmarketos-image.nix { }; + androidenv = callPackage ../development/mobile/androidenv { pkgs_i686 = pkgsi686Linux; };