Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

modules/android-integration: add am command and many termux-tools ones #382

Merged
merged 5 commits into from
Jul 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/emulator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
132 changes: 132 additions & 0 deletions modules/environment/android-integration.nix
Original file line number Diff line number Diff line change
@@ -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`).
'';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is phrased weirdly, the "is not garunteed/could be" language is unnecessary. A link to more details on the limitations would be great (if they exist). I would suggest:

Provide an `am` (activity manager) command.
It is not the real deal, and has limited capabilities compared to the real `am`, similar to `termux-am`. See [here](insert link here) for more details.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thing is, I'm not well-versed in Android and don't know its exact limitations. It's very different from the real deal in /system/bin/am, which is a shell wrapper against some java thing, in that it sends the command-line over a socket and something in Termux app handles that. The help message is very different, I wouldn't be surprised if it had different error reporting or differed in exit codes, etc., etc., but I don't know the exact details. All I know it's the best am we can currently have because it works.

};

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);
};
}
1 change: 1 addition & 0 deletions modules/module-list.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
[
./build/activation.nix
./build/config.nix
./environment/android-integration.nix
./environment/ca.nix
./environment/etc
./environment/links.nix
Expand Down
33 changes: 33 additions & 0 deletions pkgs/android-integration/termux-am.nix
Original file line number Diff line number Diff line change
@@ -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
'';
}
124 changes: 124 additions & 0 deletions pkgs/android-integration/termux-tools.nix
Original file line number Diff line number Diff line change
@@ -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 @[email protected] 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/*
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you use substituteInPlace above but gnused here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because substituteInPlace is the recommended Nix way, being more explicit and less surprising and everything...

... and then there are 6 calls to am that need to be patched to use the real path, but you can't just replace all am, it has to be at the beginning of the line, so I whip up a sed and use a regexp.


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
'';
}
Loading
Loading