diff --git a/.github/workflows/emulator.yml b/.github/workflows/emulator.yml index 16a88f47..490c17ed 100644 --- a/.github/workflows/emulator.yml +++ b/.github/workflows/emulator.yml @@ -108,6 +108,7 @@ jobs: # below 28: bootstrap didn't start, IDK why # 34: sometimes work, but doesn't seem stable, even w/o caching images script: + - android_integration - bootstrap_flakes - bootstrap_channels - poke_around diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ae6ecb1..ac6df52d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## Release 24.05 (unreleased) +### New Options + +* New options under `android-integration`, + offer some of the tools familiar to Termux users: + `am`, `termux-open`, `termux-open-url`, `termux-reload-settings`, + `termux-setup-storage`, `termux-wake-lock`, `termux-wake-unlock` + and `xdg-open`. + ### Compatibility considerations * `nixOnDroidConfigurations` `pkgs` argument is now mandatory. diff --git a/modules/environment/android-integration.nix b/modules/environment/android-integration.nix new file mode 100644 index 00000000..c8ba13e9 --- /dev/null +++ b/modules/environment/android-integration.nix @@ -0,0 +1,132 @@ +# Copyright (c) 2019-2024, see AUTHORS. Licensed under MIT License, see LICENSE. + +{ config, lib, pkgs, ... }: + +let + cfg = config.android-integration; + + termux-am = + pkgs.callPackage (import ../../pkgs/android-integration/termux-am.nix) { }; + termux-tools = + pkgs.callPackage (import ../../pkgs/android-integration/termux-tools.nix) { + inherit termux-am; + }; +in +{ + + ###### interface + + options.android-integration = { + + am.enable = lib.mkOption { + type = lib.types.bool; + default = false; + example = "true"; + description = lib.mdDoc '' + Provide an `am` (activity manager) command. + Is not guaranteed to be a real deal, could be of limited compatibility + with real `am` (like `termux-am`). + ''; + }; + + termux-open.enable = lib.mkOption { + type = lib.types.bool; + default = false; + example = "true"; + description = lib.mdDoc '' + Provide a `termux-open` command + that opens files or urls in external apps + (uses `com.termux.app.TermuxOpenReceiver`). + ''; + }; + + termux-open-url.enable = lib.mkOption { + type = lib.types.bool; + default = false; + example = "true"; + description = lib.mdDoc '' + Provide a `termux-open-url` command + that opens files or urls in external apps + (uses `android.intent.action.VIEW`). + ''; + }; + + termux-setup-storage.enable = lib.mkOption { + type = lib.types.bool; + default = false; + example = "true"; + description = lib.mdDoc '' + Provide a `termux-setup-storage` command + that makes the app request storage permission, + and then creates a $HOME/storage directory with symlinks to storage. + ''; + }; + + termux-reload-settings.enable = lib.mkOption { + type = lib.types.bool; + default = false; + example = "true"; + description = lib.mdDoc '' + Provide a `termux-reload-settings` command + which applies changes to font, colorscheme or terminal + without the need to close all the sessions. + ''; + }; + + termux-wake-lock.enable = lib.mkOption { + type = lib.types.bool; + default = false; + example = "true"; + description = lib.mdDoc '' + Provide a `termux-wake-lock` command + that tones down Android power saving measures. + This is the same action that's available from the notification. + ''; + }; + + termux-wake-unlock.enable = lib.mkOption { + type = lib.types.bool; + default = false; + example = "true"; + description = lib.mdDoc '' + Provide a `termux-wake-unlock` command + that undoes the effect of the `termux-wake-lock` one. + ''; + }; + + xdg-open.enable = lib.mkOption { + type = lib.types.bool; + default = false; + example = "true"; + description = lib.mdDoc '' + Provide an `xdg-open` alias to `termux-open` command. + ''; + }; + + unsupported.enable = lib.mkOption { + type = lib.types.bool; + default = false; + example = "true"; + description = lib.mdDoc '' + Provide several more unsupported and untested commands. + For testing and for brave souls only. + ''; + }; + + }; + + ###### implementation + + config = let ifD = cond: pkg: if cond then [ pkg ] else [ ]; in { + environment.packages = + (ifD cfg.am.enable termux-am) ++ + (ifD cfg.termux-setup-storage.enable termux-tools.setup_storage) ++ + (ifD cfg.termux-open.enable termux-tools.open) ++ + (ifD cfg.termux-open-url.enable termux-tools.open_url) ++ + (ifD cfg.termux-reload-settings.enable termux-tools.reload_settings) ++ + (ifD cfg.termux-wake-lock.enable termux-tools.wake_lock) ++ + (ifD cfg.termux-wake-unlock.enable termux-tools.wake_unlock) ++ + (ifD cfg.xdg-open.enable termux-tools.xdg_open) ++ + (ifD cfg.unsupported.enable termux-tools.out); + }; +} diff --git a/modules/module-list.nix b/modules/module-list.nix index 20dfdd00..14003530 100644 --- a/modules/module-list.nix +++ b/modules/module-list.nix @@ -9,6 +9,7 @@ [ ./build/activation.nix ./build/config.nix + ./environment/android-integration.nix ./environment/ca.nix ./environment/etc ./environment/links.nix diff --git a/pkgs/android-integration/termux-am.nix b/pkgs/android-integration/termux-am.nix new file mode 100644 index 00000000..18c8a30f --- /dev/null +++ b/pkgs/android-integration/termux-am.nix @@ -0,0 +1,33 @@ +# Copyright (c) 2019-2024, see AUTHORS. Licensed under MIT License, see LICENSE. + +{ stdenv, fetchFromGitHub, cmake }: + +let + appPath = "/data/data/com.termux.nix/files/apps/com.termux.nix"; + socketPath = "${appPath}/termux-am/am.sock"; +in +stdenv.mkDerivation rec { + name = "termux-am"; + version = "1.5.0"; + src = fetchFromGitHub { + owner = "termux"; + repo = "termux-am-socket"; + rev = version; + sha256 = "sha256-6pCv2HMBRp8Hi56b43mQqnaFaI7y5DfhS9gScANwg2I="; + }; + nativeBuildInputs = [ cmake ]; + patchPhase = '' + # Header generation doesn't seem to work on android + echo "#define SOCKET_PATH \"${socketPath}\"" > termux-am.h + # Fix the bash link so that nix can patch it + path to termux-am-socket + substituteInPlace termux-am.sh.in \ + --replace @TERMUX_PREFIX@/bin/bash /bin/bash \ + --replace \ + "termux-am-socket \"\$am_command_string\"" \ + "$out/bin/termux-am-socket \"\$am_command_string\"" + ''; + postInstall = '' + # Scripts use 'am' as an alias. + ln -s $out/bin/termux-am $out/bin/am + ''; +} diff --git a/pkgs/android-integration/termux-tools.nix b/pkgs/android-integration/termux-tools.nix new file mode 100644 index 00000000..7a4bf519 --- /dev/null +++ b/pkgs/android-integration/termux-tools.nix @@ -0,0 +1,124 @@ +# Copyright (c) 2019-2024, see AUTHORS. Licensed under MIT License, see LICENSE. + +{ stdenvNoCC +, fetchFromGitHub +, autoreconfHook +, makeWrapper +, gnused +, getopt +, termux-am +}: + +stdenvNoCC.mkDerivation rec { + name = "termux-tools"; + version = "1.42.4"; + src = fetchFromGitHub { + owner = "termux"; + repo = "termux-tools"; + rev = "v${version}"; + sha256 = "sha256-LkkeaEQcY8HgunBYAg3Ymn5xYPvrGqGNCZTd/NyIOKY="; + }; + nativeBuildInputs = [ autoreconfHook makeWrapper ]; + propagatedInputs = [ termux-am ]; + + # https://github.com/termux/termux-tools/pull/95 + patches = [ ./termux-tools.patch ]; + postPatch = '' + substituteInPlace scripts/termux-setup-storage.in \ + --replace @TERMUX_HOME@ /data/data/com.termux.nix/files/home/ \ + --replace @TERMUX_APP_PACKAGE@ com.termux.nix + substituteInPlace scripts/termux-open.in \ + --replace 'getopt ' '${getopt}/bin/getopt ' + substituteInPlace \ + scripts/termux-open.in \ + scripts/termux-wake-lock.in \ + scripts/termux-wake-unlock.in \ + --replace @TERMUX_APP_PACKAGE@.app com.termux.app \ + --replace @TERMUX_APP_PACKAGE@ com.termux.nix + substituteInPlace scripts/termux-reload-settings.in \ + --replace @TERMUX_APP_PACKAGE@ com.termux.nix + ${gnused}/bin/sed -i 's|^am |${termux-am}/bin/am |' scripts/* + + rm -r doc # manpage is half misleading, pulling pandoc is not worth it + substituteInPlace Makefile.am --replace \ + 'SUBDIRS = . scripts doc mirrors motds' \ + 'SUBDIRS = . scripts' + substituteInPlace configure.ac --replace \ + 'AC_CONFIG_FILES([Makefile scripts/Makefile doc/Makefile' \ + 'AC_CONFIG_FILES([Makefile scripts/Makefile])' + substituteInPlace configure.ac --replace \ + 'mirrors/Makefile motds/Makefile])' "" + ''; + + outputs = [ + "out" # all the unsupported unsorted stuff + "setup_storage" # termux-setup-storage + "open" # termux-open + "open_url" # termux-open-url + "reload_settings" # termux-reload-settings + "wake_lock" # termux-wake-lock + "wake_unlock" # termux-wake-unlock + "xdg_open" # xdg-open + ]; + postInstall = '' + rm $out/etc/termux-login.sh + rm $out/etc/profile.d/init-termux-properties.sh + rm -d $out/etc/profile.d + rm -d $out/etc + + rm $out/bin/chsh # we offer a declarative way to change your shell + rm $out/bin/cmd # doesn't work because we overlay /system/bin + rm $out/bin/dalvikvm # doesn't work because we overlay /system/bin + rm $out/bin/df # works without the magic + rm $out/bin/getprop # doesn't work because we overlay /system/bin + rm $out/bin/logcat # doesn't work because we overlay /system/bin + rm $out/bin/login # we have our own, very complex login + rm $out/bin/ping # doesn't work because we overlay /system/bin + rm $out/bin/ping6 # doesn't work because we overlay /system/bin + rm $out/bin/pkg # we use Nix + rm $out/bin/pm # doesn't work because we overlay /system/bin + rm $out/bin/settings # doesn't work because we overlay /system/bin + rm $out/bin/su # doesn't work because we overlay /bin + rm $out/bin/top # doesn't work because we overlay /system/bin + + rm $out/bin/termux-change-repo # we use Nix + rm $out/bin/termux-fix-shebang # we use Nix + rm $out/bin/termux-info # Termux-specific. write our own? + rm $out/bin/termux-reset # untested and dangerous + rm $out/bin/termux-restore # untested and dangerous + rm $out/bin/termux-setup-package-manager # we use Nix + + mkdir -p $setup_storage/bin + mv $out/bin/termux-setup-storage $setup_storage/bin/ + + mkdir -p $open/bin + mv $out/bin/termux-open $open/bin/ + + mkdir -p $open_url/bin + mv $out/bin/termux-open-url $open_url/bin/ + + mkdir -p $reload_settings/bin + mv $out/bin/termux-reload-settings $reload_settings/bin/ + + mkdir -p $wake_lock/bin + mv $out/bin/termux-wake-lock $wake_lock/bin/ + + mkdir -p $wake_unlock/bin + mv $out/bin/termux-wake-unlock $wake_unlock/bin/ + + mkdir -p $xdg_open/bin + rm $out/bin/xdg-open + ln -s $open/bin/termux-open $xdg_open/bin/xdg-open + + # check that we didn't package we didn't want to + find $out | ${gnused}/bin/sed "s|^$out|.|" | sort > effective + echo . >> expected + echo ./bin >> expected + echo ./bin/termux-backup >> expected # entirely untested + echo ./share >> expected + echo ./share/examples >> expected + echo ./share/examples/termux >> expected + echo ./share/examples/termux/termux.properties >> expected # useful + diff -u expected effective + ''; +} diff --git a/pkgs/android-integration/termux-tools.patch b/pkgs/android-integration/termux-tools.patch new file mode 100644 index 00000000..26e0427e --- /dev/null +++ b/pkgs/android-integration/termux-tools.patch @@ -0,0 +1,87 @@ +From 6d72b44d90347ddce8473b604c38f352e6773f8d Mon Sep 17 00:00:00 2001 +From: Alexander Sosedkin +Date: Sat, 1 Jun 2024 17:14:22 +0200 +Subject: [PATCH] scripts: replace com.termux with @TERMUX_APP_PACKAGE@ + +--- + scripts/termux-open.in | 2 +- + scripts/termux-reload-settings.in | 2 +- + scripts/termux-reset.in | 2 +- + scripts/termux-setup-storage.in | 4 ++-- + scripts/termux-wake-lock.in | 4 ++-- + scripts/termux-wake-unlock.in | 4 ++-- + 6 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/scripts/termux-open.in b/scripts/termux-open.in +index 9c81630..9a04e7b 100644 +--- a/scripts/termux-open.in ++++ b/scripts/termux-open.in +@@ -44,7 +44,7 @@ case "${TERMUX__USER_ID:-}" in ''|*[!0-9]*|0[0-9]*) TERMUX__USER_ID=0;; esac + + am broadcast --user "$TERMUX__USER_ID" \ + -a $ACTION \ +- -n com.termux/com.termux.app.TermuxOpenReceiver \ ++ -n @TERMUX_APP_PACKAGE@/@TERMUX_APP_PACKAGE@.app.TermuxOpenReceiver \ + $EXTRAS \ + -d "$FILE" \ + > /dev/null +diff --git a/scripts/termux-reload-settings.in b/scripts/termux-reload-settings.in +index 4e71f8a..ef8b0f4 100644 +--- a/scripts/termux-reload-settings.in ++++ b/scripts/termux-reload-settings.in +@@ -11,4 +11,4 @@ fi + + case "${TERMUX__USER_ID:-}" in ''|*[!0-9]*|0[0-9]*) TERMUX__USER_ID=0;; esac + +-am broadcast --user "$TERMUX__USER_ID" -a com.termux.app.reload_style com.termux > /dev/null ++am broadcast --user "$TERMUX__USER_ID" -a @TERMUX_APP_PACKAGE@.app.reload_style @TERMUX_APP_PACKAGE@ > /dev/null +diff --git a/scripts/termux-reset.in b/scripts/termux-reset.in +index 6f807a7..2161d1f 100644 +--- a/scripts/termux-reset.in ++++ b/scripts/termux-reset.in +@@ -45,6 +45,6 @@ else + /system/bin/killall -9 "$SHELL" + else + export CLASSPATH="@TERMUX_CACHE_DIR@/termux-am/am.apk" +- /system/bin/app_process / com.termux.termuxam.Am stopservice com.termux/.app.TermuxService ++ /system/bin/app_process / @TERMUX_APP_PACKAGE@.termuxam.Am stopservice @TERMUX_APP_PACKAGE@/.app.TermuxService + fi + fi +diff --git a/scripts/termux-setup-storage.in b/scripts/termux-setup-storage.in +index c621234..a086159 100644 +--- a/scripts/termux-setup-storage.in ++++ b/scripts/termux-setup-storage.in +@@ -27,5 +27,5 @@ fi + case "${TERMUX__USER_ID:-}" in ''|*[!0-9]*|0[0-9]*) TERMUX__USER_ID=0;; esac + + am broadcast --user "$TERMUX__USER_ID" \ +- --es com.termux.app.reload_style storage \ +- -a com.termux.app.reload_style com.termux > /dev/null ++ --es @TERMUX_APP_PACKAGE@.app.reload_style storage \ ++ -a @TERMUX_APP_PACKAGE@.app.reload_style @TERMUX_APP_PACKAGE@ > /dev/null +diff --git a/scripts/termux-wake-lock.in b/scripts/termux-wake-lock.in +index ba4b899..f3fd59e 100644 +--- a/scripts/termux-wake-lock.in ++++ b/scripts/termux-wake-lock.in +@@ -10,6 +10,6 @@ case "${TERMUX__USER_ID:-}" in ''|*[!0-9]*|0[0-9]*) TERMUX__USER_ID=0;; esac + + am startservice \ + --user "$TERMUX__USER_ID" \ +- -a com.termux.service_wake_lock \ +- com.termux/com.termux.app.TermuxService \ ++ -a @TERMUX_APP_PACKAGE@.service_wake_lock \ ++ @TERMUX_APP_PACKAGE@/@TERMUX_APP_PACKAGE@.app.TermuxService \ + > /dev/null +diff --git a/scripts/termux-wake-unlock.in b/scripts/termux-wake-unlock.in +index a4b1f57..d53ce31 100644 +--- a/scripts/termux-wake-unlock.in ++++ b/scripts/termux-wake-unlock.in +@@ -10,6 +10,6 @@ case "${TERMUX__USER_ID:-}" in ''|*[!0-9]*|0[0-9]*) TERMUX__USER_ID=0;; esac + + am startservice \ + --user "$TERMUX__USER_ID" \ +- -a com.termux.service_wake_unlock \ +- com.termux/com.termux.app.TermuxService \ ++ -a @TERMUX_APP_PACKAGE@.service_wake_unlock \ ++ @TERMUX_APP_PACKAGE@/@TERMUX_APP_PACKAGE@.app.TermuxService \ + > /dev/null diff --git a/tests/emulator/android_integration.py b/tests/emulator/android_integration.py new file mode 100644 index 00000000..df4e2e36 --- /dev/null +++ b/tests/emulator/android_integration.py @@ -0,0 +1,193 @@ +import base64 +import time + +import bootstrap_channels + +from common import screenshot, wait_for + + +def run(d): + OPENERS = ['termux-open', 'termux-open-url', 'xdg-open'] + TOOLS = ['am', 'termux-setup-storage', 'termux-reload-settings', + 'termux-wake-lock', 'termux-wake-unlock'] + OPENERS + + nod = bootstrap_channels.run(d) + + # Verify that android-integration tools aren't installed by default + for toolname in TOOLS: + d(f'input text "{toolname}"') + d.ui.press('enter') + wait_for(d, f'bash: {toolname}: command not found') + screenshot(d, f'no-{toolname}') + + # Apply a config that enables android-integration tools + cfg = ('/data/local/tmp/n-o-d/unpacked/tests/on-device/' + 'config-android-integration.nix') + d(f'input text \'cp {cfg} .config/nixpkgs/nix-on-droid.nix\'') + d.ui.press('enter') + screenshot(d, 'pre-switch') + d('input text "nix-on-droid switch && echo integration tools installed"') + d.ui.press('enter') + wait_for(d, 'integration tools installed') + screenshot(d, 'post-switch') + + # Verify am is there + d('input text "am | head -n2"') + d.ui.press('enter') + wait_for(d, 'termux-am is a wrapper script') + screenshot(d, 'am-appears') + + # Smoke-test that am doesn't work yet + d('input text "am start -a android.settings.SETTINGS 2>&1 | head -n5"') + d.ui.press('enter') + screenshot(d, 'am-invoked for the first time') + wait_for(d, 'Nix requires "Display over other apps" permission') + wait_for(d, 'https://dontkillmyapp.com') + screenshot(d, 'am-wants-permission') + + # ... there might be a notification now, get rid of it + time.sleep(3) + screenshot(d, 'am-wants-permission-3-seconds-later') + if 'text="TermuxAm Socket Server Error"' in d.ui.dump_hierarchy(): + d.ui.open_notification() + time.sleep(1) + screenshot(d, 'notification-opened') + d.ui(text='TermuxAm Socket Server Error').swipe('right') + screenshot(d, 'error-notification-swiped-right') + d.ui.press('back') + screenshot(d, 'back') + + # Grant nix app 'Draw over other apps' permission + nod.permissions += 'android.permission.SYSTEM_ALERT_WINDOW' + + # Smoke-test that am works + d('input text "am start -a android.settings.SETTINGS"') + d.ui.press('enter') + screenshot(d, 'settings-opening') + wait_for(d, 'Search settings') + wait_for(d, 'Network') + screenshot(d, 'settings-awaited') + d.ui.press('back') + screenshot(d, 'back-from-settings') + + # Verify we're back + d('input text "am | head -n2"') + d.ui.press('enter') + wait_for(d, 'termux-am is a wrapper script') + + # Verify termux-setup-storage is there + d('input text "termux-setup-storage"') + d.ui.press('enter') + screenshot(d, 'termux-setup-storage-invoked') + wait_for(d, 'Allow Nix to access') + screenshot(d, 'permission-requested') + if 'text="Allow"' in d.ui.dump_hierarchy(): + d.ui(text='Allow').click() + elif 'text="ALLOW"' in d.ui.dump_hierarchy(): + d.ui(text='ALLOW').click() + screenshot(d, 'permission-granted') + + d('input text "ls -l storage"') + d.ui.press('enter') + screenshot(d, 'storage-listed') + wait_for(d, 'pictures -> /storage/emulated/0/Pictures') + wait_for(d, 'shared -> /storage/emulated/0') + screenshot(d, 'storage-listed-ok') + + # Invoke termux-setup-storage again + d('input text "termux-setup-storage"') + d.ui.press('enter') + screenshot(d, 'termux-setup-storage-invoked-again') + wait_for(d, 'already exists') + wait_for(d, 'Do you want to continue?') + d.ui.press('enter') + wait_for(d, 'Aborting configuration and leaving') + + # Verify that *-open* commands work + for opener in OPENERS: + d(f'input text "{opener} https://example.org"') + d.ui.press('enter') + screenshot(d, f'{opener}-opened') + wait_for(d, 'This domain is for use in illustrative') + screenshot(d, f'{opener}-waited') + d.ui.press('back') + screenshot(d, f'{opener}-back') + wait_for(d, f'{opener} https://example.org') + + # test termux-wake-lock/termux-wake-unlock + d.ui.open_notification() + screenshot(d, 'notification-opened') + d.ui(text='Nix').right(resourceId='android:id/expand_button').click() + screenshot(d, 'notification-expanded') + wait_for(d, 'Acquire wakelock') + screenshot(d, 'wakelock-initially-not-acquired') + d.ui.press('back') + + d('input text "termux-wake-lock"') + d.ui.press('enter') + time.sleep(3) + screenshot(d, 'wake-lock-command') + if 'Let app always run in background?' in d.ui.dump_hierarchy(): + screenshot(d, 'wake-lock-permission-asked') + if 'text="Allow"' in d.ui.dump_hierarchy(): + d.ui(text='Allow').click() + elif 'text="ALLOW"' in d.ui.dump_hierarchy(): + d.ui(text='ALLOW').click() + screenshot(d, 'wake-lock-permission-granted') + d.ui.open_notification() + time.sleep(.5) + screenshot(d, 'notification-opened') + wait_for(d, '(wake lock held)') + if 'Release wakelock' not in d.ui.dump_hierarchy(): + d.ui(text='Nix').right(resourceId='android:id/expand_button').click() + screenshot(d, 'notification-expanded') + wait_for(d, 'Release wakelock') + screenshot(d, 'notification-with-wakelock') + d.ui.press('back') + screenshot(d, 'back') + wait_for(d, 'termux-wake-lock') + screenshot(d, 'really-back') + + d('input text "termux-wake-unlock"') + d.ui.press('enter') + screenshot(d, 'wake-unlock-command') + d.ui.open_notification() + time.sleep(.5) + screenshot(d, 'notification-opened') + if 'Acquire wakelock' not in d.ui.dump_hierarchy(): + d.ui(text='Nix').right(resourceId='android:id/expand_button').click() + screenshot(d, 'notification-expanded') + wait_for(d, 'Acquire wakelock') + screenshot(d, 'notification-without-wakelock') + d.ui.press('back') + screenshot(d, 'back') + wait_for(d, 'termux-wake-unlock') + screenshot(d, 'really-back') + + # Test termux-reload-settings + assert 'text="PGUP"' in d.ui.dump_hierarchy() + assert 'text="F12"' not in d.ui.dump_hierarchy() + + d('input text "mkdir ~/.termux"') + d.ui.press('enter') + cmd = 'echo "extra-keys=[[\'F12\']]" > ~/.termux/termux.properties' + cmd_base64 = base64.b64encode(cmd.encode()).decode() + d(f'input text "echo {cmd_base64} | base64 -d | bash -s"') + d.ui.press('enter') + screenshot(d, 'pre-reload') + d('input text "termux-reload-settings"') + d.ui.press('enter') + time.sleep(1) + screenshot(d, 'post-reload') + assert 'text="PGUP"' not in d.ui.dump_hierarchy() + assert 'text="F12"' in d.ui.dump_hierarchy() + + d('input text "rm -r ~/.termux"') + d.ui.press('enter') + screenshot(d, 'pre-reload-back') + d('input text "termux-reload-settings"') + d.ui.press('enter') + time.sleep(1) + screenshot(d, 'post-reload-back') + assert 'text="PGUP"' in d.ui.dump_hierarchy() + assert 'text="F12"' not in d.ui.dump_hierarchy() diff --git a/tests/emulator/bootstrap_channels.py b/tests/emulator/bootstrap_channels.py index 08d12374..2dd77a26 100644 --- a/tests/emulator/bootstrap_channels.py +++ b/tests/emulator/bootstrap_channels.py @@ -52,3 +52,5 @@ def run(d): wait_for(d, 'c21va2UtdGVzdAo=') screenshot(d, 'success-bootstrap-channels') + + return nod diff --git a/tests/emulator/bootstrap_flakes.py b/tests/emulator/bootstrap_flakes.py index 4d27a606..8131d86f 100644 --- a/tests/emulator/bootstrap_flakes.py +++ b/tests/emulator/bootstrap_flakes.py @@ -52,3 +52,5 @@ def run(d): wait_for(d, 'c21va2UtdGVzdAo=') screenshot(d, 'success-bootstrap-flakes') + + return nod diff --git a/tests/on-device/config-android-integration.bats b/tests/on-device/config-android-integration.bats new file mode 100644 index 00000000..5340d537 --- /dev/null +++ b/tests/on-device/config-android-integration.bats @@ -0,0 +1,48 @@ +# Copyright (c) 2019-2024, see AUTHORS. Licensed under MIT License, see LICENSE. + +load lib + +@test 'android-integration options can be used' { + bats_require_minimum_version 1.5.0 + run ! command -v am + run ! command -v termux-setup-storage + run ! command -v termux-open + run ! command -v termux-open-url + run ! command -v termux-reload-settings + run ! command -v termux-wake-lock + run ! command -v termux-wake-unlock + run ! command -v xdg-open + run ! command -v termux-backup + + cp \ + "$ON_DEVICE_TESTS_DIR/config-android-integration.nix" \ + ~/.config/nixpkgs/nix-on-droid.nix + nix-on-droid switch + + command -v am + command -v termux-setup-storage + command -v termux-open + command -v termux-open-url + command -v termux-reload-settings + command -v termux-wake-lock + command -v termux-wake-unlock + command -v xdg-open + run ! command -v termux-backup + + _sed \ + -e "s|# unsupported.enable = false;|unsupported.enable = true;|" \ + -e "s|am.enable = true;|am.enable = false;|" \ + -i ~/.config/nixpkgs/nix-on-droid.nix + nix-on-droid switch + run ! command -v am + command -v termux-setup-storage + command -v termux-open + command -v termux-open-url + command -v termux-reload-settings + command -v termux-wake-lock + command -v termux-wake-unlock + command -v xdg-open + command -v termux-backup + + switch_to_default_config +} diff --git a/tests/on-device/config-android-integration.nix b/tests/on-device/config-android-integration.nix new file mode 100644 index 00000000..dd30d5e4 --- /dev/null +++ b/tests/on-device/config-android-integration.nix @@ -0,0 +1,16 @@ +_: + +{ + system.stateVersion = "23.11"; + android-integration = { + am.enable = true; + termux-open.enable = true; + termux-open-url.enable = true; + termux-reload-settings.enable = true; + termux-setup-storage.enable = true; + termux-wake-lock.enable = true; + termux-wake-unlock.enable = true; + xdg-open.enable = true; + # unsupported.enable = false; + }; +}