Renamed extras `TERMUX_APP.TERMUX_SERVICE.EXTRA_SESSION_NAME` to `*.EXTRA_SHELL_NAME`, `TERMUX_APP.RUN_COMMAND_SERVICE.EXTRA_SESSION_NAME` to `*.EXTRA_SHELL_NAME`, `TERMUX_APP.TERMUX_SERVICE.EXTRA_SESSION_CREATE_MODE` to `*.EXTRA_SHELL_CREATE_MODE` and `TERMUX_APP.RUN_COMMAND_SERVICE.EXTRA_SESSION_CREATE_MODE` to `*.EXTRA_SHELL_CREATE_MODE`.
Renamed `enum` class `SessionCreateMode` to `ShellCreateMode`, `sessionName` field to `shellName`, `sessionCreateMode` to `shellCreateMode` in `ExecutionCommand`.
The `TermuxService` `AppShells`/`TermuxTasks` will now consider `ShellCreateMode` as well before starting tasks as done for `TermuxSessions` via 5794ab9a
New task command to not create new foreground session and switch to existing session if one already exits with `shellName` is
```
am startservice --user 0 -n com.termux/com.termux.app.RunCommandService \
-a com.termux.RUN_COMMAND \
--es com.termux.RUN_COMMAND_PATH '/data/data/com.termux/files/usr/bin/bash' \
--es com.termux.RUN_COMMAND_SHELL_CREATE_MODE 'no-shell-with-name' \
--es com.termux.RUN_COMMAND_SHELL_NAME "custom-name"
```
New task command to not create new background task if one already exits with `shellName` is
```
am startservice --user 0 -n com.termux/com.termux.app.RunCommandService \
-a com.termux.RUN_COMMAND \
--es com.termux.RUN_COMMAND_PATH '/data/data/com.termux/files/usr/bin/top' \
--esa com.termux.RUN_COMMAND_ARGUMENTS '-n,5' \
--es com.termux.RUN_COMMAND_SHELL_CREATE_MODE 'no-shell-with-name' \
--es com.termux.RUN_COMMAND_SHELL_NAME "custom-name" \
--es com.termux.RUN_COMMAND_RUNNER "app-shell"
```
The apps directory will now use the unique package name of apps for basename that can be automatically generated instead of having to be hardcoded.
`termux-am-socket` will be upgraded to `v1.4.0` for respective change.
The `TermuxBootstrap` class has been added that defines the `PackageManager` and `PackageVariant` classes for the supported package manager configurations for the app. The variant is defined by the `project.ext.packageVariant` value in the `app/build.gradle` and its value is used by the `build.gradle` to pack its respective bootstrap zips in the app APK at build time and the value is used to set `TermuxBootstrap.TERMUX_APP_PACKAGE_MANAGER` and `TermuxBootstrap.TERMUX_APP_PACKAGE_VARIANT` static values that are used at runtime by the app to run variant specific code. The manager is automatically extracted from the variant as the substring before first dash `-`.
The default variant is `apt-android-7` and it can either be replaced in `app/build.gradle` manually or the `TERMUX_PACKAGE_VARIANT` env variable can be exported in which the build command is run.
The `TERMUX_APP_PACKAGE_MANAGER` and `TERMUX_APP_PACKAGE_VARIANT` environmental variables will be exported by the app and they will also be added in Termux app info in about page and reports, allowing users and devs to know which variant is currently installed.
Bootstrap of a different variant must not be manually installed by the user after app installation by replacing `$PREFIX` since app code is dependant on the variant used to build the APK.
Currently, `apt-android-7` and `apt-android-5` variants will be built for by the workflows but they will fail for `apt-android-5` since `build.gradle` support is currently not enabled and will be enabled by a pull request that adds support for Android 5. The workflow needs to try to build the `apt-android-5` variant so that pull request builds are generated.
```
Exception in createServerSocketNative():
java.lang.NoSuchMethodError: no non-static method "Lcom/termux/shared/jni/models/JniResult;.<init>(IILjava/lang/String;I)V"
at com.termux.shared.net.socket.local.LocalSocketManager.createServerSocketNative(Native Method)
at com.termux.shared.net.socket.local.LocalSocketManager.createServerSocket(LocalSocketManager.java:125)
at com.termux.shared.net.socket.local.LocalServerSocket.start(LocalServerSocket.java:100)
at com.termux.shared.net.socket.local.LocalSocketManager.start(LocalSocketManager.java:84)
at com.termux.shared.shell.am.AmSocketServer.start(AmSocketServer.java:68)
at com.termux.shared.termux.shell.am.TermuxAmSocketServer.start(TermuxAmSocketServer.java:101)
at com.termux.shared.termux.shell.am.TermuxAmSocketServer.setupTermuxAmSocketServer(TermuxAmSocketServer.java:77)
at com.termux.app.TermuxApplication.onCreate(TermuxApplication.java:53)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1192)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6719)
at android.app.ActivityThread.access$1300(ActivityThread.java:237)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1913)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7664)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
```
The `AmSocketServer` now handles the entire logic for processing of am commands sent by clients and its results. This can be used by other apps as well to run their own am servers. The server started by `termux-app` will be managed by `TermuxAmSocketServer`. Read their javadocs for details.
The extended implementation `TermuxAmSocketServerClient` of `AmSocketServer.AmSocketServerClient`/`ILocalSocketManager` will also send a plugin error notification for all errors to the user instead of just logging to logcat since users are not very good at checking those, this should save dev time debugging problems. We may need to ignore notifications for some errors like broken pipe, based on their `Error` objects if they are normally expected, this requires further investigation.
The `TERMUX_APP_AM_SOCKET_SERVER_ENABLED` env variable will also be exported for all shell sessions and tasks for whether the server was successfully started on app startup. The user can disable the server by adding "run-termux-am-socket-server=false" to the "~/.termux/termux.properties" as implemented in 5f8a9222. The env variable will be checked by `$PREFIX/bin/termux-am` before attempting to connect.
The new path for the server socket is `/data/data/com.termux/files/apps/termux-app/termux-am/am.sock` as per `TERMUX_APP.APPS_DIR_PATH` added in bcd8f4c4.
- Added `LocalSocketManager` to manage the server, `LocalServerSocket` to represent server socket, `LocalClientSocket` to represent client socket, `LocalSocketRunConfig` to store server run config and `ILocalSocketManager` as interface for the `LocalSocketManager` to handle callbacks from the server to handle clients.
- Added support to get full `PeerCred` for client socket, including `pid`, `pname`, `uid`, `uname`, `gid`, `gname` and `cmdline` instead of just `uid`. This should provide more info for error logs about which client failed or tried to connect in case of disallowed clients. Some data is filled in native code and some in java. Native support for added to get process name and `cmdline` of a process with a specific pid.
- Added `JniResult` to get results for JNI calls. Previously only an int was returned and incomplete errors logged. With `JniResult`, both `retval` and `errno` will be returned and full error messages in `errmsg`, including all `strerror()` output for `errno`s. This would provide more helpful info on errors.
- Added `Error` support via `LocalSocketErrno` which contains full error messages and stacktraces for all native and java calls, allowing much better error reporting to users and devs. The errors will be logged by `LocalSocketManagerClientBase` if log level is debug or higher since `PeerCred` `cmdline` may contain private info of users.
- Added support in java to check if socket path was an absolute path and not greater than `108` bytes, after canonicalizing it since otherwise it would result in creation of useless parent directories on failure.
- Added `readDataOnInputStream()` and `sendDataToOutputStream()` functions to `LocalClientSocket` so that server manager client can easily read and send data.
- Renamed the variables and functions as per convention, specially one letter variables. https://source.android.com/setup/contribute/code-style#follow-field-naming-conventions
- Rename `local-filesystem-socket` to `local-filesystem` since abstract namespace sockets can also be created.
- Previously, it was assumed that all local server would expect a shell command string that should be converted to command args with `ArgumentTokenizer` and then should be passed to `LocalSocketHandler.handle()` and then result sent back to client with exit code, stdout and stderr, but there could be any kind of servers in which behaviour is different. Such client handling should not be hard coded and the server manager client should handle the client themselves however they like, including closing the client socket. This will now be done with `ILocalSocketManager. onClientAccepted(LocalSocketManager, LocalClientSocket)`.
- Ensure app does not crash if `local-socket` library is not found or for any other exceptions in the server since anything running in the `Application` class is critical that it does not fail since user would not be able to recover from it, specially non rooted users without SAF support to disable the server with a prop.
- Make sure all reasonable JNI exceptions are caught instead of crashing the app.
- Fixed issue where client logic (`LocalSocketHandler.handle()` was being run in the same thread as the new client acceptable thread, basically blocking new clients until previous client's am command was fully processed. Now all client interface callbacks are started in new threads by `LocalSocketManager`.
- Fix bug where timeout would not be greater than `1000ms` due to only using `tv_usec` which caps at `999,999`.
The user can add `run-termux-am-socket-server=false` entry to `termux.properties` file to disable the `termux-am` server to run at app startup which is connected to by `$PREFIX/bin/termux-am` from the `termux-am-socket` package. The default value is `true`. Changes require `termux-app` to be force stopped and restarted to provide consistent state for all termux sessions and tasks.
The prop will be used in a later commit.
The termux files directory will also be checked and created if required at startup and code related to it will only be run if it is accessible. This can later also be used for init execution commands.
The `TERMUX_APP.APPS_DIR_PATH` will act as app specific directory for `termux-app` app related files. Other plugin apps will have their own directories under `TERMUX_APPS_DIR_PATH` if required.
Execution commands and other errors that may contain potentially private info should not be logged unless user has explicitly allowed it since apps with `READ_LOGS` permission would be able to read the data. A notification for failed executions commands would still be shown if enabled and required.