diff --git a/nixos/modules/virtualisation/anbox.nix b/nixos/modules/virtualisation/anbox.nix index c7e9e23c4c92..523d9a9576ef 100644 --- a/nixos/modules/virtualisation/anbox.nix +++ b/nixos/modules/virtualisation/anbox.nix @@ -5,7 +5,7 @@ with lib; let cfg = config.virtualisation.anbox; - kernelPackages = config.boot.kernelPackages; + addrOpts = v: addr: pref: name: { address = mkOption { default = addr; @@ -25,6 +25,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 +64,18 @@ in ''; }; + imageModifications = mkOption { + default = ""; + type = types.lines; + description = lib.mdDoc '' + 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,16 +101,19 @@ in config = mkIf cfg.enable { assertions = singleton { - assertion = versionAtLeast (getVersion config.boot.kernelPackages.kernel) "4.18"; - message = "Anbox needs user namespace support to work properly"; + assertion = with config.boot.kernelPackages; kernelAtLeast "5.5" && kernelOlder "5.18"; + message = "Anbox needs a kernel with binder and ashmem support"; }; environment.systemPackages = with pkgs; [ anbox ]; - services.udev.extraRules = '' - KERNEL=="ashmem", NAME="%k", MODE="0666" - KERNEL=="binder*", NAME="%k", MODE="0666" - ''; + systemd.mounts = singleton { + 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 = []; @@ -87,6 +124,9 @@ in internalInterfaces = [ "anbox0" ]; }; + # Ensures NetworkManager doesn't touch anbox0 + networking.networkmanager.unmanaged = [ "anbox0" ]; + systemd.services.anbox-container-manager = let anboxloc = "/var/lib/anbox"; in { @@ -121,12 +161,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/all-tests.nix b/nixos/tests/all-tests.nix index 97410e220786..17be486d8ebb 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -109,6 +109,7 @@ in { allTerminfo = handleTest ./all-terminfo.nix {}; alps = handleTest ./alps.nix {}; amazon-init-shell = handleTest ./amazon-init-shell.nix {}; + anbox = runTest ./anbox.nix; anuko-time-tracker = handleTest ./anuko-time-tracker.nix {}; apcupsd = handleTest ./apcupsd.nix {}; apfs = runTest ./apfs.nix; diff --git a/nixos/tests/anbox.nix b/nixos/tests/anbox.nix new file mode 100644 index 000000000000..d78f63ec761f --- /dev/null +++ b/nixos/tests/anbox.nix @@ -0,0 +1,40 @@ +{ lib, pkgs, ... }: + +{ + name = "anbox"; + meta.maintainers = with lib.maintainers; [ mvnetbiz ]; + + nodes.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; + boot.kernelPackages = pkgs.linuxPackages_5_15; + + # 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.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 000000000000..1c3450238c7f --- /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/anbox-image.nix b/pkgs/os-specific/linux/anbox/anbox-image.nix new file mode 100644 index 000000000000..77bcd8a09f78 --- /dev/null +++ b/pkgs/os-specific/linux/anbox/anbox-image.nix @@ -0,0 +1,19 @@ +{ stdenv, fetchurl }: + +let + imgroot = "https://build.anbox.io/android-images"; +in + { + armv7l-linux = fetchurl { + url = imgroot + "/2017/06/12/android_1_armhf.img"; + sha256 = "1za4q6vnj8wgphcqpvyq1r8jg6khz7v6b7h6ws1qkd5ljangf1w5"; + }; + aarch64-linux = fetchurl { + url = imgroot + "/2017/08/04/android_1_arm64.img"; + sha256 = "02yvgpx7n0w0ya64y5c7bdxilaiqj9z3s682l5s54vzfnm5a2bg5"; + }; + x86_64-linux = fetchurl { + url = imgroot + "/2018/07/19/android_amd64.img"; + sha256 = "1jlcda4q20w30cm9ikm6bjq01p547nigik1dz7m4v0aps4rws13b"; + }; + }.${stdenv.system} or (throw "Unsupported platform ${stdenv.system}") diff --git a/pkgs/os-specific/linux/anbox/default.nix b/pkgs/os-specific/linux/anbox/default.nix index 7329dc7df2ce..7368079510d6 100644 --- a/pkgs/os-specific/linux/anbox/default.nix +++ b/pkgs/os-specific/linux/anbox/default.nix @@ -1,4 +1,6 @@ { lib, stdenv, fetchFromGitHub, fetchurl +, callPackage +, fetchpatch , cmake, pkg-config, dbus, makeWrapper , boost , elfutils # for libdw @@ -22,7 +24,8 @@ , SDL2_image , systemd , writeText -, writeScript +, writeShellScript +, nixosTests }: let @@ -33,28 +36,20 @@ 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-2021-10-20"; + version = "unstable-2023-02-03"; src = fetchFromGitHub { owner = pname; repo = pname; - rev = "84f0268012cbe322ad858d76613f4182074510ac"; + rev = "ddf4c57ebbe3a2e46099087570898ab5c1e1f279"; sha256 = "sha256-QXWhatewiUDQ93cH1UZsYgbjUxpgB1ajtGFYZnKmabc="; fetchSubmodules = true; }; @@ -90,7 +85,7 @@ stdenv.mkDerivation rec { "-Wno-error=mismatched-new-delete" ]); - patchPhase = '' + prePatch = '' patchShebangs scripts cat >cmake/FindGMock.cmake <<'EOF' @@ -118,8 +113,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 @@ -133,25 +150,13 @@ 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 - imgroot = "https://build.anbox.io/android-images"; - in - { - armv7l-linux = fetchurl { - url = imgroot + "/2017/06/12/android_1_armhf.img"; - sha256 = "1za4q6vnj8wgphcqpvyq1r8jg6khz7v6b7h6ws1qkd5ljangf1w5"; - }; - aarch64-linux = fetchurl { - url = imgroot + "/2017/08/04/android_1_arm64.img"; - sha256 = "02yvgpx7n0w0ya64y5c7bdxilaiqj9z3s682l5s54vzfnm5a2bg5"; - }; - x86_64-linux = fetchurl { - url = imgroot + "/2018/07/19/android_amd64.img"; - sha256 = "1jlcda4q20w30cm9ikm6bjq01p547nigik1dz7m4v0aps4rws13b"; - }; - }.${stdenv.system} or null; + passthru.tests = { inherit (nixosTests) anbox; }; + + passthru.image = callPackage ./postmarketos-image.nix { }; + passthru.postmarketos-image = callPackage ./anbox-image.nix { }; meta = with lib; { homepage = "https://anbox.io"; 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 000000000000..648a1a5ea9a0 --- /dev/null +++ b/pkgs/os-specific/linux/anbox/postmarketos-image.nix @@ -0,0 +1,19 @@ +{ stdenv, fetchurl }: + +let + imgroot = "https://web.archive.org/web/20211027150924/https://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} or (throw "Unsupported platform ${stdenv.system}")