Showing preview only (2,314K chars total). Download the full file or copy to clipboard to get everything.
Repository: termux/termux-app
Branch: master
Commit: 3f0dec3574a6
Files: 318
Total size: 2.1 MB
Directory structure:
gitextract_hurpdc6s/
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── 01-bug-report.yml
│ │ ├── 02-feature-request.yml
│ │ └── config.yml
│ ├── dependabot.yml
│ └── workflows/
│ ├── attach_debug_apks_to_release.yml
│ ├── debug_build.yml
│ ├── dependency-submission.yml
│ ├── gradle-wrapper-validation.yml
│ ├── run_tests.yml
│ └── trigger_library_builds_on_jitpack.yml
├── .gitignore
├── LICENSE.md
├── README.md
├── SECURITY.md
├── app/
│ ├── build.gradle
│ ├── proguard-rules.pro
│ ├── src/
│ │ ├── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── cpp/
│ │ │ │ ├── Android.mk
│ │ │ │ ├── termux-bootstrap-zip.S
│ │ │ │ └── termux-bootstrap.c
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── termux/
│ │ │ │ ├── app/
│ │ │ │ │ ├── RunCommandService.java
│ │ │ │ │ ├── TermuxActivity.java
│ │ │ │ │ ├── TermuxApplication.java
│ │ │ │ │ ├── TermuxInstaller.java
│ │ │ │ │ ├── TermuxOpenReceiver.java
│ │ │ │ │ ├── TermuxService.java
│ │ │ │ │ ├── activities/
│ │ │ │ │ │ ├── HelpActivity.java
│ │ │ │ │ │ └── SettingsActivity.java
│ │ │ │ │ ├── api/
│ │ │ │ │ │ └── file/
│ │ │ │ │ │ └── FileReceiverActivity.java
│ │ │ │ │ ├── event/
│ │ │ │ │ │ └── SystemEventReceiver.java
│ │ │ │ │ ├── fragments/
│ │ │ │ │ │ └── settings/
│ │ │ │ │ │ ├── TermuxAPIPreferencesFragment.java
│ │ │ │ │ │ ├── TermuxFloatPreferencesFragment.java
│ │ │ │ │ │ ├── TermuxPreferencesFragment.java
│ │ │ │ │ │ ├── TermuxTaskerPreferencesFragment.java
│ │ │ │ │ │ ├── TermuxWidgetPreferencesFragment.java
│ │ │ │ │ │ ├── termux/
│ │ │ │ │ │ │ ├── DebuggingPreferencesFragment.java
│ │ │ │ │ │ │ ├── TerminalIOPreferencesFragment.java
│ │ │ │ │ │ │ └── TerminalViewPreferencesFragment.java
│ │ │ │ │ │ ├── termux_api/
│ │ │ │ │ │ │ └── DebuggingPreferencesFragment.java
│ │ │ │ │ │ ├── termux_float/
│ │ │ │ │ │ │ └── DebuggingPreferencesFragment.java
│ │ │ │ │ │ ├── termux_tasker/
│ │ │ │ │ │ │ └── DebuggingPreferencesFragment.java
│ │ │ │ │ │ └── termux_widget/
│ │ │ │ │ │ └── DebuggingPreferencesFragment.java
│ │ │ │ │ ├── models/
│ │ │ │ │ │ └── UserAction.java
│ │ │ │ │ └── terminal/
│ │ │ │ │ ├── TermuxActivityRootView.java
│ │ │ │ │ ├── TermuxSessionsListViewController.java
│ │ │ │ │ ├── TermuxTerminalSessionActivityClient.java
│ │ │ │ │ ├── TermuxTerminalSessionServiceClient.java
│ │ │ │ │ ├── TermuxTerminalViewClient.java
│ │ │ │ │ └── io/
│ │ │ │ │ ├── FullScreenWorkAround.java
│ │ │ │ │ ├── KeyboardShortcut.java
│ │ │ │ │ ├── TerminalToolbarViewPager.java
│ │ │ │ │ └── TermuxTerminalExtraKeys.java
│ │ │ │ └── filepicker/
│ │ │ │ └── TermuxDocumentsProvider.java
│ │ │ └── res/
│ │ │ ├── drawable/
│ │ │ │ ├── current_session.xml
│ │ │ │ ├── current_session_black.xml
│ │ │ │ ├── ic_foreground.xml
│ │ │ │ ├── ic_new_session.xml
│ │ │ │ ├── ic_service_notification.xml
│ │ │ │ ├── ic_settings.xml
│ │ │ │ ├── session_background_black_selected.xml
│ │ │ │ ├── session_background_selected.xml
│ │ │ │ ├── session_ripple.xml
│ │ │ │ ├── session_ripple_black.xml
│ │ │ │ └── terminal_scroll_shape.xml
│ │ │ ├── layout/
│ │ │ │ ├── activity_settings.xml
│ │ │ │ ├── activity_termux.xml
│ │ │ │ ├── item_terminal_sessions_list.xml
│ │ │ │ ├── preference_markdown_text.xml
│ │ │ │ ├── view_terminal_toolbar_extra_keys.xml
│ │ │ │ └── view_terminal_toolbar_text_input.xml
│ │ │ ├── mipmap-anydpi-v26/
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── values/
│ │ │ │ ├── attrs.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── strings.xml
│ │ │ │ ├── styles.xml
│ │ │ │ └── themes.xml
│ │ │ ├── values-night/
│ │ │ │ └── themes.xml
│ │ │ └── xml/
│ │ │ ├── root_preferences.xml
│ │ │ ├── shortcuts.xml
│ │ │ ├── termux_api_debugging_preferences.xml
│ │ │ ├── termux_api_preferences.xml
│ │ │ ├── termux_debugging_preferences.xml
│ │ │ ├── termux_float_debugging_preferences.xml
│ │ │ ├── termux_float_preferences.xml
│ │ │ ├── termux_preferences.xml
│ │ │ ├── termux_tasker_debugging_preferences.xml
│ │ │ ├── termux_tasker_preferences.xml
│ │ │ ├── termux_terminal_io_preferences.xml
│ │ │ ├── termux_terminal_view_preferences.xml
│ │ │ ├── termux_widget_debugging_preferences.xml
│ │ │ └── termux_widget_preferences.xml
│ │ └── test/
│ │ └── java/
│ │ └── com/
│ │ └── termux/
│ │ └── app/
│ │ ├── TermuxActivityTest.java
│ │ └── api/
│ │ └── file/
│ │ └── FileReceiverActivityTest.java
│ └── testkey_untrusted.jks
├── art/
│ ├── copy-to-other-apps.sh
│ ├── generate-big-icon.sh
│ ├── generate-feature-graphic.sh
│ ├── generate-launcher-images.sh
│ └── generate-tv-banner.sh
├── build.gradle
├── docs/
│ └── en/
│ └── index.md
├── fastlane/
│ └── metadata/
│ └── android/
│ └── en-US/
│ ├── full_description.txt
│ └── short_description.txt
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── jitpack.yml
├── settings.gradle
├── terminal-emulator/
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── termux/
│ │ │ └── terminal/
│ │ │ ├── ByteQueue.java
│ │ │ ├── JNI.java
│ │ │ ├── KeyHandler.java
│ │ │ ├── Logger.java
│ │ │ ├── TerminalBuffer.java
│ │ │ ├── TerminalColorScheme.java
│ │ │ ├── TerminalColors.java
│ │ │ ├── TerminalEmulator.java
│ │ │ ├── TerminalOutput.java
│ │ │ ├── TerminalRow.java
│ │ │ ├── TerminalSession.java
│ │ │ ├── TerminalSessionClient.java
│ │ │ ├── TextStyle.java
│ │ │ └── WcWidth.java
│ │ └── jni/
│ │ ├── Android.mk
│ │ └── termux.c
│ └── test/
│ └── java/
│ └── com/
│ └── termux/
│ └── terminal/
│ ├── ApcTest.java
│ ├── ByteQueueTest.java
│ ├── ControlSequenceIntroducerTest.java
│ ├── CursorAndScreenTest.java
│ ├── DecSetTest.java
│ ├── DeviceControlStringTest.java
│ ├── HistoryTest.java
│ ├── KeyHandlerTest.java
│ ├── OperatingSystemControlTest.java
│ ├── RectangularAreasTest.java
│ ├── ResizeTest.java
│ ├── ScreenBufferTest.java
│ ├── ScrollRegionTest.java
│ ├── TerminalRowTest.java
│ ├── TerminalTest.java
│ ├── TerminalTestCase.java
│ ├── TextStyleTest.java
│ ├── UnicodeInputTest.java
│ └── WcWidthTest.java
├── terminal-view/
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── termux/
│ │ └── view/
│ │ ├── GestureAndScaleRecognizer.java
│ │ ├── TerminalRenderer.java
│ │ ├── TerminalView.java
│ │ ├── TerminalViewClient.java
│ │ ├── support/
│ │ │ └── PopupWindowCompatGingerbread.java
│ │ └── textselection/
│ │ ├── CursorController.java
│ │ ├── TextSelectionCursorController.java
│ │ └── TextSelectionHandleView.java
│ └── res/
│ ├── drawable/
│ │ ├── text_select_handle_left_material.xml
│ │ └── text_select_handle_right_material.xml
│ └── values/
│ └── strings.xml
└── termux-shared/
├── .gitignore
├── LICENSE.md
├── build.gradle
├── proguard-rules.pro
└── src/
├── androidTest/
│ └── java/
│ └── com/
│ └── termux/
│ └── shared/
│ └── ExampleInstrumentedTest.java
└── main/
├── AndroidManifest.xml
├── cpp/
│ ├── Android.mk
│ ├── Application.mk
│ └── local-socket.cpp
├── java/
│ └── com/
│ └── termux/
│ └── shared/
│ ├── activities/
│ │ ├── ReportActivity.java
│ │ └── TextIOActivity.java
│ ├── activity/
│ │ ├── ActivityErrno.java
│ │ ├── ActivityUtils.java
│ │ └── media/
│ │ └── AppCompatActivityUtils.java
│ ├── android/
│ │ ├── AndroidUtils.java
│ │ ├── FeatureFlagUtils.java
│ │ ├── PackageUtils.java
│ │ ├── PermissionUtils.java
│ │ ├── PhantomProcessUtils.java
│ │ ├── ProcessUtils.java
│ │ ├── SELinuxUtils.java
│ │ ├── SettingsProviderUtils.java
│ │ ├── UserUtils.java
│ │ └── resource/
│ │ └── ResourceUtils.java
│ ├── crash/
│ │ └── CrashHandler.java
│ ├── data/
│ │ ├── DataUtils.java
│ │ └── IntentUtils.java
│ ├── errors/
│ │ ├── Errno.java
│ │ ├── Error.java
│ │ └── FunctionErrno.java
│ ├── file/
│ │ ├── FileUtils.java
│ │ ├── FileUtilsErrno.java
│ │ ├── filesystem/
│ │ │ ├── FileAttributes.java
│ │ │ ├── FileKey.java
│ │ │ ├── FilePermission.java
│ │ │ ├── FilePermissions.java
│ │ │ ├── FileTime.java
│ │ │ ├── FileType.java
│ │ │ ├── FileTypes.java
│ │ │ ├── NativeDispatcher.java
│ │ │ └── UnixConstants.java
│ │ └── tests/
│ │ └── FileUtilsTests.java
│ ├── interact/
│ │ ├── MessageDialogUtils.java
│ │ └── ShareUtils.java
│ ├── jni/
│ │ └── models/
│ │ └── JniResult.java
│ ├── logger/
│ │ └── Logger.java
│ ├── markdown/
│ │ └── MarkdownUtils.java
│ ├── models/
│ │ ├── ReportInfo.java
│ │ └── TextIOInfo.java
│ ├── net/
│ │ ├── socket/
│ │ │ └── local/
│ │ │ ├── ILocalSocketManager.java
│ │ │ ├── LocalClientSocket.java
│ │ │ ├── LocalServerSocket.java
│ │ │ ├── LocalSocketErrno.java
│ │ │ ├── LocalSocketManager.java
│ │ │ ├── LocalSocketManagerClientBase.java
│ │ │ ├── LocalSocketRunConfig.java
│ │ │ └── PeerCred.java
│ │ ├── uri/
│ │ │ ├── UriScheme.java
│ │ │ └── UriUtils.java
│ │ └── url/
│ │ └── UrlUtils.java
│ ├── notification/
│ │ └── NotificationUtils.java
│ ├── reflection/
│ │ └── ReflectionUtils.java
│ ├── settings/
│ │ ├── preferences/
│ │ │ ├── AppSharedPreferences.java
│ │ │ └── SharedPreferenceUtils.java
│ │ └── properties/
│ │ ├── SharedProperties.java
│ │ └── SharedPropertiesParser.java
│ ├── shell/
│ │ ├── ArgumentTokenizer.java
│ │ ├── ShellUtils.java
│ │ ├── StreamGobbler.java
│ │ ├── am/
│ │ │ ├── AmSocketServer.java
│ │ │ ├── AmSocketServerErrno.java
│ │ │ └── AmSocketServerRunConfig.java
│ │ └── command/
│ │ ├── ExecutionCommand.java
│ │ ├── ShellCommandConstants.java
│ │ ├── environment/
│ │ │ ├── AndroidShellEnvironment.java
│ │ │ ├── IShellEnvironment.java
│ │ │ ├── ShellCommandShellEnvironment.java
│ │ │ ├── ShellEnvironmentUtils.java
│ │ │ ├── ShellEnvironmentVariable.java
│ │ │ └── UnixShellEnvironment.java
│ │ ├── result/
│ │ │ ├── ResultConfig.java
│ │ │ ├── ResultData.java
│ │ │ ├── ResultSender.java
│ │ │ └── ResultSenderErrno.java
│ │ └── runner/
│ │ └── app/
│ │ └── AppShell.java
│ ├── termux/
│ │ ├── TermuxBootstrap.java
│ │ ├── TermuxConstants.java
│ │ ├── TermuxUtils.java
│ │ ├── crash/
│ │ │ └── TermuxCrashUtils.java
│ │ ├── data/
│ │ │ └── TermuxUrlUtils.java
│ │ ├── extrakeys/
│ │ │ ├── ExtraKeyButton.java
│ │ │ ├── ExtraKeysConstants.java
│ │ │ ├── ExtraKeysInfo.java
│ │ │ ├── ExtraKeysView.java
│ │ │ ├── SpecialButton.java
│ │ │ └── SpecialButtonState.java
│ │ ├── file/
│ │ │ └── TermuxFileUtils.java
│ │ ├── interact/
│ │ │ └── TextInputDialogUtils.java
│ │ ├── models/
│ │ │ └── UserAction.java
│ │ ├── notification/
│ │ │ └── TermuxNotificationUtils.java
│ │ ├── plugins/
│ │ │ └── TermuxPluginUtils.java
│ │ ├── settings/
│ │ │ ├── preferences/
│ │ │ │ ├── TermuxAPIAppSharedPreferences.java
│ │ │ │ ├── TermuxAppSharedPreferences.java
│ │ │ │ ├── TermuxBootAppSharedPreferences.java
│ │ │ │ ├── TermuxFloatAppSharedPreferences.java
│ │ │ │ ├── TermuxPreferenceConstants.java
│ │ │ │ ├── TermuxStylingAppSharedPreferences.java
│ │ │ │ ├── TermuxTaskerAppSharedPreferences.java
│ │ │ │ └── TermuxWidgetAppSharedPreferences.java
│ │ │ └── properties/
│ │ │ ├── TermuxAppSharedProperties.java
│ │ │ ├── TermuxPropertyConstants.java
│ │ │ └── TermuxSharedProperties.java
│ │ ├── shell/
│ │ │ ├── TermuxShellManager.java
│ │ │ ├── TermuxShellUtils.java
│ │ │ ├── am/
│ │ │ │ └── TermuxAmSocketServer.java
│ │ │ └── command/
│ │ │ ├── environment/
│ │ │ │ ├── TermuxAPIShellEnvironment.java
│ │ │ │ ├── TermuxAppShellEnvironment.java
│ │ │ │ ├── TermuxShellCommandShellEnvironment.java
│ │ │ │ └── TermuxShellEnvironment.java
│ │ │ └── runner/
│ │ │ └── terminal/
│ │ │ └── TermuxSession.java
│ │ ├── terminal/
│ │ │ ├── TermuxTerminalSessionClientBase.java
│ │ │ ├── TermuxTerminalViewClientBase.java
│ │ │ └── io/
│ │ │ ├── BellHandler.java
│ │ │ └── TerminalExtraKeys.java
│ │ └── theme/
│ │ └── TermuxThemeUtils.java
│ ├── theme/
│ │ ├── NightMode.java
│ │ └── ThemeUtils.java
│ └── view/
│ ├── KeyboardUtils.java
│ └── ViewUtils.java
└── res/
├── drawable/
│ ├── ic_copy.xml
│ ├── ic_error_notification.xml
│ ├── ic_info.xml
│ ├── ic_settings.xml
│ └── ic_share.xml
├── layout/
│ ├── activity_report.xml
│ ├── activity_text_io.xml
│ ├── dialog_show_message.xml
│ ├── markdown_adapter_node_code_block.xml
│ ├── markdown_adapter_node_default.xml
│ └── partial_primary_toolbar.xml
├── menu/
│ ├── menu_report.xml
│ └── menu_text_io.xml
├── raw/
│ ├── apt_info_script.sh
│ ├── bell.ogg
│ └── keep.xml
├── values/
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ ├── styles.xml
│ └── themes.xml
└── values-night/
└── themes.xml
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided this notice is
# preserved. This file is offered as-is, without any warranty.
# EditorConfig
# http://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 4
[*.y{a,}ml]
indent_size = 2
indent_style = space
================================================
FILE: .gitattributes
================================================
* text=auto
*.bat text eol=crlf
*.gradle text eol=lf
*.mk text eol=lf
*.sh text eol=lf
================================================
FILE: .github/FUNDING.yml
================================================
custom: https://termux.dev/donate
================================================
FILE: .github/ISSUE_TEMPLATE/01-bug-report.yml
================================================
name: "Bug report"
description: "Create a report to help us improve"
title: "[Bug]: "
labels: ["bug report"]
body:
- type: markdown
attributes:
value: |
**THIS IS A BUG TRACKER OF THE TERMUX APP. IF YOU HAVE ISSUES WITH A PACKAGE INSIDE THE APP, THEN PLEASE OPEN AN ISSUE AT [TERMUX/TERMUX-PACKAGES](https://github.com/termux/termux-packages) INSTEAD.**
If you are unsure if this is a bug with the Termux app itself or any of the packages, kindly open up the bug at [termux/termux-packages](https://github.com/termux/termux-packages) as it's very likely that it belongs there.
Use search before you open an issue to check whether your issue has been already reported and perhaps solved.
Android versions 5.x and 6.x are not supported anymore.
If you have issues installing packages then please see https://github.com/termux/termux-packages/issues/6726.
- type: textarea
attributes:
label: Problem description
description: |
A clear and concise description of what the problem is. You may attach the logs, screenshots, screen video recording and whatever else that will help to understand the issue.
Issues without proper description will be closed without solution.
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce the behavior.
description: |
Please post all necessary commands that are needed to reproduce the issue.
validations:
required: true
- type: textarea
attributes:
label: What is the expected behavior?
- type: textarea
attributes:
label: System information
description: Please provide info about your device
value: |
* Termux application version:
* Android OS version:
* Device model:
validations:
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/02-feature-request.yml
================================================
name: "Feature request"
description: "Suggest a new feature for Termux application"
title: "[Feature]: "
labels: ["feature request"]
body:
- type: textarea
attributes:
label: Feature description
description: Describe the feature and why you want it.
validations:
required: true
- type: textarea
attributes:
label: Additional information
description: |
Does another app/terminal emulator have this feature?
Provide links to more background information.
validations:
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: Want ask questions about the project?
url: https://github.com/termux/termux-app/discussions
about: Join GitHub Discussions
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: daily
commit-message:
# Prefix all commit messages with "Changed: "
prefix: "Changed"
================================================
FILE: .github/workflows/attach_debug_apks_to_release.yml
================================================
name: Attach Debug APKs To Release
on:
release:
types:
- published
jobs:
attach-apks:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
package_variant: [ apt-android-7, apt-android-5 ]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Clone repository
uses: actions/checkout@v6
with:
ref: ${{ env.GITHUB_REF }}
- name: Build and attach APKs to release
shell: bash {0}
env:
PACKAGE_VARIANT: ${{ matrix.package_variant }}
run: |
exit_on_error() {
echo "$1"
echo "Deleting '$RELEASE_VERSION_NAME' release and '$GITHUB_REF' tag"
hub release delete "$RELEASE_VERSION_NAME"
git push --delete origin "$GITHUB_REF"
exit 1
}
echo "Setting vars"
RELEASE_VERSION_NAME="${GITHUB_REF/refs\/tags\//}"
if ! printf "%s" "${RELEASE_VERSION_NAME/v/}" | grep -qP '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'; then
exit_on_error "The versionName '${RELEASE_VERSION_NAME/v/}' is not a valid version as per semantic version '2.0.0' spec in the format 'major.minor.patch(-prerelease)(+buildmetadata)'. https://semver.org/spec/v2.0.0.html."
fi
APK_DIR_PATH="./app/build/outputs/apk/debug"
APK_VERSION_TAG="$RELEASE_VERSION_NAME+${{ env.PACKAGE_VARIANT }}-github-debug"
APK_BASENAME_PREFIX="termux-app_$APK_VERSION_TAG"
echo "Building APKs for 'APK_VERSION_TAG' release"
export TERMUX_APK_VERSION_TAG="$APK_VERSION_TAG" # Used by app/build.gradle
export TERMUX_PACKAGE_VARIANT="${{ env.PACKAGE_VARIANT }}" # Used by app/build.gradle
if ! ./gradlew assembleDebug; then
exit_on_error "Build failed for '$APK_VERSION_TAG' release."
fi
echo "Validating APKs"
for abi in universal arm64-v8a armeabi-v7a x86_64 x86; do
if ! test -f "$APK_DIR_PATH/${APK_BASENAME_PREFIX}_$abi.apk"; then
files_found="$(ls "$APK_DIR_PATH")"
exit_on_error "Failed to find built APK at '$APK_DIR_PATH/${APK_BASENAME_PREFIX}_$abi.apk'. Files found: "$'\n'"$files_found"
fi
done
echo "Generating sha25sums file"
if ! (cd "$APK_DIR_PATH"; sha256sum \
"${APK_BASENAME_PREFIX}_universal.apk" \
"${APK_BASENAME_PREFIX}_arm64-v8a.apk" \
"${APK_BASENAME_PREFIX}_armeabi-v7a.apk" \
"${APK_BASENAME_PREFIX}_x86_64.apk" \
"${APK_BASENAME_PREFIX}_x86.apk" \
> "${APK_BASENAME_PREFIX}_sha256sums"); then
exit_on_error "Generate sha25sums failed for '$APK_VERSION_TAG' release."
fi
echo "Attaching APKs to github release"
if ! hub release edit \
-m "" \
-a "$APK_DIR_PATH/${APK_BASENAME_PREFIX}_universal.apk" \
-a "$APK_DIR_PATH/${APK_BASENAME_PREFIX}_arm64-v8a.apk" \
-a "$APK_DIR_PATH/${APK_BASENAME_PREFIX}_armeabi-v7a.apk" \
-a "$APK_DIR_PATH/${APK_BASENAME_PREFIX}_x86_64.apk" \
-a "$APK_DIR_PATH/${APK_BASENAME_PREFIX}_x86.apk" \
-a "$APK_DIR_PATH/${APK_BASENAME_PREFIX}_sha256sums" \
"$RELEASE_VERSION_NAME"; then
exit_on_error "Attach APKs to release failed for '$APK_VERSION_TAG' release."
fi
================================================
FILE: .github/workflows/debug_build.yml
================================================
name: Build
on:
push:
branches:
- master
- 'github-releases/**'
pull_request:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
package_variant: [ apt-android-7, apt-android-5 ]
steps:
- name: Clone repository
uses: actions/checkout@v6
- name: Setup java 17
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '17'
- name: Build APKs
shell: bash {0}
env:
PACKAGE_VARIANT: ${{ matrix.package_variant }}
run: |
exit_on_error() { echo "$1"; exit 1; }
echo "Setting vars"
if [ "$GITHUB_EVENT_NAME" == "pull_request" ]; then
GITHUB_SHA="${{ github.event.pull_request.head.sha }}" # Do not use last merge commit set in GITHUB_SHA
fi
# Set RELEASE_VERSION_NAME to "<CURRENT_VERSION_NAME>+<last_commit_hash>"
CURRENT_VERSION_NAME_REGEX='\s+versionName "([^"]+)"$'
CURRENT_VERSION_NAME="$(grep -m 1 -E "$CURRENT_VERSION_NAME_REGEX" ./app/build.gradle | sed -r "s/$CURRENT_VERSION_NAME_REGEX/\1/")"
RELEASE_VERSION_NAME="v$CURRENT_VERSION_NAME+${GITHUB_SHA:0:7}" # The "+" is necessary so that versioning precedence is not affected
if ! printf "%s" "${RELEASE_VERSION_NAME/v/}" | grep -qP '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'; then
exit_on_error "The versionName '${RELEASE_VERSION_NAME/v/}' is not a valid version as per semantic version '2.0.0' spec in the format 'major.minor.patch(-prerelease)(+buildmetadata)'. https://semver.org/spec/v2.0.0.html."
fi
APK_DIR_PATH="./app/build/outputs/apk/debug"
APK_VERSION_TAG="$RELEASE_VERSION_NAME-${{ env.PACKAGE_VARIANT }}-github-debug" # Note the "-", GITHUB_SHA will already have "+" before it
APK_BASENAME_PREFIX="termux-app_$APK_VERSION_TAG"
# Used by attachment steps later
echo "APK_DIR_PATH=$APK_DIR_PATH" >> $GITHUB_ENV
echo "APK_VERSION_TAG=$APK_VERSION_TAG" >> $GITHUB_ENV
echo "APK_BASENAME_PREFIX=$APK_BASENAME_PREFIX" >> $GITHUB_ENV
echo "Building APKs for 'APK_VERSION_TAG' build"
export TERMUX_APP_VERSION_NAME="${RELEASE_VERSION_NAME/v/}" # Used by app/build.gradle
export TERMUX_APK_VERSION_TAG="$APK_VERSION_TAG" # Used by app/build.gradle
export TERMUX_PACKAGE_VARIANT="${{ env.PACKAGE_VARIANT }}" # Used by app/build.gradle
if ! ./gradlew assembleDebug; then
exit_on_error "Build failed for '$APK_VERSION_TAG' build."
fi
echo "Validating APKs"
for abi in universal arm64-v8a armeabi-v7a x86_64 x86; do
if ! test -f "$APK_DIR_PATH/${APK_BASENAME_PREFIX}_$abi.apk"; then
files_found="$(ls "$APK_DIR_PATH")"
exit_on_error "Failed to find built APK at '$APK_DIR_PATH/${APK_BASENAME_PREFIX}_$abi.apk'. Files found: "$'\n'"$files_found"
fi
done
echo "Generating sha25sums file"
if ! (cd "$APK_DIR_PATH"; sha256sum \
"${APK_BASENAME_PREFIX}_universal.apk" \
"${APK_BASENAME_PREFIX}_arm64-v8a.apk" \
"${APK_BASENAME_PREFIX}_armeabi-v7a.apk" \
"${APK_BASENAME_PREFIX}_x86_64.apk" \
"${APK_BASENAME_PREFIX}_x86.apk" \
> "${APK_BASENAME_PREFIX}_sha256sums"); then
exit_on_error "Generate sha25sums failed for '$APK_VERSION_TAG' release."
fi
- name: Attach universal APK file
uses: actions/upload-artifact@v6
with:
name: ${{ env.APK_BASENAME_PREFIX }}_universal
path: |
${{ env.APK_DIR_PATH }}/${{ env.APK_BASENAME_PREFIX }}_universal.apk
${{ env.APK_DIR_PATH }}/output-metadata.json
- name: Attach arm64-v8a APK file
uses: actions/upload-artifact@v6
with:
name: ${{ env.APK_BASENAME_PREFIX }}_arm64-v8a
path: |
${{ env.APK_DIR_PATH }}/${{ env.APK_BASENAME_PREFIX }}_arm64-v8a.apk
${{ env.APK_DIR_PATH }}/output-metadata.json
- name: Attach armeabi-v7a APK file
uses: actions/upload-artifact@v6
with:
name: ${{ env.APK_BASENAME_PREFIX }}_armeabi-v7a
path: |
${{ env.APK_DIR_PATH }}/${{ env.APK_BASENAME_PREFIX }}_armeabi-v7a.apk
${{ env.APK_DIR_PATH }}/output-metadata.json
- name: Attach x86_64 APK file
uses: actions/upload-artifact@v6
with:
name: ${{ env.APK_BASENAME_PREFIX }}_x86_64
path: |
${{ env.APK_DIR_PATH }}/${{ env.APK_BASENAME_PREFIX }}_x86_64.apk
${{ env.APK_DIR_PATH }}/output-metadata.json
- name: Attach x86 APK file
uses: actions/upload-artifact@v6
with:
name: ${{ env.APK_BASENAME_PREFIX }}_x86
path: |
${{ env.APK_DIR_PATH }}/${{ env.APK_BASENAME_PREFIX }}_x86.apk
${{ env.APK_DIR_PATH }}/output-metadata.json
- name: Attach sha256sums file
uses: actions/upload-artifact@v6
with:
name: ${{ env.APK_BASENAME_PREFIX }}_sha256sums
path: |
${{ env.APK_DIR_PATH }}/${{ env.APK_BASENAME_PREFIX }}_sha256sums
${{ env.APK_DIR_PATH }}/output-metadata.json
================================================
FILE: .github/workflows/dependency-submission.yml
================================================
name: Automatic Dependency Submission
on:
push:
branches: [ 'master' ]
workflow_dispatch:
permissions:
contents: write
jobs:
dependency-submission:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v6
- name: Setup Java
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: 17
- name: Generate and submit dependency graph
uses: gradle/actions/dependency-submission@v5
================================================
FILE: .github/workflows/gradle-wrapper-validation.yml
================================================
name: "Validate Gradle Wrapper"
on:
push:
branches:
- master
- android-10
pull_request:
branches:
- master
- android-10
jobs:
validation:
name: "Validation"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: gradle/actions/wrapper-validation@5
================================================
FILE: .github/workflows/run_tests.yml
================================================
name: Unit tests
on:
push:
branches:
- master
- android-10
pull_request:
branches:
- master
- android-10
jobs:
testing:
runs-on: ubuntu-latest
steps:
- name: Clone repository
uses: actions/checkout@v6
- name: Setup java 17
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '17'
- name: Execute tests
run: |
./gradlew test
================================================
FILE: .github/workflows/trigger_library_builds_on_jitpack.yml
================================================
name: Trigger Termux Library Builds on Jitpack
on:
release:
types:
- published
jobs:
trigger-termux-library-builds:
runs-on: ubuntu-latest
steps:
- name: Set vars
run: echo "TERMUX_LIB_VERSION=${GITHUB_REF/refs\/tags\/v/}" >> $GITHUB_ENV # Do not include "v" prefix
- name: Echo release
run: echo "Triggering termux library builds on jitpack for '$TERMUX_LIB_VERSION' release after waiting for 3 mins"
- name: Trigger termux library builds on jitpack
run: |
sleep 180 # It will take some time for the new tag to be detected by Jitpack
curl --max-time 600 --no-progress-meter "https://jitpack.io/com/termux/termux-app/terminal-emulator/$TERMUX_LIB_VERSION/terminal-emulator-$TERMUX_LIB_VERSION.pom"
curl --max-time 600 --no-progress-meter "https://jitpack.io/com/termux/termux-app/terminal-view/$TERMUX_LIB_VERSION/terminal-view-$TERMUX_LIB_VERSION.pom"
curl --max-time 600 --no-progress-meter "https://jitpack.io/com/termux/termux-app/termux-shared/$TERMUX_LIB_VERSION/termux-shared-$TERMUX_LIB_VERSION.pom"
================================================
FILE: .gitignore
================================================
# From https://gist.github.com/iainconnor/8605514
# with the addition of the /captures below.
/captures
# Built application files
build/
release/
*.apk
*.so
.externalNativeBuild
.cxx
*.zip
# Local configuration file (sdk path, etc)
local.properties
# Gradle generated files
.gradle/
# Signing files
.signing/
# Intellij
.idea/
*.iml
# Vim
*.swo
*.swp
# OS-specific files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
.swp
ehthumbs.db
Thumbs.db
================================================
FILE: LICENSE.md
================================================
The `termux/termux-app` repository is released under [GPLv3 only](https://www.gnu.org/licenses/gpl-3.0.html) license.
### Exceptions
- [Terminal Emulator for Android](https://github.com/jackpal/Android-Terminal-Emulator) code is used which is released under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) license. Check [`terminal-view`](terminal-view) and [`terminal-emulator`](terminal-emulator) libraries.
- Check [`termux-shared/LICENSE.md`](termux-shared/LICENSE.md) for `termux-shared` library related exceptions.
================================================
FILE: README.md
================================================
# Termux application
[](https://github.com/termux/termux-app/actions)
[](https://github.com/termux/termux-app/actions)
[](https://gitter.im/termux/termux)
[](https://discord.gg/HXpF69X)
[](https://jitpack.io/#termux/termux-app)
[Termux](https://termux.dev) is an Android terminal application and Linux environment.
Note that this repository is for the app itself (the user interface and the terminal emulation). For the packages installable inside the app, see [termux/termux-packages](https://github.com/termux/termux-packages).
Quick how-to about Termux package management is available at [Package Management](https://github.com/termux/termux-packages/wiki/Package-Management). It also has info on how to fix **`repository is under maintenance or down`** errors when running `apt` or `pkg` commands.
**We are looking for Termux Android application maintainers.**
***
**NOTICE: Termux may be unstable on Android 12+.** Android OS will kill any (phantom) processes greater than 32 (limit is for all apps combined) and also kill any processes using excessive CPU. You may get `[Process completed (signal 9) - press Enter]` message in the terminal without actually exiting the shell process yourself. Check the related issue [#2366](https://github.com/termux/termux-app/issues/2366), [issue tracker](https://issuetracker.google.com/u/1/issues/205156966), [phantom cached and empty processes docs](https://github.com/agnostic-apollo/Android-Docs/blob/master/en/docs/apps/processes/phantom-cached-and-empty-processes.md) and [this TLDR comment](https://github.com/termux/termux-app/issues/2366#issuecomment-1237468220) on how to disable trimming of phantom and excessive cpu usage processes. A proper docs page will be added later. An option to disable the killing should be available in Android 12L or 13, so upgrade at your own risk if you are on Android 11, specially if you are not rooted.
***
## Contents
- [Termux App and Plugins](#termux-app-and-plugins)
- [Installation](#installation)
- [Uninstallation](#uninstallation)
- [Important Links](#important-links)
- [Debugging](#debugging)
- [For Maintainers and Contributors](#for-maintainers-and-contributors)
- [Forking](#forking)
- [Sponsors and Funders](#sponsors-and-funders)
##
## Termux App and Plugins
The core [Termux](https://github.com/termux/termux-app) app comes with the following optional plugin apps.
- [Termux:API](https://github.com/termux/termux-api)
- [Termux:Boot](https://github.com/termux/termux-boot)
- [Termux:Float](https://github.com/termux/termux-float)
- [Termux:Styling](https://github.com/termux/termux-styling)
- [Termux:Tasker](https://github.com/termux/termux-tasker)
- [Termux:Widget](https://github.com/termux/termux-widget)
##
## Installation
Latest version is `v0.118.3`.
**NOTICE: It is highly recommended that you update to `v0.118.0` or higher ASAP for various bug fixes, including a critical world-readable vulnerability reported [here](https://termux.github.io/general/2022/02/15/termux-apps-vulnerability-disclosures.html). See [below](#google-play-store-experimental-branch) for information regarding Termux on Google Play.**
Termux can be obtained through various sources listed below for **only** Android `>= 7` with full support for apps and packages.
Support for both app and packages was dropped for Android `5` and `6` on [2020-01-01](https://www.reddit.com/r/termux/comments/dnzdbs/end_of_android56_support_on_20200101/) at `v0.83`, however it was re-added just for the app *without any support for package updates* on [2022-05-24](https://github.com/termux/termux-app/pull/2740) via the [GitHub](#github) sources. Check [here](https://github.com/termux/termux-app/wiki/Termux-on-android-5-or-6) for the details.
The APK files of different sources are signed with different signature keys. The `Termux` app and all its plugins use the same [`sharedUserId`](https://developer.android.com/guide/topics/manifest/manifest-element) `com.termux` and so all their APKs installed on a device must have been signed with the same signature key to work together and so they must all be installed from the same source. Do not attempt to mix them together, i.e do not try to install an app or plugin from `F-Droid` and another one from a different source like `GitHub`. Android Package Manager will also normally not allow installation of APKs with different signatures and you will get errors on installation like `App not installed`, `Failed to install due to an unknown error`, `INSTALL_FAILED_UPDATE_INCOMPATIBLE`, `INSTALL_FAILED_SHARED_USER_INCOMPATIBLE`, `signatures do not match previously installed version`, etc. This restriction can be bypassed with root or with custom roms.
If you wish to install from a different source, then you must **uninstall any and all existing Termux or its plugin app APKs** from your device first, then install all new APKs from the same new source. Check [Uninstallation](#uninstallation) section for details. You may also want to consider [Backing up Termux](https://wiki.termux.dev/wiki/Backing_up_Termux) before the uninstallation so that you can restore it after re-installing from Termux different source.
In the following paragraphs, *"bootstrap"* refers to the minimal packages that are shipped with the `termux-app` itself to start a working shell environment. Its zips are built and released [here](https://github.com/termux/termux-packages/releases).
### F-Droid
Termux application can be obtained from `F-Droid` from [here](https://f-droid.org/en/packages/com.termux/).
You **do not** need to download the `F-Droid` app (via the `Download F-Droid` link) to install Termux. You can download the Termux APK directly from the site by clicking the `Download APK` link at the bottom of each version section.
It usually takes a few days (or even a week or more) for updates to be available on `F-Droid` once an update has been released on `GitHub`. The `F-Droid` releases are built and published by `F-Droid` once they [detect](https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/com.termux.yml) a new `GitHub` release. The Termux maintainers **do not** have any control over the building and publishing of the Termux apps on `F-Droid`. Moreover, the Termux maintainers also do not have access to the APK signing keys of `F-Droid` releases, so we cannot release an APK ourselves on `GitHub` that would be compatible with `F-Droid` releases.
The `F-Droid` app often may not notify you of updates and you will manually have to do a pull down swipe action in the `Updates` tab of the app for it to check updates. Make sure battery optimizations are disabled for the app, check https://dontkillmyapp.com/ for details on how to do that.
Only a universal APK is released, which will work on all supported architectures. The APK and bootstrap installation size will be `~180MB`. `F-Droid` does [not support](https://github.com/termux/termux-app/pull/1904) architecture specific APKs.
### GitHub
Termux application can be obtained on `GitHub` either from [`GitHub Releases`](https://github.com/termux/termux-app/releases) for version `>= 0.118.0` or from [`GitHub Build Action`](https://github.com/termux/termux-app/actions/workflows/debug_build.yml?query=branch%3Amaster+event%3Apush) workflows. **For android `>= 7`, only install `apt-android-7` variants. For android `5` and `6`, only install `apt-android-5` variants.**
The APKs for `GitHub Releases` will be listed under `Assets` drop-down of a release. These are automatically attached when a new version is released.
The APKs for `GitHub Build` action workflows will be listed under `Artifacts` section of a workflow run. These are created for each commit/push done to the repository and can be used by users who don't want to wait for releases and want to try out the latest features immediately or want to test their pull requests. Note that for action workflows, you need to be [**logged into a `GitHub` account**](https://github.com/login) for the `Artifacts` links to be enabled/clickable. If you are using the [`GitHub` app](https://github.com/mobile), then make sure to open workflow link in a browser like Chrome or Firefox that has your GitHub account logged in since the in-app browser may not be logged in.
The APKs for both of these are [`debuggable`](https://developer.android.com/studio/debug) and are compatible with each other but they are not compatible with other sources.
Both universal and architecture specific APKs are released. The APK and bootstrap installation size will be `~180MB` if using universal and `~120MB` if using architecture specific. Check [here](https://github.com/termux/termux-app/issues/2153) for details.
**Security warning**: APK files on GitHub are signed with a test key that has been [shared with community](https://github.com/termux/termux-app/blob/master/app/testkey_untrusted.jks). This IS NOT an official developer key and everyone can use it to generate releases for own testing. Be very careful when using Termux GitHub builds obtained elsewhere except https://github.com/termux/termux-app. Everyone is able to use it to forge a malicious Termux update installable over the GitHub build. Think twice about installing Termux builds distributed via Telegram or other social media. If your device get caught by malware, we will not be able to help you.
The [test key](https://github.com/termux/termux-app/blob/master/app/testkey_untrusted.jks) shall not be used to impersonate @termux and can't be used for this anyway. This key is not trusted by us and it is quite easy to detect its use in user generated content.
<details>
<summary>Keystore information</summary>
```
Alias name: alias
Creation date: Oct 4, 2019
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=APK Signer, OU=Earth, O=Earth
Issuer: CN=APK Signer, OU=Earth, O=Earth
Serial number: 29be297b
Valid from: Wed Sep 04 02:03:24 EEST 2019 until: Tue Oct 26 02:03:24 EEST 2049
Certificate fingerprints:
SHA1: 51:79:55:EA:BF:69:FC:05:7C:41:C7:D3:79:DB:BC:EF:20:AD:85:F2
SHA256: B6:DA:01:48:0E:EF:D5:FB:F2:CD:37:71:B8:D1:02:1E:C7:91:30:4B:DD:6C:4B:F4:1D:3F:AA:BA:D4:8E:E5:E1
Signature algorithm name: SHA1withRSA (disabled)
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
```
</details>
### Google Play Store **(Experimental branch)**
There is currently a build of Termux available on Google Play for Android 11+ devices, with extensive adjustments in order to pass policy requirements there. This is under development and has missing functionality and bugs (see [here](https://github.com/termux-play-store/) for status updates) compared to the stable F-Droid build, which is why most users who can should still use F-Droid or GitHub build as mentioned above.
Currently, Google Play will try to update installations away from F-Droid ones. Updating will still fail as [sharedUserId](https://developer.android.com/guide/topics/manifest/manifest-element#uid) has been removed. A planned 0.118.1 F-Droid release will fix this by setting a higher version code than used for the PlayStore app. Meanwhile, to prevent Google Play from attempting to download and then fail to install the Google Play releases over existing installations, you can open the Termux apps pages on Google Play and then click on the 3 dots options button in the top right and then disable the Enable auto update toggle. However, the Termux apps updates will still show in the PlayStore app updates list.
If you want to help out with testing the Google Play build (or cannot install Termux from other sources), be aware that it's built from a separate repository (https://github.com/termux-play-store/) - be sure to report issues [there](https://github.com/termux-play-store/termux-issues/issues/new/choose), as any issues encountered might very well be specific to that repository.
## Uninstallation
Uninstallation may be required if a user doesn't want Termux installed in their device anymore or is switching to a different [install source](#installation). You may also want to consider [Backing up Termux](https://wiki.termux.com/wiki/Backing_up_Termux) before the uninstallation.
To uninstall Termux completely, you must uninstall **any and all existing Termux or its plugin app APKs** listed in [Termux App and Plugins](#termux-app-and-plugins).
Go to `Android Settings` -> `Applications` and then look for those apps. You can also use the search feature if it’s available on your device and search `termux` in the applications list.
Even if you think you have not installed any of the plugins, it's strongly suggested to go through the application list in Android settings and double-check.
##
## Important Links
### Community
All community links are available [here](https://wiki.termux.com/wiki/Community).
The main ones are the following.
- [Termux Reddit community](https://reddit.com/r/termux)
- [Termux User Matrix Channel](https://matrix.to/#/#termux_termux:gitter.im) ([Gitter](https://gitter.im/termux/termux))
- [Termux Dev Matrix Channel](https://matrix.to/#/#termux_dev:gitter.im) ([Gitter](https://gitter.im/termux/dev))
- [Termux X (Twitter)](https://twitter.com/termuxdevs)
- [Termux Support Email](mailto:support@termux.dev)
### Wikis
- [Termux Wiki](https://wiki.termux.com/wiki/)
- [Termux App Wiki](https://github.com/termux/termux-app/wiki)
- [Termux Packages Wiki](https://github.com/termux/termux-packages/wiki)
### Miscellaneous
- [FAQ](https://wiki.termux.com/wiki/FAQ)
- [Termux File System Layout](https://github.com/termux/termux-packages/wiki/Termux-file-system-layout)
- [Differences From Linux](https://wiki.termux.com/wiki/Differences_from_Linux)
- [Package Management](https://wiki.termux.com/wiki/Package_Management)
- [Remote Access](https://wiki.termux.com/wiki/Remote_Access)
- [Backing up Termux](https://wiki.termux.com/wiki/Backing_up_Termux)
- [Terminal Settings](https://wiki.termux.com/wiki/Terminal_Settings)
- [Touch Keyboard](https://wiki.termux.com/wiki/Touch_Keyboard)
- [Android Storage and Sharing Data with Other Apps](https://wiki.termux.com/wiki/Internal_and_external_storage)
- [Android APIs](https://wiki.termux.com/wiki/Termux:API)
- [Moved Termux Packages Hosting From Bintray to IPFS](https://github.com/termux/termux-packages/issues/6348)
- [Running Commands in Termux From Other Apps via `RUN_COMMAND` intent](https://github.com/termux/termux-app/wiki/RUN_COMMAND-Intent)
- [Termux and Android 10](https://github.com/termux/termux-packages/wiki/Termux-and-Android-10)
### Terminal
<details>
<summary></summary>
### Terminal resources
- [XTerm control sequences](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html)
- [vt100.net](https://vt100.net/)
- [Terminal codes (ANSI and terminfo equivalents)](https://wiki.bash-hackers.org/scripting/terminalcodes)
### Terminal emulators
- VTE (libvte): Terminal emulator widget for GTK+, mainly used in gnome-terminal. [Source](https://github.com/GNOME/vte), [Open Issues](https://bugzilla.gnome.org/buglist.cgi?quicksearch=product%3A%22vte%22+), and [All (including closed) issues](https://bugzilla.gnome.org/buglist.cgi?bug_status=RESOLVED&bug_status=VERIFIED&chfield=resolution&chfieldfrom=-2000d&chfieldvalue=FIXED&product=vte&resolution=FIXED).
- iTerm 2: OS X terminal application. [Source](https://github.com/gnachman/iTerm2), [Issues](https://gitlab.com/gnachman/iterm2/issues) and [Documentation](https://iterm2.com/documentation.html) (which includes [iTerm2 proprietary escape codes](https://iterm2.com/documentation-escape-codes.html)).
- Konsole: KDE terminal application. [Source](https://projects.kde.org/projects/kde/applications/konsole/repository), in particular [tests](https://projects.kde.org/projects/kde/applications/konsole/repository/revisions/master/show/tests), [Bugs](https://bugs.kde.org/buglist.cgi?bug_severity=critical&bug_severity=grave&bug_severity=major&bug_severity=crash&bug_severity=normal&bug_severity=minor&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&product=konsole) and [Wishes](https://bugs.kde.org/buglist.cgi?bug_severity=wishlist&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&product=konsole).
- hterm: JavaScript terminal implementation from Chromium. [Source](https://github.com/chromium/hterm), including [tests](https://github.com/chromium/hterm/blob/master/js/hterm_vt_tests.js), and [Google group](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-hterm).
- xterm: The grandfather of terminal emulators. [Source](https://invisible-island.net/datafiles/release/xterm.tar.gz).
- Connectbot: Android SSH client. [Source](https://github.com/connectbot/connectbot)
- Android Terminal Emulator: Android terminal app which Termux terminal handling is based on. Inactive. [Source](https://github.com/jackpal/Android-Terminal-Emulator).
</details>
##
### Debugging
You can help debug problems of the `Termux` app and its plugins by setting appropriate `logcat` `Log Level` in `Termux` app settings -> `<APP_NAME>` -> `Debugging` -> `Log Level` (Requires `Termux` app version `>= 0.118.0`). The `Log Level` defaults to `Normal` and log level `Verbose` currently logs additional information. Its best to revert log level to `Normal` after you have finished debugging since private data may otherwise be passed to `logcat` during normal operation and moreover, additional logging increases execution time.
The plugin apps **do not execute the commands themselves** but send execution intents to `Termux` app, which has its own log level which can be set in `Termux` app settings -> `Termux` -> `Debugging` -> `Log Level`. So you must set log level for both `Termux` and the respective plugin app settings to get all the info.
Once log levels have been set, you can run the `logcat` command in `Termux` app terminal to view the logs in realtime (`Ctrl+c` to stop) or use `logcat -d > logcat.txt` to take a dump of the log. You can also view the logs from a PC over `ADB`. For more information, check official android `logcat` guide [here](https://developer.android.com/studio/command-line/logcat).
Moreover, users can generate termux files `stat` info and `logcat` dump automatically too with terminal's long hold options menu `More` -> `Report Issue` option and selecting `YES` in the prompt shown to add debug info. This can be helpful for reporting and debugging other issues. If the report generated is too large, then `Save To File` option in context menu (3 dots on top right) of `ReportActivity` can be used and the file viewed/shared instead.
Users must post complete report (optionally without sensitive info) when reporting issues. Issues opened with **(partial) screenshots of error reports** instead of text will likely be automatically closed/deleted.
##### Log Levels
- `Off` - Log nothing.
- `Normal` - Start logging error, warn and info messages and stacktraces.
- `Debug` - Start logging debug messages.
- `Verbose` - Start logging verbose messages.
##
## For Maintainers and Contributors
The [termux-shared](termux-shared) library was added in [`v0.109`](https://github.com/termux/termux-app/releases/tag/v0.109). It defines shared constants and utils of the Termux app and its plugins. It was created to allow for the removal of all hardcoded paths in the Termux app. Some of the termux plugins are using this as well and rest will in future. If you are contributing code that is using a constant or a util that may be shared, then define it in `termux-shared` library if it currently doesn't exist and reference it from there. Update the relevant changelogs as well. Pull requests using hardcoded values **will/should not** be accepted. Termux app and plugin specific classes must be added under `com.termux.shared.termux` package and general classes outside it. The [`termux-shared` `LICENSE`](termux-shared/LICENSE.md) must also be checked and updated if necessary when contributing code. The licenses of any external library or code must be honoured.
The main Termux constants are defined by [`TermuxConstants`](https://github.com/termux/termux-app/blob/master/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java) class. It also contains information on how to fork Termux or build it with your own package name. Changing the package name will require building the bootstrap zip packages and other packages with the new `$PREFIX`, check [Building Packages](https://github.com/termux/termux-packages/wiki/Building-packages) for more info.
Check [Termux Libraries](https://github.com/termux/termux-app/wiki/Termux-Libraries) for how to import termux libraries in plugin apps and [Forking and Local Development](https://github.com/termux/termux-app/wiki/Termux-Libraries#forking-and-local-development) for how to update termux libraries for plugins.
The `versionName` in `build.gradle` files of Termux and its plugin apps must follow the [semantic version `2.0.0` spec](https://semver.org/spec/v2.0.0.html) in the format `major.minor.patch(-prerelease)(+buildmetadata)`. When bumping `versionName` in `build.gradle` files and when creating a tag for new releases on GitHub, make sure to include the patch number as well, like `v0.1.0` instead of just `v0.1`. The `build.gradle` files and `attach_debug_apks_to_release` workflow validates the version as well and the build/attachment will fail if `versionName` does not follow the spec.
### Commit Messages Guidelines
Commit messages **must** use the [Conventional Commits](https://www.conventionalcommits.org) spec so that chagelogs as per the [Keep a Changelog](https://github.com/olivierlacan/keep-a-changelog) spec can automatically be generated by the [`create-conventional-changelog`](https://github.com/termux/create-conventional-changelog) script, check its repo for further details on the spec. **The first letter for `type` and `description` must be capital and description should be in the present tense.** The space after the colon `:` is necessary. For a breaking change, add an exclamation mark `!` before the colon `:`, so that it is highlighted in the chagelog automatically.
```
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
```
**Only the `types` listed below must be used exactly as they are used in the changelog headings.** For example, `Added: Add foo`, `Added|Fixed: Add foo and fix bar`, `Changed!: Change baz as a breaking change`, etc. You can optionally add a scope as well, like `Fixed(terminal): Fix some bug`. **Do not use anything else as type, like `add` instead of `Added`, etc.**
- **Added** for new features.
- **Changed** for changes in existing functionality.
- **Deprecated** for soon-to-be removed features.
- **Removed** for now removed features.
- **Fixed** for any bug fixes.
- **Security** in case of vulnerabilities.
##
## Forking
- Check [`TermuxConstants`](https://github.com/termux/termux-app/blob/master/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java) javadocs for instructions on what changes to make in the app to change package name.
- You also need to recompile bootstrap zip for the new package name. Check [building bootstrap](https://github.com/termux/termux-packages/wiki/For-maintainers#build-bootstrap-archives), [here](https://github.com/termux/termux-app/issues/1983) and [here](https://github.com/termux/termux-app/issues/2081#issuecomment-865280111).
- Currently, not all plugins use `TermuxConstants` from `termux-shared` library and have hardcoded `com.termux` values and will need to be manually patched.
- If forking termux plugins, check [Forking and Local Development](https://github.com/termux/termux-app/wiki/Termux-Libraries#forking-and-local-development) for info on how to use termux libraries for plugins.
##
## Sponsors and Funders
[<img alt="GitHub Accelerator" width="25%" src="site/assets/sponsors/github.png" />](https://github.com)
*[GitHub Accelerator](https://github.com/accelerator) ([1](https://github.blog/2023-04-12-github-accelerator-our-first-cohort-and-whats-next))*
[<img alt="GitHub Secure Open Source Fund" width="25%" src="site/assets/sponsors/github.png" />](https://github.com)
*[GitHub Secure Open Source Fund](https://resources.github.com/github-secure-open-source-fund) ([1](https://github.blog/open-source/maintainers/securing-the-supply-chain-at-scale-starting-with-71-important-open-source-projects), [2](https://termux.dev/en/posts/general/2025/08/11/termux-selected-for-github-secure-open-source-fund-session-2.html))*
[<img alt="NLnet NGI Mobifree" width="25%" src="site/assets/sponsors/nlnet-ngi-mobifree.png" />](https://nlnet.nl/mobifree)
*[NLnet NGI Mobifree](https://nlnet.nl/mobifree) ([1](https://nlnet.nl/news/2024/20241111-NGI-Mobifree-grants.html), [2](https://termux.dev/en/posts/general/2024/11/11/termux-selected-for-nlnet-ngi-mobifree-grant.html))*
[<img alt="Cloudflare" width="25%" src="site/assets/sponsors/cloudflare.png" />](https://www.cloudflare.com)
*[Cloudflare](https://www.cloudflare.com) ([1](https://packages-cf.termux.dev))*
[<img alt="Warp" width="25%" src="https://github.com/warpdotdev/brand-assets/blob/640dffd347439bbcb535321ab36b7281cf4446c0/Github/Sponsor/Warp-Github-LG-03.png" />](https://www.warp.dev/?utm_source=github&utm_medium=readme&utm_campaign=termux)
[*Warp, built for coding with multiple AI agents*](https://www.warp.dev/?utm_source=github&utm_medium=readme&utm_campaign=termux)
================================================
FILE: SECURITY.md
================================================
Check https://termux.dev/security for info on Termux security policies and how to report vulnerabilities.
================================================
FILE: app/build.gradle
================================================
plugins {
id "com.android.application"
}
ext {
// The packageVariant defines the bootstrap variant that will be included in the app APK.
// This must be supported by com.termux.shared.termux.TermuxBootstrap.PackageVariant or app will
// crash at startup.
// 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 supported values are: [ "apt-android-7" "apt-android-5" ]
packageVariant = System.getenv("TERMUX_PACKAGE_VARIANT") ?: "apt-android-7" // Default: "apt-android-7"
}
android {
namespace "com.termux"
compileSdkVersion project.properties.compileSdkVersion.toInteger()
ndkVersion = System.getenv("JITPACK_NDK_VERSION") ?: project.properties.ndkVersion
def appVersionName = System.getenv("TERMUX_APP_VERSION_NAME") ?: ""
def apkVersionTag = System.getenv("TERMUX_APK_VERSION_TAG") ?: ""
def splitAPKsForDebugBuilds = System.getenv("TERMUX_SPLIT_APKS_FOR_DEBUG_BUILDS") ?: "1"
def splitAPKsForReleaseBuilds = System.getenv("TERMUX_SPLIT_APKS_FOR_RELEASE_BUILDS") ?: "0" // F-Droid does not support split APKs #1904
dependencies {
implementation "androidx.annotation:annotation:1.9.0"
implementation "androidx.core:core:1.13.1"
implementation "androidx.drawerlayout:drawerlayout:1.2.0"
implementation "androidx.preference:preference:1.2.1"
implementation "androidx.viewpager:viewpager:1.0.0"
implementation "com.google.android.material:material:1.12.0"
implementation "com.google.guava:guava:24.1-jre"
implementation "io.noties.markwon:core:$markwonVersion"
implementation "io.noties.markwon:ext-strikethrough:$markwonVersion"
implementation "io.noties.markwon:linkify:$markwonVersion"
implementation "io.noties.markwon:recycler:$markwonVersion"
implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
implementation project(":terminal-view")
implementation project(":termux-shared")
}
defaultConfig {
minSdkVersion project.properties.minSdkVersion.toInteger()
targetSdkVersion project.properties.targetSdkVersion.toInteger()
versionCode 118
versionName "0.118.0"
if (appVersionName) versionName = appVersionName
validateVersionName(versionName)
buildConfigField "String", "TERMUX_PACKAGE_VARIANT", "\"" + project.ext.packageVariant + "\"" // Used by TermuxApplication class
manifestPlaceholders.TERMUX_PACKAGE_NAME = "com.termux"
manifestPlaceholders.TERMUX_APP_NAME = "Termux"
manifestPlaceholders.TERMUX_API_APP_NAME = "Termux:API"
manifestPlaceholders.TERMUX_BOOT_APP_NAME = "Termux:Boot"
manifestPlaceholders.TERMUX_FLOAT_APP_NAME = "Termux:Float"
manifestPlaceholders.TERMUX_STYLING_APP_NAME = "Termux:Styling"
manifestPlaceholders.TERMUX_TASKER_APP_NAME = "Termux:Tasker"
manifestPlaceholders.TERMUX_WIDGET_APP_NAME = "Termux:Widget"
externalNativeBuild {
ndkBuild {
cFlags "-std=c11", "-Wall", "-Wextra", "-Werror", "-Os", "-fno-stack-protector", "-Wl,--gc-sections"
}
}
splits {
abi {
enable ((gradle.startParameter.taskNames.any { it.contains("Debug") } && splitAPKsForDebugBuilds == "1") ||
(gradle.startParameter.taskNames.any { it.contains("Release") } && splitAPKsForReleaseBuilds == "1"))
reset ()
include 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
universalApk true
}
}
}
signingConfigs {
debug {
storeFile file('testkey_untrusted.jks')
keyAlias 'alias'
storePassword 'xrj45yWGLbsO7W0v'
keyPassword 'xrj45yWGLbsO7W0v'
}
}
buildTypes {
release {
minifyEnabled true
shrinkResources false // Reproducible builds
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
signingConfig signingConfigs.debug
}
}
compileOptions {
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
externalNativeBuild {
ndkBuild {
path "src/main/cpp/Android.mk"
}
}
lint {
disable 'ProtectedPermissions'
}
testOptions {
unitTests {
includeAndroidResources = true
}
}
packagingOptions {
jniLibs {
useLegacyPackaging true
}
}
applicationVariants.all { variant ->
variant.outputs.all { output ->
if (variant.buildType.name == "debug") {
def abi = output.getFilter(com.android.build.OutputFile.ABI)
outputFileName = new File("termux-app_" + (apkVersionTag ? apkVersionTag : project.ext.packageVariant + "-" + "debug") + "_" + (abi ? abi : "universal") + ".apk")
} else if (variant.buildType.name == "release") {
def abi = output.getFilter(com.android.build.OutputFile.ABI)
outputFileName = new File("termux-app_" + (apkVersionTag ? apkVersionTag : project.ext.packageVariant + "-" + "release") + "_" + (abi ? abi : "universal") + ".apk")
}
}
}
buildFeatures {
buildConfig true
}
}
dependencies {
testImplementation "junit:junit:4.13.2"
testImplementation "org.robolectric:robolectric:4.10"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
}
task versionName {
doLast {
print android.defaultConfig.versionName
}
}
def validateVersionName(String versionName) {
// https://semver.org/spec/v2.0.0.html#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
// ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
if (!java.util.regex.Pattern.matches("^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?\$", versionName))
throw new GradleException("The versionName '" + versionName + "' is not a valid version as per semantic version '2.0.0' spec in the format 'major.minor.patch(-prerelease)(+buildmetadata)'. https://semver.org/spec/v2.0.0.html.")
}
def downloadBootstrap(String arch, String expectedChecksum, String version) {
def digest = java.security.MessageDigest.getInstance("SHA-256")
def localUrl = "src/main/cpp/bootstrap-" + arch + ".zip"
def file = new File(projectDir, localUrl)
if (file.exists()) {
def buffer = new byte[8192]
def input = new FileInputStream(file)
while (true) {
def readBytes = input.read(buffer)
if (readBytes < 0) break
digest.update(buffer, 0, readBytes)
}
def checksum = new BigInteger(1, digest.digest()).toString(16)
while (checksum.length() < 64) { checksum = "0" + checksum }
if (checksum == expectedChecksum) {
return
} else {
logger.quiet("Deleting old local file with wrong hash: " + localUrl + ": expected: " + expectedChecksum + ", actual: " + checksum)
file.delete()
}
}
def remoteUrl = "https://github.com/termux/termux-packages/releases/download/bootstrap-" + version + "/bootstrap-" + arch + ".zip"
logger.quiet("Downloading " + remoteUrl + " ...")
file.parentFile.mkdirs()
def out = new BufferedOutputStream(new FileOutputStream(file))
def connection = new URL(remoteUrl).openConnection()
connection.setInstanceFollowRedirects(true)
def digestStream = new java.security.DigestInputStream(connection.inputStream, digest)
out << digestStream
out.close()
def checksum = new BigInteger(1, digest.digest()).toString(16)
while (checksum.length() < 64) { checksum = "0" + checksum }
if (checksum != expectedChecksum) {
file.delete()
throw new GradleException("Wrong checksum for " + remoteUrl + ": expected: " + expectedChecksum + ", actual: " + checksum)
}
}
clean {
doLast {
def tree = fileTree(new File(projectDir, 'src/main/cpp'))
tree.include 'bootstrap-*.zip'
tree.each { it.delete() }
}
}
task downloadBootstraps() {
doLast {
def packageVariant = project.ext.packageVariant
if (packageVariant == "apt-android-7") {
def version = "2026.02.12-r1" + "%2B" + "apt.android-7"
downloadBootstrap("aarch64", "ea2aeba8819e517db711f8c32369e89e7c52cee73e07930ff91185e1ab93f4f3", version)
downloadBootstrap("arm", "a38f4d3b2f735f83be2bf54eff463e86dc32a3e2f9f861c1557c4378d249c018", version)
downloadBootstrap("i686", "f5bc0b025b9f3b420b5fcaeefc064f888f5f22a0d6fd7090f4aac0c33eb3555b", version)
downloadBootstrap("x86_64", "b7fd0f2e3a4de534be3144f9f91acc768630fc463eaf134ab2e64c545e834f7a", version)
} else if (packageVariant == "apt-android-5") {
def version = "2022.04.28-r6" + "+" + packageVariant
downloadBootstrap("aarch64", "913609d439415c828c5640be1b0561467e539cb1c7080662decaaca2fb4820e7", version)
downloadBootstrap("arm", "26bfb45304c946170db69108e5eb6e3641aad751406ce106c80df80cad2eccf8", version)
downloadBootstrap("i686", "46dcfeb5eef67ba765498db9fe4c50dc4690805139aa0dd141a9d8ee0693cd27", version)
downloadBootstrap("x86_64", "615b590679ee6cd885b7fd2ff9473c845e920f9b422f790bb158c63fe42b8481", version)
} else {
throw new GradleException("Unsupported TERMUX_PACKAGE_VARIANT \"" + packageVariant + "\"")
}
}
}
afterEvaluate {
android.applicationVariants.all { variant ->
variant.javaCompileProvider.get().dependsOn(downloadBootstraps)
}
}
================================================
FILE: app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in android-sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
-dontobfuscate
#-renamesourcefileattribute SourceFile
#-keepattributes SourceFile,LineNumberTable
================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="internalOnly"
android:sharedUserId="${TERMUX_PACKAGE_NAME}"
android:sharedUserLabel="@string/shared_user_label">
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
<uses-feature
android:name="android.software.leanback"
android:required="false" />
<permission
android:name="${TERMUX_PACKAGE_NAME}.permission.RUN_COMMAND"
android:description="@string/permission_run_command_description"
android:icon="@mipmap/ic_launcher"
android:label="@string/permission_run_command_label"
android:protectionLevel="dangerous" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.DUMP" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<application
android:name=".app.TermuxApplication"
android:allowBackup="false"
android:banner="@drawable/banner"
android:icon="@mipmap/ic_launcher"
android:label="@string/application_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="false"
android:theme="@style/Theme.TermuxApp.DayNight.DarkActionBar"
tools:targetApi="m">
<activity
android:name=".app.TermuxActivity"
android:exported="true"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|keyboard|keyboardHidden|navigation"
android:label="@string/application_name"
android:launchMode="singleTask"
android:resizeableActivity="true"
android:theme="@style/Theme.TermuxActivity.DayNight.NoActionBar"
tools:targetApi="n">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
</activity>
<activity-alias
android:name=".HomeActivity"
android:exported="true"
android:targetActivity=".app.TermuxActivity">
<!-- Launch activity automatically on boot on Android Things devices -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.IOT_LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity-alias>
<activity
android:name=".app.activities.HelpActivity"
android:exported="false"
android:label="@string/application_name"
android:parentActivityName=".app.TermuxActivity"
android:resizeableActivity="true"
tools:targetApi="n" />
<activity
android:name=".app.activities.SettingsActivity"
android:exported="true"
android:label="@string/title_activity_termux_settings"
android:theme="@style/Theme.TermuxApp.DayNight.NoActionBar" />
<activity
android:name=".shared.activities.ReportActivity"
android:theme="@style/Theme.MarkdownViewActivity.DayNight"
android:documentLaunchMode="intoExisting" />
<activity
android:name=".app.api.file.FileReceiverActivity"
android:excludeFromRecents="true"
android:exported="false"
android:noHistory="true"
android:resizeableActivity="true"
android:taskAffinity="${TERMUX_PACKAGE_NAME}.filereceiver"
tools:targetApi="n">
</activity>
<activity-alias
android:name=".app.api.file.FileShareReceiverActivity"
android:exported="true"
android:targetActivity=".app.api.file.FileReceiverActivity">
<!-- Accept multiple file types when sending. -->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/*" />
<data android:mimeType="audio/*" />
<data android:mimeType="image/*" />
<data android:mimeType="message/*" />
<data android:mimeType="multipart/*" />
<data android:mimeType="text/*" />
<data android:mimeType="video/*" />
</intent-filter>
</activity-alias>
<activity-alias
android:name=".app.api.file.FileViewReceiverActivity"
android:exported="true"
android:targetActivity=".app.api.file.FileReceiverActivity">
<!-- Accept multiple file types to let Termux be usable as generic file viewer. -->
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="application/*" />
<data android:mimeType="audio/*" />
<data android:mimeType="image/*" />
<data android:mimeType="text/*" />
<data android:mimeType="video/*" />
</intent-filter>
</activity-alias>
<provider
android:name=".filepicker.TermuxDocumentsProvider"
android:authorities="${TERMUX_PACKAGE_NAME}.documents"
android:exported="true"
android:grantUriPermissions="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>
<provider
android:name=".app.TermuxOpenReceiver$ContentProvider"
android:authorities="${TERMUX_PACKAGE_NAME}.files"
android:exported="true"
android:grantUriPermissions="true"
android:permission="${TERMUX_PACKAGE_NAME}.permission.RUN_COMMAND" />
<receiver
android:name=".app.TermuxOpenReceiver"
android:exported="false" />
<receiver
android:name=".app.event.SystemEventReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver
android:name=".shared.activities.ReportActivity$ReportActivityBroadcastReceiver"
android:exported="false" />
<service
android:name=".app.TermuxService"
android:exported="false" />
<service
android:name=".app.RunCommandService"
android:exported="true"
android:permission="${TERMUX_PACKAGE_NAME}.permission.RUN_COMMAND">
<intent-filter>
<action android:name="${TERMUX_PACKAGE_NAME}.RUN_COMMAND" />
</intent-filter>
</service>
<!-- This (or rather, value 2.1 or higher) is needed to make the Samsung Galaxy S8 mark the
app with "This app is optimized to run in full screen." -->
<meta-data
android:name="android.max_aspect"
android:value="10.0" />
<!-- https://developer.samsung.com/samsung-dex/modify-optimizing.html -->
<!-- Version < 3.0. DeX Mode and Screen Mirroring support -->
<meta-data
android:name="com.samsung.android.keepalive.density"
android:value="true" />
<!-- Version >= 3.0. DeX Dual Mode support -->
<meta-data
android:name="com.samsung.android.multidisplay.keep_process_alive"
android:value="true" />
<meta-data
android:name="com.sec.android.support.multiwindow"
android:value="true" />
</application>
</manifest>
================================================
FILE: app/src/main/cpp/Android.mk
================================================
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libtermux-bootstrap
LOCAL_SRC_FILES := termux-bootstrap-zip.S termux-bootstrap.c
include $(BUILD_SHARED_LIBRARY)
================================================
FILE: app/src/main/cpp/termux-bootstrap-zip.S
================================================
.global blob
.global blob_size
.section .rodata
blob:
#if defined __i686__
.incbin "bootstrap-i686.zip"
#elif defined __x86_64__
.incbin "bootstrap-x86_64.zip"
#elif defined __aarch64__
.incbin "bootstrap-aarch64.zip"
#elif defined __arm__
.incbin "bootstrap-arm.zip"
#else
# error Unsupported arch
#endif
1:
blob_size:
.int 1b - blob
================================================
FILE: app/src/main/cpp/termux-bootstrap.c
================================================
#include <jni.h>
extern jbyte blob[];
extern int blob_size;
JNIEXPORT jbyteArray JNICALL Java_com_termux_app_TermuxInstaller_getZip(JNIEnv *env, __attribute__((__unused__)) jobject This)
{
jbyteArray ret = (*env)->NewByteArray(env, blob_size);
(*env)->SetByteArrayRegion(env, ret, 0, blob_size, blob);
return ret;
}
================================================
FILE: app/src/main/java/com/termux/app/RunCommandService.java
================================================
package com.termux.app;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import com.termux.R;
import com.termux.shared.data.DataUtils;
import com.termux.shared.data.IntentUtils;
import com.termux.shared.termux.plugins.TermuxPluginUtils;
import com.termux.shared.termux.file.TermuxFileUtils;
import com.termux.shared.file.filesystem.FileType;
import com.termux.shared.errors.Errno;
import com.termux.shared.errors.Error;
import com.termux.shared.termux.TermuxConstants;
import com.termux.shared.termux.TermuxConstants.TERMUX_APP.RUN_COMMAND_SERVICE;
import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_SERVICE;
import com.termux.shared.file.FileUtils;
import com.termux.shared.logger.Logger;
import com.termux.shared.notification.NotificationUtils;
import com.termux.shared.shell.command.ExecutionCommand;
import com.termux.shared.shell.command.ExecutionCommand.Runner;
/**
* A service that receives {@link RUN_COMMAND_SERVICE#ACTION_RUN_COMMAND} intent from third party apps and
* plugins that contains info on command execution and forwards the extras to {@link TermuxService}
* for the actual execution.
*
* Check https://github.com/termux/termux-app/wiki/RUN_COMMAND-Intent for more info.
*/
public class RunCommandService extends Service {
private static final String LOG_TAG = "RunCommandService";
class LocalBinder extends Binder {
public final RunCommandService service = RunCommandService.this;
}
private final IBinder mBinder = new RunCommandService.LocalBinder();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public void onCreate() {
Logger.logVerbose(LOG_TAG, "onCreate");
runStartForeground();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Logger.logDebug(LOG_TAG, "onStartCommand");
if (intent == null) return Service.START_NOT_STICKY;
// Run again in case service is already started and onCreate() is not called
runStartForeground();
Logger.logVerboseExtended(LOG_TAG, "Intent Received:\n" + IntentUtils.getIntentString(intent));
ExecutionCommand executionCommand = new ExecutionCommand();
executionCommand.pluginAPIHelp = this.getString(R.string.error_run_command_service_api_help, RUN_COMMAND_SERVICE.RUN_COMMAND_API_HELP_URL);
Error error;
String errmsg;
// If invalid action passed, then just return
if (!RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND.equals(intent.getAction())) {
errmsg = this.getString(R.string.error_run_command_service_invalid_intent_action, intent.getAction());
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return stopService();
}
String executableExtra = executionCommand.executable = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_COMMAND_PATH, null);
executionCommand.arguments = IntentUtils.getStringArrayExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_ARGUMENTS, null);
/*
* If intent was sent with `am` command, then normal comma characters may have been replaced
* with alternate characters if a normal comma existed in an argument itself to prevent it
* splitting into multiple arguments by `am` command.
* If `tudo` or `sudo` are used, then simply using their `-r` and `--comma-alternative` command
* options can be used without passing the below extras, but native supports is helpful if
* they are not being used.
* https://github.com/agnostic-apollo/tudo#passing-arguments-using-run_command-intent
* https://android.googlesource.com/platform/frameworks/base/+/21bdaf1/cmds/am/src/com/android/commands/am/Am.java#572
*/
boolean replaceCommaAlternativeCharsInArguments = intent.getBooleanExtra(RUN_COMMAND_SERVICE.EXTRA_REPLACE_COMMA_ALTERNATIVE_CHARS_IN_ARGUMENTS, false);
if (replaceCommaAlternativeCharsInArguments) {
String commaAlternativeCharsInArguments = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_COMMA_ALTERNATIVE_CHARS_IN_ARGUMENTS, null);
if (commaAlternativeCharsInArguments == null)
commaAlternativeCharsInArguments = TermuxConstants.COMMA_ALTERNATIVE;
// Replace any commaAlternativeCharsInArguments characters with normal commas
DataUtils.replaceSubStringsInStringArrayItems(executionCommand.arguments, commaAlternativeCharsInArguments, TermuxConstants.COMMA_NORMAL);
}
executionCommand.stdin = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_STDIN, null);
executionCommand.workingDirectory = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_WORKDIR, null);
// If EXTRA_RUNNER is passed, use that, otherwise check EXTRA_BACKGROUND and default to Runner.TERMINAL_SESSION
executionCommand.runner = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_RUNNER,
(intent.getBooleanExtra(RUN_COMMAND_SERVICE.EXTRA_BACKGROUND, false) ? Runner.APP_SHELL.getName() : Runner.TERMINAL_SESSION.getName()));
if (Runner.runnerOf(executionCommand.runner) == null) {
errmsg = this.getString(R.string.error_run_command_service_invalid_execution_command_runner, executionCommand.runner);
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return stopService();
}
executionCommand.backgroundCustomLogLevel = IntentUtils.getIntegerExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_BACKGROUND_CUSTOM_LOG_LEVEL, null);
executionCommand.sessionAction = intent.getStringExtra(RUN_COMMAND_SERVICE.EXTRA_SESSION_ACTION);
executionCommand.shellName = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_SHELL_NAME, null);
executionCommand.shellCreateMode = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_SHELL_CREATE_MODE, null);
executionCommand.commandLabel = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_COMMAND_LABEL, "RUN_COMMAND Execution Intent Command");
executionCommand.commandDescription = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_COMMAND_DESCRIPTION, null);
executionCommand.commandHelp = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_COMMAND_HELP, null);
executionCommand.isPluginExecutionCommand = true;
executionCommand.resultConfig.resultPendingIntent = intent.getParcelableExtra(RUN_COMMAND_SERVICE.EXTRA_PENDING_INTENT);
executionCommand.resultConfig.resultDirectoryPath = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_RESULT_DIRECTORY, null);
if (executionCommand.resultConfig.resultDirectoryPath != null) {
executionCommand.resultConfig.resultSingleFile = intent.getBooleanExtra(RUN_COMMAND_SERVICE.EXTRA_RESULT_SINGLE_FILE, false);
executionCommand.resultConfig.resultFileBasename = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_RESULT_FILE_BASENAME, null);
executionCommand.resultConfig.resultFileOutputFormat = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_RESULT_FILE_OUTPUT_FORMAT, null);
executionCommand.resultConfig.resultFileErrorFormat = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_RESULT_FILE_ERROR_FORMAT, null);
executionCommand.resultConfig.resultFilesSuffix = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_RESULT_FILES_SUFFIX, null);
}
// If "allow-external-apps" property to not set to "true", then just return
// We enable force notifications if "allow-external-apps" policy is violated so that the
// user knows someone tried to run a command in termux context, since it may be malicious
// app or imported (tasker) plugin project and not the user himself. If a pending intent is
// also sent, then its creator is also logged and shown.
errmsg = TermuxPluginUtils.checkIfAllowExternalAppsPolicyIsViolated(this, LOG_TAG);
if (errmsg != null) {
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, true);
return stopService();
}
// If executable is null or empty, then exit here instead of getting canonical path which would expand to "/"
if (executionCommand.executable == null || executionCommand.executable.isEmpty()) {
errmsg = this.getString(R.string.error_run_command_service_mandatory_extra_missing, RUN_COMMAND_SERVICE.EXTRA_COMMAND_PATH);
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return stopService();
}
// Get canonical path of executable
executionCommand.executable = TermuxFileUtils.getCanonicalPath(executionCommand.executable, null, true);
// If executable is not a regular file, or is not readable or executable, then just return
// Setting of missing read and execute permissions is not done
error = FileUtils.validateRegularFileExistenceAndPermissions("executable", executionCommand.executable, null,
FileUtils.APP_EXECUTABLE_FILE_PERMISSIONS, true, true,
false);
if (error != null) {
executionCommand.setStateFailed(error);
TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return stopService();
}
// If workingDirectory is not null or empty
if (executionCommand.workingDirectory != null && !executionCommand.workingDirectory.isEmpty()) {
// Get canonical path of workingDirectory
executionCommand.workingDirectory = TermuxFileUtils.getCanonicalPath(executionCommand.workingDirectory, null, true);
// If workingDirectory is not a directory, or is not readable or writable, then just return
// Creation of missing directory and setting of read, write and execute permissions are only done if workingDirectory is
// under allowed termux working directory paths.
// We try to set execute permissions, but ignore if they are missing, since only read and write permissions are required
// for working directories.
error = TermuxFileUtils.validateDirectoryFileExistenceAndPermissions("working", executionCommand.workingDirectory,
true, true, true,
false, true);
if (error != null) {
executionCommand.setStateFailed(error);
TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return stopService();
}
}
// If the executable passed as the extra was an applet for coreutils/busybox, then we must
// use it instead of the canonical path above since otherwise arguments would be passed to
// coreutils/busybox instead and command would fail. Broken symlinks would already have been
// validated so it should be fine to use it.
executableExtra = TermuxFileUtils.getExpandedTermuxPath(executableExtra);
if (FileUtils.getFileType(executableExtra, false) == FileType.SYMLINK) {
Logger.logVerbose(LOG_TAG, "The executableExtra path \"" + executableExtra + "\" is a symlink so using it instead of the canonical path \"" + executionCommand.executable + "\"");
executionCommand.executable = executableExtra;
}
executionCommand.executableUri = new Uri.Builder().scheme(TERMUX_SERVICE.URI_SCHEME_SERVICE_EXECUTE).path(executionCommand.executable).build();
Logger.logVerboseExtended(LOG_TAG, executionCommand.toString());
// Create execution intent with the action TERMUX_SERVICE#ACTION_SERVICE_EXECUTE to be sent to the TERMUX_SERVICE
Intent execIntent = new Intent(TERMUX_SERVICE.ACTION_SERVICE_EXECUTE, executionCommand.executableUri);
execIntent.setClass(this, TermuxService.class);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_ARGUMENTS, executionCommand.arguments);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_STDIN, executionCommand.stdin);
if (executionCommand.workingDirectory != null && !executionCommand.workingDirectory.isEmpty()) execIntent.putExtra(TERMUX_SERVICE.EXTRA_WORKDIR, executionCommand.workingDirectory);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_RUNNER, executionCommand.runner);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_BACKGROUND_CUSTOM_LOG_LEVEL, DataUtils.getStringFromInteger(executionCommand.backgroundCustomLogLevel, null));
execIntent.putExtra(TERMUX_SERVICE.EXTRA_SESSION_ACTION, executionCommand.sessionAction);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_SHELL_NAME, executionCommand.shellName);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_SHELL_CREATE_MODE, executionCommand.shellCreateMode);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_COMMAND_LABEL, executionCommand.commandLabel);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_COMMAND_DESCRIPTION, executionCommand.commandDescription);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_COMMAND_HELP, executionCommand.commandHelp);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_PLUGIN_API_HELP, executionCommand.pluginAPIHelp);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_PENDING_INTENT, executionCommand.resultConfig.resultPendingIntent);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_RESULT_DIRECTORY, executionCommand.resultConfig.resultDirectoryPath);
if (executionCommand.resultConfig.resultDirectoryPath != null) {
execIntent.putExtra(TERMUX_SERVICE.EXTRA_RESULT_SINGLE_FILE, executionCommand.resultConfig.resultSingleFile);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_RESULT_FILE_BASENAME, executionCommand.resultConfig.resultFileBasename);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_RESULT_FILE_OUTPUT_FORMAT, executionCommand.resultConfig.resultFileOutputFormat);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_RESULT_FILE_ERROR_FORMAT, executionCommand.resultConfig.resultFileErrorFormat);
execIntent.putExtra(TERMUX_SERVICE.EXTRA_RESULT_FILES_SUFFIX, executionCommand.resultConfig.resultFilesSuffix);
}
// Start TERMUX_SERVICE and pass it execution intent
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.startForegroundService(execIntent);
} else {
this.startService(execIntent);
}
return stopService();
}
private int stopService() {
runStopForeground();
return Service.START_NOT_STICKY;
}
private void runStartForeground() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
setupNotificationChannel();
startForeground(TermuxConstants.TERMUX_RUN_COMMAND_NOTIFICATION_ID, buildNotification());
}
}
private void runStopForeground() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
stopForeground(true);
}
}
private Notification buildNotification() {
// Build the notification
Notification.Builder builder = NotificationUtils.geNotificationBuilder(this,
TermuxConstants.TERMUX_RUN_COMMAND_NOTIFICATION_CHANNEL_ID, Notification.PRIORITY_LOW,
TermuxConstants.TERMUX_RUN_COMMAND_NOTIFICATION_CHANNEL_NAME, null, null,
null, null, NotificationUtils.NOTIFICATION_MODE_SILENT);
if (builder == null) return null;
// No need to show a timestamp:
builder.setShowWhen(false);
// Set notification icon
builder.setSmallIcon(R.drawable.ic_service_notification);
// Set background color for small notification icon
builder.setColor(0xFF607D8B);
return builder.build();
}
private void setupNotificationChannel() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return;
NotificationUtils.setupNotificationChannel(this, TermuxConstants.TERMUX_RUN_COMMAND_NOTIFICATION_CHANNEL_ID,
TermuxConstants.TERMUX_RUN_COMMAND_NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
}
}
================================================
FILE: app/src/main/java/com/termux/app/TermuxActivity.java
================================================
package com.termux.app;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.termux.R;
import com.termux.app.api.file.FileReceiverActivity;
import com.termux.app.terminal.TermuxActivityRootView;
import com.termux.app.terminal.TermuxTerminalSessionActivityClient;
import com.termux.app.terminal.io.TermuxTerminalExtraKeys;
import com.termux.shared.activities.ReportActivity;
import com.termux.shared.activity.ActivityUtils;
import com.termux.shared.activity.media.AppCompatActivityUtils;
import com.termux.shared.data.IntentUtils;
import com.termux.shared.android.PermissionUtils;
import com.termux.shared.data.DataUtils;
import com.termux.shared.termux.TermuxConstants;
import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_ACTIVITY;
import com.termux.app.activities.HelpActivity;
import com.termux.app.activities.SettingsActivity;
import com.termux.shared.termux.crash.TermuxCrashUtils;
import com.termux.shared.termux.settings.preferences.TermuxAppSharedPreferences;
import com.termux.app.terminal.TermuxSessionsListViewController;
import com.termux.app.terminal.io.TerminalToolbarViewPager;
import com.termux.app.terminal.TermuxTerminalViewClient;
import com.termux.shared.termux.extrakeys.ExtraKeysView;
import com.termux.shared.termux.interact.TextInputDialogUtils;
import com.termux.shared.logger.Logger;
import com.termux.shared.termux.TermuxUtils;
import com.termux.shared.termux.settings.properties.TermuxAppSharedProperties;
import com.termux.shared.termux.theme.TermuxThemeUtils;
import com.termux.shared.theme.NightMode;
import com.termux.shared.view.ViewUtils;
import com.termux.terminal.TerminalSession;
import com.termux.terminal.TerminalSessionClient;
import com.termux.view.TerminalView;
import com.termux.view.TerminalViewClient;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.viewpager.widget.ViewPager;
import java.util.Arrays;
/**
* A terminal emulator activity.
* <p/>
* See
* <ul>
* <li>http://www.mongrel-phones.com.au/default/how_to_make_a_local_service_and_bind_to_it_in_android</li>
* <li>https://code.google.com/p/android/issues/detail?id=6426</li>
* </ul>
* about memory leaks.
*/
public final class TermuxActivity extends AppCompatActivity implements ServiceConnection {
/**
* The connection to the {@link TermuxService}. Requested in {@link #onCreate(Bundle)} with a call to
* {@link #bindService(Intent, ServiceConnection, int)}, and obtained and stored in
* {@link #onServiceConnected(ComponentName, IBinder)}.
*/
TermuxService mTermuxService;
/**
* The {@link TerminalView} shown in {@link TermuxActivity} that displays the terminal.
*/
TerminalView mTerminalView;
/**
* The {@link TerminalViewClient} interface implementation to allow for communication between
* {@link TerminalView} and {@link TermuxActivity}.
*/
TermuxTerminalViewClient mTermuxTerminalViewClient;
/**
* The {@link TerminalSessionClient} interface implementation to allow for communication between
* {@link TerminalSession} and {@link TermuxActivity}.
*/
TermuxTerminalSessionActivityClient mTermuxTerminalSessionActivityClient;
/**
* Termux app shared preferences manager.
*/
private TermuxAppSharedPreferences mPreferences;
/**
* Termux app SharedProperties loaded from termux.properties
*/
private TermuxAppSharedProperties mProperties;
/**
* The root view of the {@link TermuxActivity}.
*/
TermuxActivityRootView mTermuxActivityRootView;
/**
* The space at the bottom of {@link @mTermuxActivityRootView} of the {@link TermuxActivity}.
*/
View mTermuxActivityBottomSpaceView;
/**
* The terminal extra keys view.
*/
ExtraKeysView mExtraKeysView;
/**
* The client for the {@link #mExtraKeysView}.
*/
TermuxTerminalExtraKeys mTermuxTerminalExtraKeys;
/**
* The termux sessions list controller.
*/
TermuxSessionsListViewController mTermuxSessionListViewController;
/**
* The {@link TermuxActivity} broadcast receiver for various things like terminal style configuration changes.
*/
private final BroadcastReceiver mTermuxActivityBroadcastReceiver = new TermuxActivityBroadcastReceiver();
/**
* The last toast shown, used cancel current toast before showing new in {@link #showToast(String, boolean)}.
*/
Toast mLastToast;
/**
* If between onResume() and onStop(). Note that only one session is in the foreground of the terminal view at the
* time, so if the session causing a change is not in the foreground it should probably be treated as background.
*/
private boolean mIsVisible;
/**
* If onResume() was called after onCreate().
*/
private boolean mIsOnResumeAfterOnCreate = false;
/**
* If activity was restarted like due to call to {@link #recreate()} after receiving
* {@link TERMUX_ACTIVITY#ACTION_RELOAD_STYLE}, system dark night mode was changed or activity
* was killed by android.
*/
private boolean mIsActivityRecreated = false;
/**
* The {@link TermuxActivity} is in an invalid state and must not be run.
*/
private boolean mIsInvalidState;
private int mNavBarHeight;
private float mTerminalToolbarDefaultHeight;
private static final int CONTEXT_MENU_SELECT_URL_ID = 0;
private static final int CONTEXT_MENU_SHARE_TRANSCRIPT_ID = 1;
private static final int CONTEXT_MENU_SHARE_SELECTED_TEXT = 10;
private static final int CONTEXT_MENU_AUTOFILL_USERNAME = 11;
private static final int CONTEXT_MENU_AUTOFILL_PASSWORD = 2;
private static final int CONTEXT_MENU_RESET_TERMINAL_ID = 3;
private static final int CONTEXT_MENU_KILL_PROCESS_ID = 4;
private static final int CONTEXT_MENU_STYLING_ID = 5;
private static final int CONTEXT_MENU_TOGGLE_KEEP_SCREEN_ON = 6;
private static final int CONTEXT_MENU_HELP_ID = 7;
private static final int CONTEXT_MENU_SETTINGS_ID = 8;
private static final int CONTEXT_MENU_REPORT_ID = 9;
private static final String ARG_TERMINAL_TOOLBAR_TEXT_INPUT = "terminal_toolbar_text_input";
private static final String ARG_ACTIVITY_RECREATED = "activity_recreated";
private static final String LOG_TAG = "TermuxActivity";
@Override
public void onCreate(Bundle savedInstanceState) {
Logger.logDebug(LOG_TAG, "onCreate");
mIsOnResumeAfterOnCreate = true;
if (savedInstanceState != null)
mIsActivityRecreated = savedInstanceState.getBoolean(ARG_ACTIVITY_RECREATED, false);
// Delete ReportInfo serialized object files from cache older than 14 days
ReportActivity.deleteReportInfoFilesOlderThanXDays(this, 14, false);
// Load Termux app SharedProperties from disk
mProperties = TermuxAppSharedProperties.getProperties();
reloadProperties();
setActivityTheme();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_termux);
// Load termux shared preferences
// This will also fail if TermuxConstants.TERMUX_PACKAGE_NAME does not equal applicationId
mPreferences = TermuxAppSharedPreferences.build(this, true);
if (mPreferences == null) {
// An AlertDialog should have shown to kill the app, so we don't continue running activity code
mIsInvalidState = true;
return;
}
setMargins();
mTermuxActivityRootView = findViewById(R.id.activity_termux_root_view);
mTermuxActivityRootView.setActivity(this);
mTermuxActivityBottomSpaceView = findViewById(R.id.activity_termux_bottom_space_view);
mTermuxActivityRootView.setOnApplyWindowInsetsListener(new TermuxActivityRootView.WindowInsetsListener());
View content = findViewById(android.R.id.content);
content.setOnApplyWindowInsetsListener((v, insets) -> {
mNavBarHeight = insets.getSystemWindowInsetBottom();
return insets;
});
if (mProperties.isUsingFullScreen()) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
setTermuxTerminalViewAndClients();
setTerminalToolbarView(savedInstanceState);
setSettingsButtonView();
setNewSessionButtonView();
setToggleKeyboardView();
registerForContextMenu(mTerminalView);
FileReceiverActivity.updateFileReceiverActivityComponentsState(this);
try {
// Start the {@link TermuxService} and make it run regardless of who is bound to it
Intent serviceIntent = new Intent(this, TermuxService.class);
startService(serviceIntent);
// Attempt to bind to the service, this will call the {@link #onServiceConnected(ComponentName, IBinder)}
// callback if it succeeds.
if (!bindService(serviceIntent, this, 0))
throw new RuntimeException("bindService() failed");
} catch (Exception e) {
Logger.logStackTraceWithMessage(LOG_TAG,"TermuxActivity failed to start TermuxService", e);
Logger.showToast(this,
getString(e.getMessage() != null && e.getMessage().contains("app is in background") ?
R.string.error_termux_service_start_failed_bg : R.string.error_termux_service_start_failed_general),
true);
mIsInvalidState = true;
return;
}
// Send the {@link TermuxConstants#BROADCAST_TERMUX_OPENED} broadcast to notify apps that Termux
// app has been opened.
TermuxUtils.sendTermuxOpenedBroadcast(this);
}
@Override
public void onStart() {
super.onStart();
Logger.logDebug(LOG_TAG, "onStart");
if (mIsInvalidState) return;
mIsVisible = true;
if (mTermuxTerminalSessionActivityClient != null)
mTermuxTerminalSessionActivityClient.onStart();
if (mTermuxTerminalViewClient != null)
mTermuxTerminalViewClient.onStart();
if (mPreferences.isTerminalMarginAdjustmentEnabled())
addTermuxActivityRootViewGlobalLayoutListener();
registerTermuxActivityBroadcastReceiver();
}
@Override
public void onResume() {
super.onResume();
Logger.logVerbose(LOG_TAG, "onResume");
if (mIsInvalidState) return;
if (mTermuxTerminalSessionActivityClient != null)
mTermuxTerminalSessionActivityClient.onResume();
if (mTermuxTerminalViewClient != null)
mTermuxTerminalViewClient.onResume();
// Check if a crash happened on last run of the app or if a plugin crashed and show a
// notification with the crash details if it did
TermuxCrashUtils.notifyAppCrashFromCrashLogFile(this, LOG_TAG);
mIsOnResumeAfterOnCreate = false;
}
@Override
protected void onStop() {
super.onStop();
Logger.logDebug(LOG_TAG, "onStop");
if (mIsInvalidState) return;
mIsVisible = false;
if (mTermuxTerminalSessionActivityClient != null)
mTermuxTerminalSessionActivityClient.onStop();
if (mTermuxTerminalViewClient != null)
mTermuxTerminalViewClient.onStop();
removeTermuxActivityRootViewGlobalLayoutListener();
unregisterTermuxActivityBroadcastReceiver();
getDrawer().closeDrawers();
}
@Override
public void onDestroy() {
super.onDestroy();
Logger.logDebug(LOG_TAG, "onDestroy");
if (mIsInvalidState) return;
if (mTermuxService != null) {
// Do not leave service and session clients with references to activity.
mTermuxService.unsetTermuxTerminalSessionClient();
mTermuxService = null;
}
try {
unbindService(this);
} catch (Exception e) {
// ignore.
}
}
@Override
public void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
Logger.logVerbose(LOG_TAG, "onSaveInstanceState");
super.onSaveInstanceState(savedInstanceState);
saveTerminalToolbarTextInput(savedInstanceState);
savedInstanceState.putBoolean(ARG_ACTIVITY_RECREATED, true);
}
/**
* Part of the {@link ServiceConnection} interface. The service is bound with
* {@link #bindService(Intent, ServiceConnection, int)} in {@link #onCreate(Bundle)} which will cause a call to this
* callback method.
*/
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
Logger.logDebug(LOG_TAG, "onServiceConnected");
mTermuxService = ((TermuxService.LocalBinder) service).service;
setTermuxSessionsListView();
final Intent intent = getIntent();
setIntent(null);
if (mTermuxService.isTermuxSessionsEmpty()) {
if (mIsVisible) {
TermuxInstaller.setupBootstrapIfNeeded(TermuxActivity.this, () -> {
if (mTermuxService == null) return; // Activity might have been destroyed.
try {
boolean launchFailsafe = false;
if (intent != null && intent.getExtras() != null) {
launchFailsafe = intent.getExtras().getBoolean(TERMUX_ACTIVITY.EXTRA_FAILSAFE_SESSION, false);
}
mTermuxTerminalSessionActivityClient.addNewSession(launchFailsafe, null);
} catch (WindowManager.BadTokenException e) {
// Activity finished - ignore.
}
});
} else {
// The service connected while not in foreground - just bail out.
finishActivityIfNotFinishing();
}
} else {
// If termux was started from launcher "New session" shortcut and activity is recreated,
// then the original intent will be re-delivered, resulting in a new session being re-added
// each time.
if (!mIsActivityRecreated && intent != null && Intent.ACTION_RUN.equals(intent.getAction())) {
// Android 7.1 app shortcut from res/xml/shortcuts.xml.
boolean isFailSafe = intent.getBooleanExtra(TERMUX_ACTIVITY.EXTRA_FAILSAFE_SESSION, false);
mTermuxTerminalSessionActivityClient.addNewSession(isFailSafe, null);
} else {
mTermuxTerminalSessionActivityClient.setCurrentSession(mTermuxTerminalSessionActivityClient.getCurrentStoredSessionOrLast());
}
}
// Update the {@link TerminalSession} and {@link TerminalEmulator} clients.
mTermuxService.setTermuxTerminalSessionClient(mTermuxTerminalSessionActivityClient);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Logger.logDebug(LOG_TAG, "onServiceDisconnected");
// Respect being stopped from the {@link TermuxService} notification action.
finishActivityIfNotFinishing();
}
private void reloadProperties() {
mProperties.loadTermuxPropertiesFromDisk();
if (mTermuxTerminalViewClient != null)
mTermuxTerminalViewClient.onReloadProperties();
}
private void setActivityTheme() {
// Update NightMode.APP_NIGHT_MODE
TermuxThemeUtils.setAppNightMode(mProperties.getNightMode());
// Set activity night mode. If NightMode.SYSTEM is set, then android will automatically
// trigger recreation of activity when uiMode/dark mode configuration is changed so that
// day or night theme takes affect.
AppCompatActivityUtils.setNightMode(this, NightMode.getAppNightMode().getName(), true);
}
private void setMargins() {
RelativeLayout relativeLayout = findViewById(R.id.activity_termux_root_relative_layout);
int marginHorizontal = mProperties.getTerminalMarginHorizontal();
int marginVertical = mProperties.getTerminalMarginVertical();
ViewUtils.setLayoutMarginsInDp(relativeLayout, marginHorizontal, marginVertical, marginHorizontal, marginVertical);
}
public void addTermuxActivityRootViewGlobalLayoutListener() {
getTermuxActivityRootView().getViewTreeObserver().addOnGlobalLayoutListener(getTermuxActivityRootView());
}
public void removeTermuxActivityRootViewGlobalLayoutListener() {
if (getTermuxActivityRootView() != null)
getTermuxActivityRootView().getViewTreeObserver().removeOnGlobalLayoutListener(getTermuxActivityRootView());
}
private void setTermuxTerminalViewAndClients() {
// Set termux terminal view and session clients
mTermuxTerminalSessionActivityClient = new TermuxTerminalSessionActivityClient(this);
mTermuxTerminalViewClient = new TermuxTerminalViewClient(this, mTermuxTerminalSessionActivityClient);
// Set termux terminal view
mTerminalView = findViewById(R.id.terminal_view);
mTerminalView.setTerminalViewClient(mTermuxTerminalViewClient);
if (mTermuxTerminalViewClient != null)
mTermuxTerminalViewClient.onCreate();
if (mTermuxTerminalSessionActivityClient != null)
mTermuxTerminalSessionActivityClient.onCreate();
}
private void setTermuxSessionsListView() {
ListView termuxSessionsListView = findViewById(R.id.terminal_sessions_list);
mTermuxSessionListViewController = new TermuxSessionsListViewController(this, mTermuxService.getTermuxSessions());
termuxSessionsListView.setAdapter(mTermuxSessionListViewController);
termuxSessionsListView.setOnItemClickListener(mTermuxSessionListViewController);
termuxSessionsListView.setOnItemLongClickListener(mTermuxSessionListViewController);
}
private void setTerminalToolbarView(Bundle savedInstanceState) {
mTermuxTerminalExtraKeys = new TermuxTerminalExtraKeys(this, mTerminalView,
mTermuxTerminalViewClient, mTermuxTerminalSessionActivityClient);
final ViewPager terminalToolbarViewPager = getTerminalToolbarViewPager();
if (mPreferences.shouldShowTerminalToolbar()) terminalToolbarViewPager.setVisibility(View.VISIBLE);
ViewGroup.LayoutParams layoutParams = terminalToolbarViewPager.getLayoutParams();
mTerminalToolbarDefaultHeight = layoutParams.height;
setTerminalToolbarHeight();
String savedTextInput = null;
if (savedInstanceState != null)
savedTextInput = savedInstanceState.getString(ARG_TERMINAL_TOOLBAR_TEXT_INPUT);
terminalToolbarViewPager.setAdapter(new TerminalToolbarViewPager.PageAdapter(this, savedTextInput));
terminalToolbarViewPager.addOnPageChangeListener(new TerminalToolbarViewPager.OnPageChangeListener(this, terminalToolbarViewPager));
}
private void setTerminalToolbarHeight() {
final ViewPager terminalToolbarViewPager = getTerminalToolbarViewPager();
if (terminalToolbarViewPager == null) return;
ViewGroup.LayoutParams layoutParams = terminalToolbarViewPager.getLayoutParams();
layoutParams.height = Math.round(mTerminalToolbarDefaultHeight *
(mTermuxTerminalExtraKeys.getExtraKeysInfo() == null ? 0 : mTermuxTerminalExtraKeys.getExtraKeysInfo().getMatrix().length) *
mProperties.getTerminalToolbarHeightScaleFactor());
terminalToolbarViewPager.setLayoutParams(layoutParams);
}
public void toggleTerminalToolbar() {
final ViewPager terminalToolbarViewPager = getTerminalToolbarViewPager();
if (terminalToolbarViewPager == null) return;
final boolean showNow = mPreferences.toogleShowTerminalToolbar();
Logger.showToast(this, (showNow ? getString(R.string.msg_enabling_terminal_toolbar) : getString(R.string.msg_disabling_terminal_toolbar)), true);
terminalToolbarViewPager.setVisibility(showNow ? View.VISIBLE : View.GONE);
if (showNow && isTerminalToolbarTextInputViewSelected()) {
// Focus the text input view if just revealed.
findViewById(R.id.terminal_toolbar_text_input).requestFocus();
}
}
private void saveTerminalToolbarTextInput(Bundle savedInstanceState) {
if (savedInstanceState == null) return;
final EditText textInputView = findViewById(R.id.terminal_toolbar_text_input);
if (textInputView != null) {
String textInput = textInputView.getText().toString();
if (!textInput.isEmpty()) savedInstanceState.putString(ARG_TERMINAL_TOOLBAR_TEXT_INPUT, textInput);
}
}
private void setSettingsButtonView() {
ImageButton settingsButton = findViewById(R.id.settings_button);
settingsButton.setOnClickListener(v -> {
ActivityUtils.startActivity(this, new Intent(this, SettingsActivity.class));
});
}
private void setNewSessionButtonView() {
View newSessionButton = findViewById(R.id.new_session_button);
newSessionButton.setOnClickListener(v -> mTermuxTerminalSessionActivityClient.addNewSession(false, null));
newSessionButton.setOnLongClickListener(v -> {
TextInputDialogUtils.textInput(TermuxActivity.this, R.string.title_create_named_session, null,
R.string.action_create_named_session_confirm, text -> mTermuxTerminalSessionActivityClient.addNewSession(false, text),
R.string.action_new_session_failsafe, text -> mTermuxTerminalSessionActivityClient.addNewSession(true, text),
-1, null, null);
return true;
});
}
private void setToggleKeyboardView() {
findViewById(R.id.toggle_keyboard_button).setOnClickListener(v -> {
mTermuxTerminalViewClient.onToggleSoftKeyboardRequest();
getDrawer().closeDrawers();
});
findViewById(R.id.toggle_keyboard_button).setOnLongClickListener(v -> {
toggleTerminalToolbar();
return true;
});
}
@SuppressLint("RtlHardcoded")
@Override
public void onBackPressed() {
if (getDrawer().isDrawerOpen(Gravity.LEFT)) {
getDrawer().closeDrawers();
} else {
finishActivityIfNotFinishing();
}
}
public void finishActivityIfNotFinishing() {
// prevent duplicate calls to finish() if called from multiple places
if (!TermuxActivity.this.isFinishing()) {
finish();
}
}
/** Show a toast and dismiss the last one if still visible. */
public void showToast(String text, boolean longDuration) {
if (text == null || text.isEmpty()) return;
if (mLastToast != null) mLastToast.cancel();
mLastToast = Toast.makeText(TermuxActivity.this, text, longDuration ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT);
mLastToast.setGravity(Gravity.TOP, 0, 0);
mLastToast.show();
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
TerminalSession currentSession = getCurrentSession();
if (currentSession == null) return;
boolean autoFillEnabled = mTerminalView.isAutoFillEnabled();
menu.add(Menu.NONE, CONTEXT_MENU_SELECT_URL_ID, Menu.NONE, R.string.action_select_url);
menu.add(Menu.NONE, CONTEXT_MENU_SHARE_TRANSCRIPT_ID, Menu.NONE, R.string.action_share_transcript);
if (!DataUtils.isNullOrEmpty(mTerminalView.getStoredSelectedText()))
menu.add(Menu.NONE, CONTEXT_MENU_SHARE_SELECTED_TEXT, Menu.NONE, R.string.action_share_selected_text);
if (autoFillEnabled)
menu.add(Menu.NONE, CONTEXT_MENU_AUTOFILL_USERNAME, Menu.NONE, R.string.action_autofill_username);
if (autoFillEnabled)
menu.add(Menu.NONE, CONTEXT_MENU_AUTOFILL_PASSWORD, Menu.NONE, R.string.action_autofill_password);
menu.add(Menu.NONE, CONTEXT_MENU_RESET_TERMINAL_ID, Menu.NONE, R.string.action_reset_terminal);
menu.add(Menu.NONE, CONTEXT_MENU_KILL_PROCESS_ID, Menu.NONE, getResources().getString(R.string.action_kill_process, getCurrentSession().getPid())).setEnabled(currentSession.isRunning());
menu.add(Menu.NONE, CONTEXT_MENU_STYLING_ID, Menu.NONE, R.string.action_style_terminal);
menu.add(Menu.NONE, CONTEXT_MENU_TOGGLE_KEEP_SCREEN_ON, Menu.NONE, R.string.action_toggle_keep_screen_on).setCheckable(true).setChecked(mPreferences.shouldKeepScreenOn());
menu.add(Menu.NONE, CONTEXT_MENU_HELP_ID, Menu.NONE, R.string.action_open_help);
menu.add(Menu.NONE, CONTEXT_MENU_SETTINGS_ID, Menu.NONE, R.string.action_open_settings);
menu.add(Menu.NONE, CONTEXT_MENU_REPORT_ID, Menu.NONE, R.string.action_report_issue);
}
/** Hook system menu to show context menu instead. */
@Override
public boolean onCreateOptionsMenu(Menu menu) {
mTerminalView.showContextMenu();
return false;
}
@Override
public boolean onContextItemSelected(MenuItem item) {
TerminalSession session = getCurrentSession();
switch (item.getItemId()) {
case CONTEXT_MENU_SELECT_URL_ID:
mTermuxTerminalViewClient.showUrlSelection();
return true;
case CONTEXT_MENU_SHARE_TRANSCRIPT_ID:
mTermuxTerminalViewClient.shareSessionTranscript();
return true;
case CONTEXT_MENU_SHARE_SELECTED_TEXT:
mTermuxTerminalViewClient.shareSelectedText();
return true;
case CONTEXT_MENU_AUTOFILL_USERNAME:
mTerminalView.requestAutoFillUsername();
return true;
case CONTEXT_MENU_AUTOFILL_PASSWORD:
mTerminalView.requestAutoFillPassword();
return true;
case CONTEXT_MENU_RESET_TERMINAL_ID:
onResetTerminalSession(session);
return true;
case CONTEXT_MENU_KILL_PROCESS_ID:
showKillSessionDialog(session);
return true;
case CONTEXT_MENU_STYLING_ID:
showStylingDialog();
return true;
case CONTEXT_MENU_TOGGLE_KEEP_SCREEN_ON:
toggleKeepScreenOn();
return true;
case CONTEXT_MENU_HELP_ID:
ActivityUtils.startActivity(this, new Intent(this, HelpActivity.class));
return true;
case CONTEXT_MENU_SETTINGS_ID:
ActivityUtils.startActivity(this, new Intent(this, SettingsActivity.class));
return true;
case CONTEXT_MENU_REPORT_ID:
mTermuxTerminalViewClient.reportIssueFromTranscript();
return true;
default:
return super.onContextItemSelected(item);
}
}
@Override
public void onContextMenuClosed(Menu menu) {
super.onContextMenuClosed(menu);
// onContextMenuClosed() is triggered twice if back button is pressed to dismiss instead of tap for some reason
mTerminalView.onContextMenuClosed(menu);
}
private void showKillSessionDialog(TerminalSession session) {
if (session == null) return;
final AlertDialog.Builder b = new AlertDialog.Builder(this);
b.setIcon(android.R.drawable.ic_dialog_alert);
b.setMessage(R.string.title_confirm_kill_process);
b.setPositiveButton(android.R.string.yes, (dialog, id) -> {
dialog.dismiss();
session.finishIfRunning();
});
b.setNegativeButton(android.R.string.no, null);
b.show();
}
private void onResetTerminalSession(TerminalSession session) {
if (session != null) {
session.reset();
showToast(getResources().getString(R.string.msg_terminal_reset), true);
if (mTermuxTerminalSessionActivityClient != null)
mTermuxTerminalSessionActivityClient.onResetTerminalSession();
}
}
private void showStylingDialog() {
Intent stylingIntent = new Intent();
stylingIntent.setClassName(TermuxConstants.TERMUX_STYLING_PACKAGE_NAME, TermuxConstants.TERMUX_STYLING_APP.TERMUX_STYLING_ACTIVITY_NAME);
try {
startActivity(stylingIntent);
} catch (ActivityNotFoundException | IllegalArgumentException e) {
// The startActivity() call is not documented to throw IllegalArgumentException.
// However, crash reporting shows that it sometimes does, so catch it here.
new AlertDialog.Builder(this).setMessage(getString(R.string.error_styling_not_installed))
.setPositiveButton(R.string.action_styling_install,
(dialog, which) -> ActivityUtils.startActivity(this, new Intent(Intent.ACTION_VIEW, Uri.parse(TermuxConstants.TERMUX_STYLING_FDROID_PACKAGE_URL))))
.setNegativeButton(android.R.string.cancel, null).show();
}
}
private void toggleKeepScreenOn() {
if (mTerminalView.getKeepScreenOn()) {
mTerminalView.setKeepScreenOn(false);
mPreferences.setKeepScreenOn(false);
} else {
mTerminalView.setKeepScreenOn(true);
mPreferences.setKeepScreenOn(true);
}
}
/**
* For processes to access primary external storage (/sdcard, /storage/emulated/0, ~/storage/shared),
* termux needs to be granted legacy WRITE_EXTERNAL_STORAGE or MANAGE_EXTERNAL_STORAGE permissions
* if targeting targetSdkVersion 30 (android 11) and running on sdk 30 (android 11) and higher.
*/
public void requestStoragePermission(boolean isPermissionCallback) {
new Thread() {
@Override
public void run() {
// Do not ask for permission again
int requestCode = isPermissionCallback ? -1 : PermissionUtils.REQUEST_GRANT_STORAGE_PERMISSION;
// If permission is granted, then also setup storage symlinks.
if(PermissionUtils.checkAndRequestLegacyOrManageExternalStoragePermission(
TermuxActivity.this, requestCode, !isPermissionCallback)) {
if (isPermissionCallback)
Logger.logInfoAndShowToast(TermuxActivity.this, LOG_TAG,
getString(com.termux.shared.R.string.msg_storage_permission_granted_on_request));
TermuxInstaller.setupStorageSymlinks(TermuxActivity.this);
} else {
if (isPermissionCallback)
Logger.logInfoAndShowToast(TermuxActivity.this, LOG_TAG,
getString(com.termux.shared.R.string.msg_storage_permission_not_granted_on_request));
}
}
}.start();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Logger.logVerbose(LOG_TAG, "onActivityResult: requestCode: " + requestCode + ", resultCode: " + resultCode + ", data: " + IntentUtils.getIntentString(data));
if (requestCode == PermissionUtils.REQUEST_GRANT_STORAGE_PERMISSION) {
requestStoragePermission(true);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
Logger.logVerbose(LOG_TAG, "onRequestPermissionsResult: requestCode: " + requestCode + ", permissions: " + Arrays.toString(permissions) + ", grantResults: " + Arrays.toString(grantResults));
if (requestCode == PermissionUtils.REQUEST_GRANT_STORAGE_PERMISSION) {
requestStoragePermission(true);
}
}
public int getNavBarHeight() {
return mNavBarHeight;
}
public TermuxActivityRootView getTermuxActivityRootView() {
return mTermuxActivityRootView;
}
public View getTermuxActivityBottomSpaceView() {
return mTermuxActivityBottomSpaceView;
}
public ExtraKeysView getExtraKeysView() {
return mExtraKeysView;
}
public TermuxTerminalExtraKeys getTermuxTerminalExtraKeys() {
return mTermuxTerminalExtraKeys;
}
public void setExtraKeysView(ExtraKeysView extraKeysView) {
mExtraKeysView = extraKeysView;
}
public DrawerLayout getDrawer() {
return (DrawerLayout) findViewById(R.id.drawer_layout);
}
public ViewPager getTerminalToolbarViewPager() {
return (ViewPager) findViewById(R.id.terminal_toolbar_view_pager);
}
public float getTerminalToolbarDefaultHeight() {
return mTerminalToolbarDefaultHeight;
}
public boolean isTerminalViewSelected() {
return getTerminalToolbarViewPager().getCurrentItem() == 0;
}
public boolean isTerminalToolbarTextInputViewSelected() {
return getTerminalToolbarViewPager().getCurrentItem() == 1;
}
public void termuxSessionListNotifyUpdated() {
mTermuxSessionListViewController.notifyDataSetChanged();
}
public boolean isVisible() {
return mIsVisible;
}
public boolean isOnResumeAfterOnCreate() {
return mIsOnResumeAfterOnCreate;
}
public boolean isActivityRecreated() {
return mIsActivityRecreated;
}
public TermuxService getTermuxService() {
return mTermuxService;
}
public TerminalView getTerminalView() {
return mTerminalView;
}
public TermuxTerminalViewClient getTermuxTerminalViewClient() {
return mTermuxTerminalViewClient;
}
public TermuxTerminalSessionActivityClient getTermuxTerminalSessionClient() {
return mTermuxTerminalSessionActivityClient;
}
@Nullable
public TerminalSession getCurrentSession() {
if (mTerminalView != null)
return mTerminalView.getCurrentSession();
else
return null;
}
public TermuxAppSharedPreferences getPreferences() {
return mPreferences;
}
public TermuxAppSharedProperties getProperties() {
return mProperties;
}
public static void updateTermuxActivityStyling(Context context, boolean recreateActivity) {
// Make sure that terminal styling is always applied.
Intent stylingIntent = new Intent(TERMUX_ACTIVITY.ACTION_RELOAD_STYLE);
stylingIntent.putExtra(TERMUX_ACTIVITY.EXTRA_RECREATE_ACTIVITY, recreateActivity);
context.sendBroadcast(stylingIntent);
}
private void registerTermuxActivityBroadcastReceiver() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TERMUX_ACTIVITY.ACTION_NOTIFY_APP_CRASH);
intentFilter.addAction(TERMUX_ACTIVITY.ACTION_RELOAD_STYLE);
intentFilter.addAction(TERMUX_ACTIVITY.ACTION_REQUEST_PERMISSIONS);
registerReceiver(mTermuxActivityBroadcastReceiver, intentFilter);
}
private void unregisterTermuxActivityBroadcastReceiver() {
unregisterReceiver(mTermuxActivityBroadcastReceiver);
}
private void fixTermuxActivityBroadcastReceiverIntent(Intent intent) {
if (intent == null) return;
String extraReloadStyle = intent.getStringExtra(TERMUX_ACTIVITY.EXTRA_RELOAD_STYLE);
if ("storage".equals(extraReloadStyle)) {
intent.removeExtra(TERMUX_ACTIVITY.EXTRA_RELOAD_STYLE);
intent.setAction(TERMUX_ACTIVITY.ACTION_REQUEST_PERMISSIONS);
}
}
class TermuxActivityBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null) return;
if (mIsVisible) {
fixTermuxActivityBroadcastReceiverIntent(intent);
switch (intent.getAction()) {
case TERMUX_ACTIVITY.ACTION_NOTIFY_APP_CRASH:
Logger.logDebug(LOG_TAG, "Received intent to notify app crash");
TermuxCrashUtils.notifyAppCrashFromCrashLogFile(context, LOG_TAG);
return;
case TERMUX_ACTIVITY.ACTION_RELOAD_STYLE:
Logger.logDebug(LOG_TAG, "Received intent to reload styling");
reloadActivityStyling(intent.getBooleanExtra(TERMUX_ACTIVITY.EXTRA_RECREATE_ACTIVITY, true));
return;
case TERMUX_ACTIVITY.ACTION_REQUEST_PERMISSIONS:
Logger.logDebug(LOG_TAG, "Received intent to request storage permissions");
requestStoragePermission(false);
return;
default:
}
}
}
}
private void reloadActivityStyling(boolean recreateActivity) {
if (mProperties != null) {
reloadProperties();
if (mExtraKeysView != null) {
mExtraKeysView.setButtonTextAllCaps(mProperties.shouldExtraKeysTextBeAllCaps());
mExtraKeysView.reload(mTermuxTerminalExtraKeys.getExtraKeysInfo(), mTerminalToolbarDefaultHeight);
}
// Update NightMode.APP_NIGHT_MODE
TermuxThemeUtils.setAppNightMode(mProperties.getNightMode());
}
setMargins();
setTerminalToolbarHeight();
FileReceiverActivity.updateFileReceiverActivityComponentsState(this);
if (mTermuxTerminalSessionActivityClient != null)
mTermuxTerminalSessionActivityClient.onReloadActivityStyling();
if (mTermuxTerminalViewClient != null)
mTermuxTerminalViewClient.onReloadActivityStyling();
// To change the activity and drawer theme, activity needs to be recreated.
// It will destroy the activity, including all stored variables and views, and onCreate()
// will be called again. Extra keys input text, terminal sessions and transcripts will be preserved.
if (recreateActivity) {
Logger.logDebug(LOG_TAG, "Recreating activity");
TermuxActivity.this.recreate();
}
}
public static void startTermuxActivity(@NonNull final Context context) {
ActivityUtils.startActivity(context, newInstance(context));
}
public static Intent newInstance(@NonNull final Context context) {
Intent intent = new Intent(context, TermuxActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return intent;
}
}
================================================
FILE: app/src/main/java/com/termux/app/TermuxApplication.java
================================================
package com.termux.app;
import android.app.Application;
import android.content.Context;
import com.termux.BuildConfig;
import com.termux.shared.errors.Error;
import com.termux.shared.logger.Logger;
import com.termux.shared.termux.TermuxBootstrap;
import com.termux.shared.termux.TermuxConstants;
import com.termux.shared.termux.crash.TermuxCrashUtils;
import com.termux.shared.termux.file.TermuxFileUtils;
import com.termux.shared.termux.settings.preferences.TermuxAppSharedPreferences;
import com.termux.shared.termux.settings.properties.TermuxAppSharedProperties;
import com.termux.shared.termux.shell.command.environment.TermuxShellEnvironment;
import com.termux.shared.termux.shell.am.TermuxAmSocketServer;
import com.termux.shared.termux.shell.TermuxShellManager;
import com.termux.shared.termux.theme.TermuxThemeUtils;
public class TermuxApplication extends Application {
private static final String LOG_TAG = "TermuxApplication";
public void onCreate() {
super.onCreate();
Context context = getApplicationContext();
// Set crash handler for the app
TermuxCrashUtils.setDefaultCrashHandler(this);
// Set log config for the app
setLogConfig(context);
Logger.logDebug("Starting Application");
// Set TermuxBootstrap.TERMUX_APP_PACKAGE_MANAGER and TermuxBootstrap.TERMUX_APP_PACKAGE_VARIANT
TermuxBootstrap.setTermuxPackageManagerAndVariant(BuildConfig.TERMUX_PACKAGE_VARIANT);
// Init app wide SharedProperties loaded from termux.properties
TermuxAppSharedProperties properties = TermuxAppSharedProperties.init(context);
// Init app wide shell manager
TermuxShellManager shellManager = TermuxShellManager.init(context);
// Set NightMode.APP_NIGHT_MODE
TermuxThemeUtils.setAppNightMode(properties.getNightMode());
// Check and create termux files directory. If failed to access it like in case of secondary
// user or external sd card installation, then don't run files directory related code
Error error = TermuxFileUtils.isTermuxFilesDirectoryAccessible(this, true, true);
boolean isTermuxFilesDirectoryAccessible = error == null;
if (isTermuxFilesDirectoryAccessible) {
Logger.logInfo(LOG_TAG, "Termux files directory is accessible");
error = TermuxFileUtils.isAppsTermuxAppDirectoryAccessible(true, true);
if (error != null) {
Logger.logErrorExtended(LOG_TAG, "Create apps/termux-app directory failed\n" + error);
return;
}
// Setup termux-am-socket server
TermuxAmSocketServer.setupTermuxAmSocketServer(context);
} else {
Logger.logErrorExtended(LOG_TAG, "Termux files directory is not accessible\n" + error);
}
// Init TermuxShellEnvironment constants and caches after everything has been setup including termux-am-socket server
TermuxShellEnvironment.init(this);
if (isTermuxFilesDirectoryAccessible) {
TermuxShellEnvironment.writeEnvironmentToFile(this);
}
}
public static void setLogConfig(Context context) {
Logger.setDefaultLogTag(TermuxConstants.TERMUX_APP_NAME);
// Load the log level from shared preferences and set it to the {@link Logger.CURRENT_LOG_LEVEL}
TermuxAppSharedPreferences preferences = TermuxAppSharedPreferences.build(context);
if (preferences == null) return;
preferences.setLogLevel(null, preferences.getLogLevel());
}
}
================================================
FILE: app/src/main/java/com/termux/app/TermuxInstaller.java
================================================
package com.termux.app;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.system.Os;
import android.util.Pair;
import android.view.WindowManager;
import com.termux.R;
import com.termux.shared.file.FileUtils;
import com.termux.shared.termux.crash.TermuxCrashUtils;
import com.termux.shared.termux.file.TermuxFileUtils;
import com.termux.shared.interact.MessageDialogUtils;
import com.termux.shared.logger.Logger;
import com.termux.shared.markdown.MarkdownUtils;
import com.termux.shared.errors.Error;
import com.termux.shared.android.PackageUtils;
import com.termux.shared.termux.TermuxConstants;
import com.termux.shared.termux.TermuxUtils;
import com.termux.shared.termux.shell.command.environment.TermuxShellEnvironment;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import static com.termux.shared.termux.TermuxConstants.TERMUX_PREFIX_DIR;
import static com.termux.shared.termux.TermuxConstants.TERMUX_PREFIX_DIR_PATH;
import static com.termux.shared.termux.TermuxConstants.TERMUX_STAGING_PREFIX_DIR;
import static com.termux.shared.termux.TermuxConstants.TERMUX_STAGING_PREFIX_DIR_PATH;
/**
* Install the Termux bootstrap packages if necessary by following the below steps:
* <p/>
* (1) If $PREFIX already exist, assume that it is correct and be done. Note that this relies on that we do not create a
* broken $PREFIX directory below.
* <p/>
* (2) A progress dialog is shown with "Installing..." message and a spinner.
* <p/>
* (3) A staging directory, $STAGING_PREFIX, is cleared if left over from broken installation below.
* <p/>
* (4) The zip file is loaded from a shared library.
* <p/>
* (5) The zip, containing entries relative to the $PREFIX, is is downloaded and extracted by a zip input stream
* continuously encountering zip file entries:
* <p/>
* (5.1) If the zip entry encountered is SYMLINKS.txt, go through it and remember all symlinks to setup.
* <p/>
* (5.2) For every other zip entry, extract it into $STAGING_PREFIX and set execute permissions if necessary.
*/
final class TermuxInstaller {
private static final String LOG_TAG = "TermuxInstaller";
/** Performs bootstrap setup if necessary. */
static void setupBootstrapIfNeeded(final Activity activity, final Runnable whenDone) {
String bootstrapErrorMessage;
Error filesDirectoryAccessibleError;
// This will also call Context.getFilesDir(), which should ensure that termux files directory
// is created if it does not already exist
filesDirectoryAccessibleError = TermuxFileUtils.isTermuxFilesDirectoryAccessible(activity, true, true);
boolean isFilesDirectoryAccessible = filesDirectoryAccessibleError == null;
// Termux can only be run as the primary user (device owner) since only that
// account has the expected file system paths. Verify that:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && !PackageUtils.isCurrentUserThePrimaryUser(activity)) {
bootstrapErrorMessage = activity.getString(R.string.bootstrap_error_not_primary_user_message,
MarkdownUtils.getMarkdownCodeForString(TERMUX_PREFIX_DIR_PATH, false));
Logger.logError(LOG_TAG, "isFilesDirectoryAccessible: " + isFilesDirectoryAccessible);
Logger.logError(LOG_TAG, bootstrapErrorMessage);
sendBootstrapCrashReportNotification(activity, bootstrapErrorMessage);
MessageDialogUtils.exitAppWithErrorMessage(activity,
activity.getString(R.string.bootstrap_error_title),
bootstrapErrorMessage);
return;
}
if (!isFilesDirectoryAccessible) {
bootstrapErrorMessage = Error.getMinimalErrorString(filesDirectoryAccessibleError);
//noinspection SdCardPath
if (PackageUtils.isAppInstalledOnExternalStorage(activity) &&
!TermuxConstants.TERMUX_FILES_DIR_PATH.equals(activity.getFilesDir().getAbsolutePath().replaceAll("^/data/user/0/", "/data/data/"))) {
bootstrapErrorMessage += "\n\n" + activity.getString(R.string.bootstrap_error_installed_on_portable_sd,
MarkdownUtils.getMarkdownCodeForString(TERMUX_PREFIX_DIR_PATH, false));
}
Logger.logError(LOG_TAG, bootstrapErrorMessage);
sendBootstrapCrashReportNotification(activity, bootstrapErrorMessage);
MessageDialogUtils.showMessage(activity,
activity.getString(R.string.bootstrap_error_title),
bootstrapErrorMessage, null);
return;
}
// If prefix directory exists, even if its a symlink to a valid directory and symlink is not broken/dangling
if (FileUtils.directoryFileExists(TERMUX_PREFIX_DIR_PATH, true)) {
if (TermuxFileUtils.isTermuxPrefixDirectoryEmpty()) {
Logger.logInfo(LOG_TAG, "The termux prefix directory \"" + TERMUX_PREFIX_DIR_PATH + "\" exists but is empty or only contains specific unimportant files.");
} else {
whenDone.run();
return;
}
} else if (FileUtils.fileExists(TERMUX_PREFIX_DIR_PATH, false)) {
Logger.logInfo(LOG_TAG, "The termux prefix directory \"" + TERMUX_PREFIX_DIR_PATH + "\" does not exist but another file exists at its destination.");
}
final ProgressDialog progress = ProgressDialog.show(activity, null, activity.getString(R.string.bootstrap_installer_body), true, false);
new Thread() {
@Override
public void run() {
try {
Logger.logInfo(LOG_TAG, "Installing " + TermuxConstants.TERMUX_APP_NAME + " bootstrap packages.");
Error error;
// Delete prefix staging directory or any file at its destination
error = FileUtils.deleteFile("termux prefix staging directory", TERMUX_STAGING_PREFIX_DIR_PATH, true);
if (error != null) {
showBootstrapErrorDialog(activity, whenDone, Error.getErrorMarkdownString(error));
return;
}
// Delete prefix directory or any file at its destination
error = FileUtils.deleteFile("termux prefix directory", TERMUX_PREFIX_DIR_PATH, true);
if (error != null) {
showBootstrapErrorDialog(activity, whenDone, Error.getErrorMarkdownString(error));
return;
}
// Create prefix staging directory if it does not already exist and set required permissions
error = TermuxFileUtils.isTermuxPrefixStagingDirectoryAccessible(true, true);
if (error != null) {
showBootstrapErrorDialog(activity, whenDone, Error.getErrorMarkdownString(error));
return;
}
// Create prefix directory if it does not already exist and set required permissions
error = TermuxFileUtils.isTermuxPrefixDirectoryAccessible(true, true);
if (error != null) {
showBootstrapErrorDialog(activity, whenDone, Error.getErrorMarkdownString(error));
return;
}
Logger.logInfo(LOG_TAG, "Extracting bootstrap zip to prefix staging directory \"" + TERMUX_STAGING_PREFIX_DIR_PATH + "\".");
final byte[] buffer = new byte[8096];
final List<Pair<String, String>> symlinks = new ArrayList<>(50);
final byte[] zipBytes = loadZipBytes();
try (ZipInputStream zipInput = new ZipInputStream(new ByteArrayInputStream(zipBytes))) {
ZipEntry zipEntry;
while ((zipEntry = zipInput.getNextEntry()) != null) {
if (zipEntry.getName().equals("SYMLINKS.txt")) {
BufferedReader symlinksReader = new BufferedReader(new InputStreamReader(zipInput));
String line;
while ((line = symlinksReader.readLine()) != null) {
String[] parts = line.split("←");
if (parts.length != 2)
throw new RuntimeException("Malformed symlink line: " + line);
String oldPath = parts[0];
String newPath = TERMUX_STAGING_PREFIX_DIR_PATH + "/" + parts[1];
symlinks.add(Pair.create(oldPath, newPath));
error = ensureDirectoryExists(new File(newPath).getParentFile());
if (error != null) {
showBootstrapErrorDialog(activity, whenDone, Error.getErrorMarkdownString(error));
return;
}
}
} else {
String zipEntryName = zipEntry.getName();
File targetFile = new File(TERMUX_STAGING_PREFIX_DIR_PATH, zipEntryName);
boolean isDirectory = zipEntry.isDirectory();
error = ensureDirectoryExists(isDirectory ? targetFile : targetFile.getParentFile());
if (error != null) {
showBootstrapErrorDialog(activity, whenDone, Error.getErrorMarkdownString(error));
return;
}
if (!isDirectory) {
try (FileOutputStream outStream = new FileOutputStream(targetFile)) {
int readBytes;
while ((readBytes = zipInput.read(buffer)) != -1)
outStream.write(buffer, 0, readBytes);
}
if (zipEntryName.startsWith("bin/") || zipEntryName.startsWith("libexec") ||
zipEntryName.startsWith("lib/apt/apt-helper") || zipEntryName.startsWith("lib/apt/methods")) {
//noinspection OctalInteger
Os.chmod(targetFile.getAbsolutePath(), 0700);
}
}
}
}
}
if (symlinks.isEmpty())
throw new RuntimeException("No SYMLINKS.txt encountered");
for (Pair<String, String> symlink : symlinks) {
Os.symlink(symlink.first, symlink.second);
}
Logger.logInfo(LOG_TAG, "Moving termux prefix staging to prefix directory.");
if (!TERMUX_STAGING_PREFIX_DIR.renameTo(TERMUX_PREFIX_DIR)) {
throw new RuntimeException("Moving termux prefix staging to prefix directory failed");
}
Logger.logInfo(LOG_TAG, "Bootstrap packages installed successfully.");
// Recreate env file since termux prefix was wiped earlier
TermuxShellEnvironment.writeEnvironmentToFile(activity);
activity.runOnUiThread(whenDone);
} catch (final Exception e) {
showBootstrapErrorDialog(activity, whenDone, Logger.getStackTracesMarkdownString(null, Logger.getStackTracesStringArray(e)));
} finally {
activity.runOnUiThread(() -> {
try {
progress.dismiss();
} catch (RuntimeException e) {
// Activity already dismissed - ignore.
}
});
}
}
}.start();
}
public static void showBootstrapErrorDialog(Activity activity, Runnable whenDone, String message) {
Logger.logErrorExtended(LOG_TAG, "Bootstrap Error:\n" + message);
// Send a notification with the exception so that the user knows why bootstrap setup failed
sendBootstrapCrashReportNotification(activity, message);
activity.runOnUiThread(() -> {
try {
new AlertDialog.Builder(activity).setTitle(R.string.bootstrap_error_title).setMessage(R.string.bootstrap_error_body)
.setNegativeButton(R.string.bootstrap_error_abort, (dialog, which) -> {
dialog.dismiss();
activity.finish();
})
.setPositiveButton(R.string.bootstrap_error_try_again, (dialog, which) -> {
dialog.dismiss();
FileUtils.deleteFile("termux prefix directory", TERMUX_PREFIX_DIR_PATH, true);
TermuxInstaller.setupBootstrapIfNeeded(activity, whenDone);
}).show();
} catch (WindowManager.BadTokenException e1) {
// Activity already dismissed - ignore.
}
});
}
private static void sendBootstrapCrashReportNotification(Activity activity, String message) {
final String title = TermuxConstants.TERMUX_APP_NAME + " Bootstrap Error";
// Add info of all install Termux plugin apps as well since their target sdk or installation
// on external/portable sd card can affect Termux app files directory access or exec.
TermuxCrashUtils.sendCrashReportNotification(activity, LOG_TAG,
title, null, "## " + title + "\n\n" + message + "\n\n" +
TermuxUtils.getTermuxDebugMarkdownString(activity),
true, false, TermuxUtils.AppInfoMode.TERMUX_AND_PLUGIN_PACKAGES, true);
}
static void setupStorageSymlinks(final Context context) {
final String LOG_TAG = "termux-storage";
final String title = TermuxConstants.TERMUX_APP_NAME + " Setup Storage Error";
Logger.logInfo(LOG_TAG, "Setting up storage symlinks.");
new Thread() {
public void run() {
try {
Error error;
File storageDir = TermuxConstants.TERMUX_STORAGE_HOME_DIR;
error = FileUtils.clearDirectory("~/storage", storageDir.getAbsolutePath());
if (error != null) {
Logger.logErrorAndShowToast(context, LOG_TAG, error.getMessage());
Logger.logErrorExtended(LOG_TAG, "Setup Storage Error\n" + error.toString());
TermuxCrashUtils.sendCrashReportNotification(context, LOG_TAG, title, null,
"## " + title + "\n\n" + Error.getErrorMarkdownString(error),
true, false, TermuxUtils.AppInfoMode.TERMUX_PACKAGE, true);
return;
}
Logger.logInfo(LOG_TAG, "Setting up storage symlinks at ~/storage/shared, ~/storage/downloads, ~/storage/dcim, ~/storage/pictures, ~/storage/music and ~/storage/movies for directories in \"" + Environment.getExternalStorageDirectory().getAbsolutePath() + "\".");
// Get primary storage root "/storage/emulated/0" symlink
File sharedDir = Environment.getExternalStorageDirectory();
Os.symlink(sharedDir.getAbsolutePath(), new File(storageDir, "shared").getAbsolutePath());
File documentsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
Os.symlink(documentsDir.getAbsolutePath(), new File(storageDir, "documents").getAbsolutePath());
File downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
Os.symlink(downloadsDir.getAbsolutePath(), new File(storageDir, "downloads").getAbsolutePath());
File dcimDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
Os.symlink(dcimDir.getAbsolutePath(), new File(storageDir, "dcim").getAbsolutePath());
File picturesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
Os.symlink(picturesDir.getAbsolutePath(), new File(storageDir, "pictures").getAbsolutePath());
File musicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
Os.symlink(musicDir.getAbsolutePath(), new File(storageDir, "music").getAbsolutePath());
File moviesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
Os.symlink(moviesDir.getAbsolutePath(), new File(storageDir, "movies").getAbsolutePath());
File podcastsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PODCASTS);
Os.symlink(podcastsDir.getAbsolutePath(), new File(storageDir, "podcasts").getAbsolutePath());
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
File audiobooksDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_AUDIOBOOKS);
Os.symlink(audiobooksDir.getAbsolutePath(), new File(storageDir, "audiobooks").getAbsolutePath());
}
// Dir 0 should ideally be for primary storage
// https://cs.android.com/android/platform/superproject/+/android-12.0.0_r32:frameworks/base/core/java/android/app/ContextImpl.java;l=818
// https://cs.android.com/android/platform/superproject/+/android-12.0.0_r32:frameworks/base/core/java/android/os/Environment.java;l=219
// https://cs.android.com/android/platform/superproject/+/android-12.0.0_r32:frameworks/base/core/java/android/os/Environment.java;l=181
// https://cs.android.com/android/platform/superproject/+/android-12.0.0_r32:frameworks/base/services/core/java/com/android/server/StorageManagerService.java;l=3796
// https://cs.android.com/android/platform/superproject/+/android-7.0.0_r36:frameworks/base/services/core/java/com/android/server/MountService.java;l=3053
// Create "Android/data/com.termux" symlinks
File[] dirs = context.getExternalFilesDirs(null);
if (dirs != null && dirs.length > 0) {
for (int i = 0; i < dirs.length; i++) {
File dir = dirs[i];
if (dir == null) continue;
String symlinkName = "external-" + i;
Logger.logInfo(LOG_TAG, "Setting up storage symlinks at ~/storage/" + symlinkName + " for \"" + dir.getAbsolutePath() + "\".");
Os.symlink(dir.getAbsolutePath(), new File(storageDir, symlinkName).getAbsolutePath());
}
}
// Create "Android/media/com.termux" symlinks
dirs = context.getExternalMediaDirs();
if (dirs != null && dirs.length > 0) {
for (int i = 0; i < dirs.length; i++) {
File dir = dirs[i];
if (dir == null) continue;
String symlinkName = "media-" + i;
Logger.logInfo(LOG_TAG, "Setting up storage symlinks at ~/storage/" + symlinkName + " for \"" + dir.getAbsolutePath() + "\".");
Os.symlink(dir.getAbsolutePath(), new File(storageDir, symlinkName).getAbsolutePath());
}
}
Logger.logInfo(LOG_TAG, "Storage symlinks created successfully.");
} catch (Exception e) {
Logger.logErrorAndShowToast(context, LOG_TAG, e.getMessage());
Logger.logStackTraceWithMessage(LOG_TAG, "Setup Storage Error: Error setting up link", e);
TermuxCrashUtils.sendCrashReportNotification(context, LOG_TAG, title, null,
"## " + title + "\n\n" + Logger.getStackTracesMarkdownString(null, Logger.getStackTracesStringArray(e)),
true, false, TermuxUtils.AppInfoMode.TERMUX_PACKAGE, true);
}
}
}.start();
}
private static Error ensureDirectoryExists(File directory) {
return FileUtils.createDirectoryFile(directory.getAbsolutePath());
}
public static byte[] loadZipBytes() {
// Only load the shared library when necessary to save memory usage.
System.loadLibrary("termux-bootstrap");
return getZip();
}
public static native byte[] getZip();
}
================================================
FILE: app/src/main/java/com/termux/app/TermuxOpenReceiver.java
================================================
package com.termux.app;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.provider.MediaStore;
import android.webkit.MimeTypeMap;
import com.termux.shared.termux.plugins.TermuxPluginUtils;
import com.termux.shared.data.DataUtils;
import com.termux.shared.data.IntentUtils;
import com.termux.shared.net.uri.UriUtils;
import com.termux.shared.logger.Logger;
import com.termux.shared.net.uri.UriScheme;
import com.termux.shared.termux.TermuxConstants;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import androidx.annotation.NonNull;
public class TermuxOpenReceiver extends BroadcastReceiver {
private static final String LOG_TAG = "TermuxOpenReceiver";
@Override
public void onReceive(Context context, Intent intent) {
final Uri data = intent.getData();
if (data == null) {
Logger.logError(LOG_TAG, "Called without intent data");
return;
}
Logger.logVerbose(LOG_TAG, "Intent Received:\n" + IntentUtils.getIntentString(intent));
Logger.logVerbose(LOG_TAG, "uri: \"" + data + "\", path: \"" + data.getPath() + "\", fragment: \"" + data.getFragment() + "\"");
final String contentTypeExtra = intent.getStringExtra("content-type");
final boolean useChooser = intent.getBooleanExtra("chooser", false);
final String intentAction = intent.getAction() == null ? Intent.ACTION_VIEW : intent.getAction();
switch (intentAction) {
case Intent.ACTION_SEND:
case Intent.ACTION_VIEW:
// Ok.
break;
default:
Logger.logError(LOG_TAG, "Invalid action '" + intentAction + "', using 'view'");
break;
}
String scheme = data.getScheme();
if (scheme != null && !UriScheme.SCHEME_FILE.equals(scheme)) {
Intent urlIntent = new Intent(intentAction, data);
if (intentAction.equals(Intent.ACTION_SEND)) {
urlIntent.putExtra(Intent.EXTRA_TEXT, data.toString());
urlIntent.setData(null);
} else if (contentTypeExtra != null) {
urlIntent.setDataAndType(data, contentTypeExtra);
}
urlIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
context.startActivity(urlIntent);
} catch (ActivityNotFoundException e) {
Logger.logError(LOG_TAG, "No app handles the url " + data);
}
return;
}
// Get full path including fragment (anything after last "#")
String filePath = UriUtils.getUriFilePathWithFragment(data);
if (DataUtils.isNullOrEmpty(filePath)) {
Logger.logError(LOG_TAG, "filePath is null or empty");
return;
}
final File fileToShare = new File(filePath);
if (!(fileToShare.isFile() && fileToShare.canRead())) {
Logger.logError(LOG_TAG, "Not a readable file: '" + fileToShare.getAbsolutePath() + "'");
return;
}
Intent sendIntent = new Intent();
sendIntent.setAction(intentAction);
sendIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
String contentTypeToUse;
if (contentTypeExtra == null) {
String fileName = fileToShare.getName();
int lastDotIndex = fileName.lastIndexOf('.');
String fileExtension = fileName.substring(lastDotIndex + 1);
MimeTypeMap mimeTypes = MimeTypeMap.getSingleton();
// Lower casing makes it work with e.g. "JPG":
contentTypeToUse = mimeTypes.getMimeTypeFromExtension(fileExtension.toLowerCase());
if (contentTypeToUse == null) contentTypeToUse = "application/octet-stream";
} else {
contentTypeToUse = contentTypeExtra;
}
// Do not create Uri with Uri.parse() and use Uri.Builder().path(), check UriUtils.getUriFilePath().
Uri uriToShare = UriUtils.getContentUri(TermuxConstants.TERMUX_FILE_SHARE_URI_AUTHORITY, fileToShare.getAbsolutePath());
if (Intent.ACTION_SEND.equals(intentAction)) {
sendIntent.putExtra(Intent.EXTRA_STREAM, uriToShare);
sendIntent.setType(contentTypeToUse);
} else {
sendIntent.setDataAndType(uriToShare, contentTypeToUse);
}
if (useChooser) {
sendIntent = Intent.createChooser(sendIntent, null).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
try {
context.startActivity(sendIntent);
} catch (ActivityNotFoundException e) {
Logger.logError(LOG_TAG, "No app handles the url " + data);
}
}
public static class ContentProvider extends android.content.ContentProvider {
private static final String LOG_TAG = "TermuxContentProvider";
@Override
public boolean onCreate() {
return true;
}
@Override
public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
File file = new File(uri.getPath());
if (projection == null) {
projection = new String[]{
MediaStore.MediaColumns.DISPLAY_NAME,
MediaStore.MediaColumns.SIZE,
MediaStore.MediaColumns._ID
};
}
Object[] row = new Object[projection.length];
for (int i = 0; i < projection.length; i++) {
String column = projection[i];
Object value;
switch (column) {
case MediaStore.MediaColumns.DISPLAY_NAME:
value = file.getName();
break;
case MediaStore.MediaColumns.SIZE:
value = (int) file.length();
break;
case MediaStore.MediaColumns._ID:
value = 1;
break;
default:
value = null;
}
row[i] = value;
}
MatrixCursor cursor = new MatrixCursor(projection);
cursor.addRow(row);
return cursor;
}
@Override
public String getType(@NonNull Uri uri) {
String path = uri.getLastPathSegment();
int extIndex = path.lastIndexOf('.') + 1;
if (extIndex > 0) {
MimeTypeMap mimeMap = MimeTypeMap.getSingleton();
String ext = path.substring(extIndex).toLowerCase();
return mimeMap.getMimeTypeFromExtension(ext);
}
return null;
}
@Override
public Uri insert(@NonNull Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
@Override
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
File file = new File(uri.getPath());
try {
String path = file.getCanonicalPath();
String callingPackageName = getCallingPackage();
Logger.logDebug(LOG_TAG, "Open file request received from " + callingPackageName + " for \"" + path + "\" with mode \"" + mode + "\"");
String storagePath = Environment.getExternalStorageDirectory().getCanonicalPath();
// See https://support.google.com/faqs/answer/7496913:
if (!(path.startsWith(TermuxConstants.TERMUX_FILES_DIR_PATH) || path.startsWith(storagePath))) {
throw new IllegalArgumentException("Invalid path: " + path);
}
// If TermuxConstants.PROP_ALLOW_EXTERNAL_APPS property to not set to "true", then throw exception
String errmsg = TermuxPluginUtils.checkIfAllowExternalAppsPolicyIsViolated(getContext(), LOG_TAG);
if (errmsg != null) {
throw new IllegalArgumentException(errmsg);
}
// **DO NOT** allow these files to be modified by ContentProvider exposed to external
// apps, since they may silently modify the values for security properties like
// TermuxConstants.PROP_ALLOW_EXTERNAL_APPS set by users without their explicit consent.
if (TermuxConstants.TERMUX_PROPERTIES_FILE_PATHS_LIST.contains(path) ||
TermuxConstants.TERMUX_FLOAT_PROPERTIES_FILE_PATHS_LIST.contains(path)) {
mode = "r";
}
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.parseMode(mode));
}
}
}
================================================
FILE: app/src/main/java/com/termux/app/TermuxService.java
================================================
package com.termux.app;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.termux.R;
import com.termux.app.event.SystemEventReceiver;
import com.termux.app.terminal.TermuxTerminalSessionActivityClient;
import com.termux.app.terminal.TermuxTerminalSessionServiceClient;
import com.termux.shared.termux.plugins.TermuxPluginUtils;
import com.termux.shared.data.IntentUtils;
import com.termux.shared.net.uri.UriUtils;
import com.termux.shared.errors.Errno;
import com.termux.shared.shell.ShellUtils;
import com.termux.shared.shell.command.runner.app.AppShell;
import com.termux.shared.termux.settings.properties.TermuxAppSharedProperties;
import com.termux.shared.termux.shell.command.environment.TermuxShellEnvironment;
import com.termux.shared.termux.shell.TermuxShellUtils;
import com.termux.shared.termux.TermuxConstants;
import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_ACTIVITY;
import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_SERVICE;
import com.termux.shared.termux.settings.preferences.TermuxAppSharedPreferences;
import com.termux.shared.termux.shell.TermuxShellManager;
import com.termux.shared.termux.shell.command.runner.terminal.TermuxSession;
import com.termux.shared.termux.terminal.TermuxTerminalSessionClientBase;
import com.termux.shared.logger.Logger;
import com.termux.shared.notification.NotificationUtils;
import com.termux.shared.android.PermissionUtils;
import com.termux.shared.data.DataUtils;
import com.termux.shared.shell.command.ExecutionCommand;
import com.termux.shared.shell.command.ExecutionCommand.Runner;
import com.termux.shared.shell.command.ExecutionCommand.ShellCreateMode;
import com.termux.terminal.TerminalEmulator;
import com.termux.terminal.TerminalSession;
import com.termux.terminal.TerminalSessionClient;
import java.util.ArrayList;
import java.util.List;
/**
* A service holding a list of {@link TermuxSession} in {@link TermuxShellManager#mTermuxSessions} and background {@link AppShell}
* in {@link TermuxShellManager#mTermuxTasks}, showing a foreground notification while running so that it is not terminated.
* The user interacts with the session through {@link TermuxActivity}, but this service may outlive
* the activity when the user or the system disposes of the activity. In that case the user may
* restart {@link TermuxActivity} later to yet again access the sessions.
* <p/>
* In order to keep both terminal sessions and spawned processes (who may outlive the terminal sessions) alive as long
* as wanted by the user this service is a foreground service, {@link Service#startForeground(int, Notification)}.
* <p/>
* Optionally may hold a wake and a wifi lock, in which case that is shown in the notification - see
* {@link #buildNotification()}.
*/
public final class TermuxService extends Service implements AppShell.AppShellClient, TermuxSession.TermuxSessionClient {
/** This service is only bound from inside the same process and never uses IPC. */
class LocalBinder extends Binder {
public final TermuxService service = TermuxService.this;
}
private final IBinder mBinder = new LocalBinder();
private final Handler mHandler = new Handler();
/** The full implementation of the {@link TerminalSessionClient} interface to be used by {@link TerminalSession}
* that holds activity references for activity related functions.
* Note that the service may often outlive the activity, so need to clear this reference.
*/
private TermuxTerminalSessionActivityClient mTermuxTerminalSessionActivityClient;
/** The basic implementation of the {@link TerminalSessionClient} interface to be used by {@link TerminalSession}
* that does not hold activity references and only a service reference.
*/
private final TermuxTerminalSessionServiceClient mTermuxTerminalSessionServiceClient = new TermuxTerminalSessionServiceClient(this);
/**
* Termux app shared properties manager, loaded from termux.properties
*/
private TermuxAppSharedProperties mProperties;
/**
* Termux app shell manager
*/
private TermuxShellManager mShellManager;
/** The wake lock and wifi lock are always acquired and released together. */
private PowerManager.WakeLock mWakeLock;
private WifiManager.WifiLock mWifiLock;
/** If the user has executed the {@link TERMUX_SERVICE#ACTION_STOP_SERVICE} intent. */
boolean mWantsToStop = false;
private static final String LOG_TAG = "TermuxService";
@Override
public void onCreate() {
Logger.logVerbose(LOG_TAG, "onCreate");
// Get Termux app SharedProperties without loading from disk since TermuxApplication handles
// load and TermuxActivity handles reloads
mProperties = TermuxAppSharedProperties.getProperties();
mShellManager = TermuxShellManager.getShellManager();
runStartForeground();
SystemEventReceiver.registerPackageUpdateEvents(this);
}
@SuppressLint("Wakelock")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Logger.logDebug(LOG_TAG, "onStartCommand");
// Run again in case service is already started and onCreate() is not called
runStartForeground();
String action = null;
if (intent != null) {
Logger.logVerboseExtended(LOG_TAG, "Intent Received:\n" + IntentUtils.getIntentString(intent));
action = intent.getAction();
}
if (action != null) {
switch (action) {
case TERMUX_SERVICE.ACTION_STOP_SERVICE:
Logger.logDebug(LOG_TAG, "ACTION_STOP_SERVICE intent received");
actionStopService();
break;
case TERMUX_SERVICE.ACTION_WAKE_LOCK:
Logger.logDebug(LOG_TAG, "ACTION_WAKE_LOCK intent received");
actionAcquireWakeLock();
break;
case TERMUX_SERVICE.ACTION_WAKE_UNLOCK:
Logger.logDebug(LOG_TAG, "ACTION_WAKE_UNLOCK intent received");
actionReleaseWakeLock(true);
break;
case TERMUX_SERVICE.ACTION_SERVICE_EXECUTE:
Logger.logDebug(LOG_TAG, "ACTION_SERVICE_EXECUTE intent received");
actionServiceExecute(intent);
break;
default:
Logger.logError(LOG_TAG, "Invalid action: \"" + action + "\"");
break;
}
}
// If this service really do get killed, there is no point restarting it automatically - let the user do on next
// start of {@link Term):
return Service.START_NOT_STICKY;
}
@Override
public void onDestroy() {
Logger.logVerbose(LOG_TAG, "onDestroy");
TermuxShellUtils.clearTermuxTMPDIR(true);
actionReleaseWakeLock(false);
if (!mWantsToStop)
killAllTermuxExecutionCommands();
TermuxShellManager.onAppExit(this);
SystemEventReceiver.unregisterPackageUpdateEvents(this);
runStopForeground();
}
@Override
public IBinder onBind(Intent intent) {
Logger.logVerbose(LOG_TAG, "onBind");
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Logger.logVerbose(LOG_TAG, "onUnbind");
// Since we cannot rely on {@link TermuxActivity.onDestroy()} to always complete,
// we unset clients here as well if it failed, so that we do not leave service and session
// clients with references to the activity.
if (mTermuxTerminalSessionActivityClient != null)
unsetTermuxTerminalSessionClient();
return false;
}
/** Make service run in foreground mode. */
private void runStartForeground() {
setupNotificationChannel();
startForeground(TermuxConstants.TERMUX_APP_NOTIFICATION_ID, buildNotification());
}
/** Make service leave foreground mode. */
private void runStopForeground() {
stopForeground(true);
}
/** Request to stop service. */
private void requestStopService() {
Logger.logDebug(LOG_TAG, "Requesting to stop service");
runStopForeground();
stopSelf();
}
/** Process action to stop service. */
private void actionStopService() {
mWantsToStop = true;
killAllTermuxExecutionCommands();
requestStopService();
}
/** Kill all TermuxSessions and TermuxTasks by sending SIGKILL to their processes.
*
* For TermuxSessions, all sessions will be killed, whether user manually exited Termux or if
* onDestroy() was directly called because of unintended shutdown. The processing of results
* will only be done if user manually exited termux or if the session was started by a plugin
* which **expects** the result back via a pending intent.
*
* For TermuxTasks, only tasks that were started by a plugin which **expects** the result
* back via a pending intent will be killed, whether user manually exited Termux or if
* onDestroy() was directly called because of unintended shutdown. The processing of results
* will always be done for the tasks that are killed. The remaining processes will keep on
* running until the termux app process is killed by android, like by OOM, so we let them run
* as long as they can.
*
* Some plugin execution commands may not have been processed and added to mTermuxSessions and
* mTermuxTasks lists before the service is killed, so we maintain a separate
* mPendingPluginExecutionCommands list for those, so that we can notify the pending intent
* creators that execution was cancelled.
*
* Note that if user didn't manually exit Termux and if onDestroy() was directly called because
* of unintended shutdown, like android deciding to kill the service, then there will be no
* guarantee that onDestroy() will be allowed to finish and termux app process may be killed before
* it has finished. This means that in those cases some results may not be sent back to their
* creators for plugin commands but we still try to process whatever results can be processed
* despite the unreliable behaviour of onDestroy().
*
* Note that if don't kill the processes started by plugins which **expect** the result back
* and notify their creators that they have been killed, then they may get stuck waiting for
* the results forever like in case of commands started by Termux:Tasker or RUN_COMMAND intent,
* since once TermuxService has been killed, no result will be sent back. They may still get
* stuck if termux app process gets killed, so for this case reasonable timeout values should
* be used, like in Tasker for the Termux:Tasker actions.
*
* We make copies of each list since items are removed inside the loop.
*/
private synchronized void killAllTermuxExecutionCommands() {
boolean processResult;
Logger.logDebug(LOG_TAG, "Killing TermuxSessions=" + mShellManager.mTermuxSessions.size() +
", TermuxTasks=" + mShellManager.mTermuxTasks.size() +
", PendingPluginExecutionCommands=" + mShellManager.mPendingPluginExecutionCommands.size());
List<TermuxSession> termuxSessions = new ArrayList<>(mShellManager.mTermuxSessions);
List<AppShell> termuxTasks = new ArrayList<>(mShellManager.mTermuxTasks);
List<ExecutionCommand> pendingPluginExecutionCommands = new ArrayList<>(mShellManager.mPendingPluginExecutionCommands);
for (int i = 0; i < termuxSessions.size(); i++) {
ExecutionCommand executionCommand = termuxSessions.get(i).getExecutionCommand();
processResult = mWantsToStop || executionCommand.isPluginExecutionCommandWithPendingResult();
termuxSessions.get(i).killIfExecuting(this, processResult);
if (!processResult)
mShellManager.mTermuxSessions.remove(termuxSessions.get(i));
}
for (int i = 0; i < termuxTasks.size(); i++) {
ExecutionCommand executionCommand = termuxTasks.get(i).getExecutionCommand();
if (executionCommand.isPluginExecutionCommandWithPendingResult())
termuxTasks.get(i).killIfExecuting(this, true);
else
mShellManager.mTermuxTasks.remove(termuxTasks.get(i));
}
for (int i = 0; i < pendingPluginExecutionCommands.size(); i++) {
ExecutionCommand executionCommand = pendingPluginExecutionCommands.get(i);
if (!executionCommand.shouldNotProcessResults() && executionCommand.isPluginExecutionCommandWithPendingResult()) {
if (executionCommand.setStateFailed(Errno.ERRNO_CANCELLED.getCode(), this.getString(com.termux.shared.R.string.error_execution_cancelled))) {
TermuxPluginUtils.processPluginExecutionCommandResult(this, LOG_TAG, executionCommand);
}
}
}
}
/** Process action to acquire Power and Wi-Fi WakeLocks. */
@SuppressLint({"WakelockTimeout", "BatteryLife"})
private void actionAcquireWakeLock() {
if (mWakeLock != null) {
Logger.logDebug(LOG_TAG, "Ignoring acquiring WakeLocks since they are already held");
return;
}
Logger.logDebug(LOG_TAG, "Acquiring WakeLocks");
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TermuxConstants.TERMUX_APP_NAME.toLowerCase() + ":service-wakelock");
mWakeLock.acquire();
// http://tools.android.com/tech-docs/lint-in-studio-2-3#TOC-WifiManager-Leak
WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
mWifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, TermuxConstants.TERMUX_APP_NAME.toLowerCase());
mWifiLock.acquire();
if (!PermissionUtils.checkIfBatteryOptimizationsDisabled(this)) {
PermissionUtils.requestDisableBatteryOptimizations(this);
}
updateNotification();
Logger.logDebug(LOG_TAG, "WakeLocks acquired successfully");
}
/** Process action to release Power and Wi-Fi WakeLocks. */
private void actionReleaseWakeLock(boolean updateNotification) {
if (mWakeLock == null && mWifiLock == null) {
Logger.logDebug(LOG_TAG, "Ignoring releasing WakeLocks since none are already held");
return;
}
Logger.logDebug(LOG_TAG, "Releasing WakeLocks");
if (mWakeLock != null) {
mWakeLock.release();
mWakeLock = null;
}
if (mWifiLock != null) {
mWifiLock.release();
mWifiLock = null;
}
if (updateNotification)
updateNotification();
Logger.logDebug(LOG_TAG, "WakeLocks released successfully");
}
/** Process {@link TERMUX_SERVICE#ACTION_SERVICE_EXECUTE} intent to execute a shell command in
* a foreground TermuxSession or in a background TermuxTask. */
private void actionServiceExecute(Intent intent) {
if (intent == null) {
Logger.logError(LOG_TAG, "Ignoring null intent to actionServiceExecute");
return;
}
ExecutionCommand executionCommand = new ExecutionCommand(TermuxShellManager.getNextShellId());
executionCommand.executableUri = intent.getData();
executionCommand.isPluginExecutionCommand = true;
// If EXTRA_RUNNER is passed, use that, otherwise check EXTRA_BACKGROUND and default to Runner.TERMINAL_SESSION
executionCommand.runner = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_RUNNER,
(intent.getBooleanExtra(TERMUX_SERVICE.EXTRA_BACKGROUND, false) ? Runner.APP_SHELL.getName() : Runner.TERMINAL_SESSION.getName()));
if (Runner.runnerOf(executionCommand.runner) == null) {
String errmsg = this.getString(R.string.error_termux_service_invalid_execution_command_runner, executionCommand.runner);
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return;
}
if (executionCommand.executableUri != null) {
Logger.logVerbose(LOG_TAG, "uri: \"" + executionCommand.executableUri + "\", path: \"" + executionCommand.executableUri.getPath() + "\", fragment: \"" + executionCommand.executableUri.getFragment() + "\"");
// Get full path including fragment (anything after last "#")
executionCommand.executable = UriUtils.getUriFilePathWithFragment(executionCommand.executableUri);
executionCommand.arguments = IntentUtils.getStringArrayExtraIfSet(intent, TERMUX_SERVICE.EXTRA_ARGUMENTS, null);
if (Runner.APP_SHELL.equalsRunner(executionCommand.runner))
executionCommand.stdin = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_STDIN, null);
executionCommand.backgroundCustomLogLevel = IntentUtils.getIntegerExtraIfSet(intent, TERMUX_SERVICE.EXTRA_BACKGROUND_CUSTOM_LOG_LEVEL, null);
}
executionCommand.workingDirectory = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_WORKDIR, null);
executionCommand.isFailsafe = intent.getBooleanExtra(TERMUX_ACTIVITY.EXTRA_FAILSAFE_SESSION, false);
executionCommand.sessionAction = intent.getStringExtra(TERMUX_SERVICE.EXTRA_SESSION_ACTION);
executionCommand.shellName = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_SHELL_NAME, null);
executionCommand.shellCreateMode = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_SHELL_CREATE_MODE, null);
executionCommand.commandLabel = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_COMMAND_LABEL, "Execution Intent Command");
executionCommand.commandDescription = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_COMMAND_DESCRIPTION, null);
executionCommand.commandHelp = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_COMMAND_HELP, null);
executionCommand.pluginAPIHelp = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_PLUGIN_API_HELP, null);
executionCommand.resultConfig.resultPendingIntent = intent.getParcelableExtra(TERMUX_SERVICE.EXTRA_PENDING_INTENT);
executionCommand.resultConfig.resultDirectoryPath = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_RESULT_DIRECTORY, null);
if (executionCommand.resultConfig.resultDirectoryPath != null) {
executionCommand.resultConfig.resultSingleFile = intent.getBooleanExtra(TERMUX_SERVICE.EXTRA_RESULT_SINGLE_FILE, false);
executionCommand.resultConfig.resultFileBasename = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_RESULT_FILE_BASENAME, null);
executionCommand.resultConfig.resultFileOutputFormat = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_RESULT_FILE_OUTPUT_FORMAT, null);
executionCommand.resultConfig.resultFileErrorFormat = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_RESULT_FILE_ERROR_FORMAT, null);
executionCommand.resultConfig.resultFilesSuffix = IntentUtils.getStringExtraIfSet(intent, TERMUX_SERVICE.EXTRA_RESULT_FILES_SUFFIX, null);
}
if (executionCommand.shellCreateMode == null)
executionCommand.shellCreateMode = ShellCreateMode.ALWAYS.getMode();
// Add the execution command to pending plugin execution commands list
mShellManager.mPendingPluginExecutionCommands.add(executionCommand);
if (Runner.APP_SHELL.equalsRunner(executionCommand.runner))
executeTermuxTaskCommand(executionCommand);
else if (Runner.TERMINAL_SESSION.equalsRunner(executionCommand.runner))
executeTermuxSessionCommand(executionCommand);
else {
String errmsg = getString(R.string.error_termux_service_unsupported_execution_command_runner, executionCommand.runner);
executionCommand.setStateFailed(Errno.ERRNO_FAILED.getCode(), errmsg);
TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
}
}
/** Execute a shell command in background TermuxTask. */
private void executeTermuxTaskCommand(ExecutionCommand executionCommand) {
if (executionCommand == null) return;
Logger.logDebug(LOG_TAG, "Executing background \"" + executionCommand.getCommandIdAndLabelLogString() + "\" TermuxTask command");
// Transform executable path to shell/session name, e.g. "/bin/do-something.sh" => "do-something.sh".
if (executionCommand.shellName == null && executionCommand.executable != null)
executionCommand.shellName = ShellUtils.getExecutableBasename(executionCommand.executable);
AppShell newTermuxTask = null;
ShellCreateMode shellCreateMode = processShellCreateMode(executionCommand);
if (shellCreateMode == null) return;
if (ShellCreateMode.NO_SHELL_WITH_NAME.equals(shellCreateMode)) {
newTermuxTask = getTermuxTaskForShellName(executionCommand.shellName);
if (newTermuxTask != null)
Logger.logVerbose(LOG_TAG, "Existing TermuxTask with \"" + executionCommand.shellName + "\" shell name found for shell create mode \"" + shellCreateMode.getMode() + "\"");
else
Logger.logVerbose(LOG_TAG, "No existing TermuxTask with \"" + executionCommand.shellName + "\" shell name found for shell create mode \"" + shellCreateMode.getMode() + "\"");
}
if (newTermuxTask == null)
newTermuxTask = createTermuxTask(executionCommand);
}
/** Create a TermuxTask. */
@Nullable
public AppShell createTermuxTask(String executablePath, String[] arguments, String stdin, String workingDirectory) {
return createTermuxTask(new ExecutionCommand(TermuxShellManager.getNextShellId(), executablePath,
arguments, stdin, workingDirectory, Runner.APP_SHELL.getName(), false));
}
/** Create a TermuxTask. */
@Nullable
public synchronized AppShell createTermuxTask(ExecutionCommand executionCommand) {
if (executionCommand == null) return null;
Logger.logDebug(LOG_TAG, "Creating \"" + executionCommand.getCommandIdAndLabelLogString() + "\" TermuxTask");
if (!Runner.APP_SHELL.equalsRunner(executionCommand.runner)) {
Logger.logDebug(LOG_TAG, "Ignoring wrong runner \"" + executionCommand.runner + "\" command passed to createTermuxTask()");
return null;
}
executionCommand.setShellCommandShellEnvironment = true;
if (Logger.getLogLevel() >= Logger.LOG_LEVEL_VERBOSE)
Logger.logVerboseExtended(LOG_TAG, executionCommand.toString());
AppShell newTermuxTask = AppShell.execute(this, executionCommand, this,
new TermuxShellEnvironment(), null,false);
if (newTermuxTask == null) {
Logger.logError(LOG_TAG, "Failed to execute new TermuxTask command for:\n" + executionCommand.getCommandIdAndLabelLogString());
// If the execution command was started for a plugin, then process the error
if (executionCommand.isPluginExecutionCommand)
TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
else {
Logger.logError(LOG_TAG, "Set log level to debug or higher to see error in logs");
Logger.logErrorPrivateExtended(LOG_TAG, executionCommand.toString());
}
return null;
}
mShellManager.mTermuxTasks.add(newTermuxTask);
// Remove the execution command from the pending plugin execution commands list since it has
// now been processed
if (executionCommand.isPluginExecutionCommand)
mShellManager.mPendingPluginExecutionCommands.remove(executionCommand);
updateNotification();
return newTermuxTask;
}
/** Callback received when a TermuxTask finishes. */
@Override
public void onAppShellExited(final AppShell termuxTask) {
mHandler.post(() -> {
if (termuxTask != null) {
ExecutionCommand executionCommand = termuxTask.getExecutionCommand();
Logger.logVerbose(LOG_TAG, "The onTermuxTaskExited() callback called for \"" + executionCommand.getCommandIdAndLabelLogString() + "\" TermuxTask command");
// If the execution command was started for a plugin, then process the results
if (executionCommand != null && executionCommand.isPluginExecutionCommand)
TermuxPluginUtils.processPluginExecutionCommandResult(this, LOG_TAG, executionCommand);
mShellManager.mTermuxTasks.remove(termuxTask);
}
updateNotification();
});
}
/** Execute a shell command in a foreground {@link TermuxSession}. */
private void executeTermuxSessionCommand(ExecutionCommand executionCommand) {
if (executionCommand == null) return;
Logger.logDebug(LOG_TAG, "Executing foreground \"" + executionCommand.getCommandIdAndLabelLogString() + "\" TermuxSession command");
// Transform executable path to shell/session name, e.g. "/bin/do-something.sh" => "do-something.sh".
if (executionCommand.shellName == null && executionCommand.executable != null)
executionCommand.shellName = ShellUtils.getExecutableBasename(executionCommand.executable);
TermuxSession newTermuxSession = null;
ShellCreateMode shellCreateMode = processShellCreateMode(executionCommand);
if (shellCreateMode == null) return;
if (ShellCreateMode.NO_SHELL_WITH_NAME.equals(shellCreateMode)) {
newTermuxSession = getTermuxSessionForShellName(executionCommand.shellName);
if (newTermuxSession != null)
Logger.logVerbose(LOG_TAG, "Existing TermuxSession with \"" + executionCommand.shellName + "\" shell name found for shell create mode \"" + shellCreateMode.getMode() + "\"");
else
Logger.logVerbose(LOG_TAG, "No existing TermuxSession with \"" + executionCommand.shellName + "\" shell name found for shell create mode \"" + shellCreateMode.getMode() + "\"");
}
if (newTermuxSession == null)
newTermuxSession = createTermuxSession(executionCommand);
if (newTermuxSession == null) return;
handleSessionAction(DataUtils.getIntFromString(executionCommand.sessionAction,
TERMUX_SERVICE.VALUE_EXTRA_SESSION_ACTION_SWITCH_TO_NEW_SESSION_AND_OPEN_ACTIVITY),
newTermuxSession.getTerminalSession());
}
/**
* Create a {@link TermuxSession}.
* Currently called by {@link TermuxTerminalSessionActivityClient#addNewSession(boolean, String)} to add a new {@link TermuxSession}.
*/
@Nullable
public TermuxSession createTermuxSession(String executablePath, String[] arguments, String stdin,
String workingDirectory, boolean isFailSafe, String sessionName) {
ExecutionCommand executionCommand = new ExecutionCommand(TermuxShellManager.getNextShellId(),
executablePath, arguments, stdin, workingDirectory, Runner.TERMINAL_SESSION.getName(), isFailSafe);
executionCommand.shellName = sessionName;
return createTermuxSession(executionCommand);
}
/** Create a {@link TermuxSession}. */
@Nullable
public synchronized TermuxSession createTermuxSession(ExecutionCommand executionCommand) {
if (executionCommand == null) return null;
Logger.logDebug(LOG_TAG, "Creating \"" + executionCommand.getCommandIdAndLabelLogString() + "\" TermuxSession");
if (!Runner.TERMINAL_SESSION.equalsRunner(executionCommand.runner)) {
Logger.logDebug(LOG_TAG, "Ignoring wrong runner \"" + executionCommand.runner + "\" command passed to createTermuxSession()");
return null;
}
executionCommand.setShellCommandShellEnvironment = true;
executionCommand.terminalTranscriptRows = mProperties.getTerminalTranscriptRows();
if (Logger.getLogLevel() >= Logger.LOG_LEVEL_VERBOSE)
Logger.logVerboseExtended(LOG_TAG, executionCommand.toString());
// If the execution command was started for a plugin, only then will the stdout be set
// Otherwise if command was manually started by the user like by adding a new terminal session,
// then no need to set stdout
TermuxSession newTermuxSession = TermuxSession.execute(this, executionCommand, getTermuxTerminalSessionClient(),
this, new TermuxShellEnvironment(), null, executionCommand.isPluginExecutionCommand);
if (newTermuxSession == null) {
Logger.logError(LOG_TAG, "Failed to execute new TermuxSession command for:\n" + executionCommand.getCommandIdAndLabelLogString());
// If the execution command was started for a plugin, then process the error
if (executionCommand.isPluginExecutionCommand)
TermuxPluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
else {
Logger.logError(LOG_TAG, "Set log level to debug or higher to see error in logs");
Logger.logErrorPrivateExtended(LOG_TAG, executionCommand.toString());
}
return null;
}
mShellManager.mTermuxSessions.add(newTermuxSession);
// Remove the execution command from the pending plugin execution commands list since it has
// now been processed
if (executionCommand.isPluginExecutionCommand)
mShellManager.mPendingPluginExecutionCommands.remove(executionCommand);
// Notify {@link TermuxSessionsListViewController} that sessions list has been updated if
// activity in is foreground
if (mTermuxTerminalSessionActivityClient != null)
mTermuxTerminalSessionActivityClient.termuxSessionListNotifyUpdated();
updateNotification();
// No need to recreate the activity since it likely just started and theme should already have applied
TermuxActivity.updateTermuxActivityStyling(this, false);
return newTermuxSession;
}
/** Remove a TermuxSession. */
public synchronized int removeTermuxSession(TerminalSession sessionToRemove) {
int index = getIndexOfSession(sessionToRemove);
if (index >= 0)
mShellManager.mTermuxSessions.get(index).finish();
return index;
}
/** Callback received when a {@link TermuxSession} finishes. */
@Override
public void onTermuxSessionExited(final TermuxSession termuxSession) {
if (termuxSession != null) {
ExecutionCommand executionCommand = termuxSession.getExecutionCommand();
Logger.logVerbose(LOG_TAG, "The onTermuxSessionExited() callback called for \"" + executionCommand.getCommandIdAndLabelLogString() + "\" TermuxSession command");
// If the execution command was started for a plugin, then process the results
if (executionCommand != null && executionCommand.isPluginExecutionCommand)
TermuxPluginUtils.processPluginExecutionCommandResult(this, LOG_TAG, executionCommand);
mShellManager.mTermuxSessions.remove(termuxSession);
// Notify {@link TermuxSessionsListViewController} that sessions list has been updated if
// activity in is foreground
if (mTermuxTerminalSessionActivityClient != null)
mTermuxTerminalSessionActivityClient.termuxSessionListNotifyUpdated();
}
updateNotification();
}
private ShellCreateMode processShellCreateMode(@NonNull ExecutionCommand executionCommand) {
if (ShellCreateMode.ALWAYS.equalsMode(executionCommand.shellCreateMode))
return ShellCreateMode.ALWAYS; // Default
else if (ShellCreateMode.NO_SHELL_WITH_NAME.equalsMode(executionCommand.shellCreateMode))
if (DataUtils.isNullOrEmpty(executionCommand.shellName)) {
TermuxPluginUtils.setAndProcessPluginExecutionCommandError(this, LOG_TAG, executionCommand, false,
getString(R.string.error_termux_service_execution_command_shell_name_unset, executionCommand.shellCreateMode));
return null;
} else {
return ShellCreateMode.NO_SHELL_WITH_NAME;
}
else {
TermuxPluginUtils.setAndProcessPluginExecutionCommandError(this, LOG_TAG, executionCommand, false,
getString(R.string.error_termux_service_unsupported_execution_command_shell_create_mode, executionCommand.shellCreateMode));
return null;
}
}
/** Process session action for new session. */
private void handleSessionAction(int sessionAction, TerminalSession newTerminalSession) {
Logger.logDebug(LOG_TAG, "Processing sessionAction \"" + sessionAction + "\" for session \"" + newTerminalSession.mSessionName + "\"");
switch (sessionAction) {
case TERMUX_SERVICE.VALUE_EXTRA_SESSION_ACTION_SWITCH_TO_NEW_SESSION_AND_OPEN_ACTIVITY:
setCurrentStoredTerminalSession(newTerminalSession);
if (mTermuxTerminalSessionActivityClient != null)
mTermuxTerminalSessionActivityClient.setCurrentSession(newTerminalSession);
startTermuxActivity();
break;
case TERMUX_SERVICE.VALUE_EXTRA_SESSION_ACTION_KEEP_CURRENT_SESSION_AND_OPEN_ACTIVITY:
if (getTermuxSessionsSize() == 1)
setCurrentStoredTerminalSession(newTerminalSession);
startTermuxActivity();
break;
case TERMUX_SERVICE.VALUE_EXTRA_SESSION_ACTION_SWITCH_TO_NEW_SESSION_AND_DONT_OPEN_ACTIVITY:
setCurrentStoredTerminalSession(newTerminalSession);
if (mTermuxTerminalSessionActivityClient != null)
mTermuxTerminalSessionActivityClient.setCurrentSession(newTerminalSession);
break;
case TERMUX_SERVICE.VALUE_EXTRA_SESSION_ACTION_KEEP_CURRENT_SESSION_AND_DONT_OPEN_ACTIVITY:
if (getTermuxSessionsSize() == 1)
setCurrentStoredTerminalSession(newTerminalSession);
break;
default:
Logger.logError(LOG_TAG, "Invalid sessionAction: \"" + sessionAction + "\". Force using default sessionAction.");
handleSessionAction(TERMUX_SERVICE.VALUE_EXTRA_SESSION_ACTION_SWITCH_TO_NEW_SESSION_AND_OPEN_ACTIVITY, newTerminalSession);
break;
}
}
/** Launch the {@link }TermuxActivity} to bring it to foreground. */
private void startTermuxActivity() {
// For android >= 10, apps require Display over other apps permission to start foreground activities
// from background (services). If it is not granted, then TermuxSessions that are started will
// show in Termux notification but will not run until user manually clicks the notification.
if (PermissionUtils.validateDisplayOverOtherAppsPermissionForPostAndroid10(this, true)) {
TermuxActivity.startTermuxActivity(this);
} else {
TermuxAppSharedPreferences preferences = TermuxAppSharedPreferences.build(this);
if (preferences == null) return;
if (preferences.arePluginErrorNotificationsEnabled(false))
Logger.showToast(this, this.getString(R.string.error_display_over_other_apps_permission_not_granted_to_start_terminal), true);
}
}
/** If {@link TermuxActivity} has not bound to the {@link TermuxService} yet or is destroyed, then
* interface functions requiring the activity should not be available to the terminal sessions,
* so we just return the {@link #mTermuxTerminalSessionServiceClient}. Once {@link TermuxActivity} bind
* callback is received, it should call {@link #setTermuxTerminalSessionClient} to set the
* {@link TermuxService#mTermuxTerminalSessionActivityClient} so that further terminal sessions are directly
* passed the {@link TermuxTerminalSessionActivityClient} object which fully implements the
* {@link TerminalSessionClient} interface.
*
* @return Returns the {@link TermuxTerminalSessionActivityClient} if {@link TermuxActivity} has bound with
* {@link TermuxService}, otherwise {@link TermuxTerminalSessionServiceClient}.
*/
public synchronized TermuxTerminalSessionClientBase getTermuxTerminalSessionClient() {
if (mTermuxTerminalSessionActivityClient != null)
return mTermuxTerminalSessionActivityClient;
else
return mTermuxTerminalSessionServiceClient;
}
/** This should be called when {@link TermuxActivity#onServiceConnected} is called to set the
* {@link TermuxService#mTermuxTerminalSessionActivityClient} variable and update the {@link TerminalSession}
* and {@link TerminalEmulator} clients in case they were passed {@link TermuxTerminalSessionServiceClient}
* earlier.
*
* @param termuxTerminalSessionActivityClient The {@link TermuxTerminalSessionActivityClient} object that fully
* implements the {@link TerminalSessionClient} interface.
*/
public synchronized void setTermuxTerminalSessionClient(TermuxTerminalSessionActivityClient termuxTerminalSessionActivityClient) {
mTermuxTerminalSessionActivityClient = termuxTerminalSessionActivityClient;
for (int i = 0; i < mShellManager.mTermuxSessions.size(); i++)
mShellManager.mTermuxSessions.get(i).getTerminalSession().updateTerminalSessionClient(mTermuxTerminalSessionActivityClient);
}
/** This should be called when {@link TermuxActivity} has been destroyed and in {@link #onUnbind(Intent)}
* so that the {@link TermuxService} and {@link TerminalSession} and {@link TerminalEmulator}
* clients do not hold an activity references.
*/
public synchronized void unsetTermuxTerminalSessionClient() {
for (int i = 0; i < mShellManager.mTermuxSessions.size(); i++)
mShellManager.mTermuxSessions.get(i).getTerminalSession().updateTerminalSessionClient(mTermuxTerminalSessionServiceClient);
mTermuxTerminalSessionActivityClient = null;
}
private Notification buildNotification() {
Resources res = getResources();
// Set pending intent to be launched when notification is clicked
Intent notificationIntent = TermuxActivity.newInstance(this);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
// Set notification text
int sessionCount = getTermuxSessionsSize();
int taskCount = mShellManager.mTermuxTasks.size();
String notificationText = sessionCount + " session" + (sessionCount == 1 ? "" : "s");
if (taskCount > 0) {
notificationText += ", " + taskCount + " task" + (taskCount == 1 ? "" : "s");
}
final boolean wakeLockHeld = mWakeLock != null;
if (wakeLockHeld) notificationText += " (wake lock held)";
// Set notification priority
// If holding a wake or wifi lock consider the notification of high priority since it's using power,
// otherwise use a low priority
int priority = (wakeLockHeld) ? Notification.PRIORITY_HIGH : Notification.PRIORITY_LOW;
// Build the notification
Notification.Builder builder = NotificationUtils.geNotificationBuilder(this,
TermuxConstants.TERMUX_APP_NOTIFICATION_CHANNEL_ID, priority,
TermuxConstants.TERMUX_APP_NAME, notificationText, null,
contentIntent, null, NotificationUtils.NOTIFICATION_MODE_SILENT);
if (builder == null) return null;
// No need to show a timestamp:
builder.setShowWhen(false);
// Set notification icon
builder.setSmallIcon(R.drawable.ic_service_notification);
// Set background color for small notification icon
gitextract_hurpdc6s/
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── 01-bug-report.yml
│ │ ├── 02-feature-request.yml
│ │ └── config.yml
│ ├── dependabot.yml
│ └── workflows/
│ ├── attach_debug_apks_to_release.yml
│ ├── debug_build.yml
│ ├── dependency-submission.yml
│ ├── gradle-wrapper-validation.yml
│ ├── run_tests.yml
│ └── trigger_library_builds_on_jitpack.yml
├── .gitignore
├── LICENSE.md
├── README.md
├── SECURITY.md
├── app/
│ ├── build.gradle
│ ├── proguard-rules.pro
│ ├── src/
│ │ ├── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── cpp/
│ │ │ │ ├── Android.mk
│ │ │ │ ├── termux-bootstrap-zip.S
│ │ │ │ └── termux-bootstrap.c
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── termux/
│ │ │ │ ├── app/
│ │ │ │ │ ├── RunCommandService.java
│ │ │ │ │ ├── TermuxActivity.java
│ │ │ │ │ ├── TermuxApplication.java
│ │ │ │ │ ├── TermuxInstaller.java
│ │ │ │ │ ├── TermuxOpenReceiver.java
│ │ │ │ │ ├── TermuxService.java
│ │ │ │ │ ├── activities/
│ │ │ │ │ │ ├── HelpActivity.java
│ │ │ │ │ │ └── SettingsActivity.java
│ │ │ │ │ ├── api/
│ │ │ │ │ │ └── file/
│ │ │ │ │ │ └── FileReceiverActivity.java
│ │ │ │ │ ├── event/
│ │ │ │ │ │ └── SystemEventReceiver.java
│ │ │ │ │ ├── fragments/
│ │ │ │ │ │ └── settings/
│ │ │ │ │ │ ├── TermuxAPIPreferencesFragment.java
│ │ │ │ │ │ ├── TermuxFloatPreferencesFragment.java
│ │ │ │ │ │ ├── TermuxPreferencesFragment.java
│ │ │ │ │ │ ├── TermuxTaskerPreferencesFragment.java
│ │ │ │ │ │ ├── TermuxWidgetPreferencesFragment.java
│ │ │ │ │ │ ├── termux/
│ │ │ │ │ │ │ ├── DebuggingPreferencesFragment.java
│ │ │ │ │ │ │ ├── TerminalIOPreferencesFragment.java
│ │ │ │ │ │ │ └── TerminalViewPreferencesFragment.java
│ │ │ │ │ │ ├── termux_api/
│ │ │ │ │ │ │ └── DebuggingPreferencesFragment.java
│ │ │ │ │ │ ├── termux_float/
│ │ │ │ │ │ │ └── DebuggingPreferencesFragment.java
│ │ │ │ │ │ ├── termux_tasker/
│ │ │ │ │ │ │ └── DebuggingPreferencesFragment.java
│ │ │ │ │ │ └── termux_widget/
│ │ │ │ │ │ └── DebuggingPreferencesFragment.java
│ │ │ │ │ ├── models/
│ │ │ │ │ │ └── UserAction.java
│ │ │ │ │ └── terminal/
│ │ │ │ │ ├── TermuxActivityRootView.java
│ │ │ │ │ ├── TermuxSessionsListViewController.java
│ │ │ │ │ ├── TermuxTerminalSessionActivityClient.java
│ │ │ │ │ ├── TermuxTerminalSessionServiceClient.java
│ │ │ │ │ ├── TermuxTerminalViewClient.java
│ │ │ │ │ └── io/
│ │ │ │ │ ├── FullScreenWorkAround.java
│ │ │ │ │ ├── KeyboardShortcut.java
│ │ │ │ │ ├── TerminalToolbarViewPager.java
│ │ │ │ │ └── TermuxTerminalExtraKeys.java
│ │ │ │ └── filepicker/
│ │ │ │ └── TermuxDocumentsProvider.java
│ │ │ └── res/
│ │ │ ├── drawable/
│ │ │ │ ├── current_session.xml
│ │ │ │ ├── current_session_black.xml
│ │ │ │ ├── ic_foreground.xml
│ │ │ │ ├── ic_new_session.xml
│ │ │ │ ├── ic_service_notification.xml
│ │ │ │ ├── ic_settings.xml
│ │ │ │ ├── session_background_black_selected.xml
│ │ │ │ ├── session_background_selected.xml
│ │ │ │ ├── session_ripple.xml
│ │ │ │ ├── session_ripple_black.xml
│ │ │ │ └── terminal_scroll_shape.xml
│ │ │ ├── layout/
│ │ │ │ ├── activity_settings.xml
│ │ │ │ ├── activity_termux.xml
│ │ │ │ ├── item_terminal_sessions_list.xml
│ │ │ │ ├── preference_markdown_text.xml
│ │ │ │ ├── view_terminal_toolbar_extra_keys.xml
│ │ │ │ └── view_terminal_toolbar_text_input.xml
│ │ │ ├── mipmap-anydpi-v26/
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── values/
│ │ │ │ ├── attrs.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── strings.xml
│ │ │ │ ├── styles.xml
│ │ │ │ └── themes.xml
│ │ │ ├── values-night/
│ │ │ │ └── themes.xml
│ │ │ └── xml/
│ │ │ ├── root_preferences.xml
│ │ │ ├── shortcuts.xml
│ │ │ ├── termux_api_debugging_preferences.xml
│ │ │ ├── termux_api_preferences.xml
│ │ │ ├── termux_debugging_preferences.xml
│ │ │ ├── termux_float_debugging_preferences.xml
│ │ │ ├── termux_float_preferences.xml
│ │ │ ├── termux_preferences.xml
│ │ │ ├── termux_tasker_debugging_preferences.xml
│ │ │ ├── termux_tasker_preferences.xml
│ │ │ ├── termux_terminal_io_preferences.xml
│ │ │ ├── termux_terminal_view_preferences.xml
│ │ │ ├── termux_widget_debugging_preferences.xml
│ │ │ └── termux_widget_preferences.xml
│ │ └── test/
│ │ └── java/
│ │ └── com/
│ │ └── termux/
│ │ └── app/
│ │ ├── TermuxActivityTest.java
│ │ └── api/
│ │ └── file/
│ │ └── FileReceiverActivityTest.java
│ └── testkey_untrusted.jks
├── art/
│ ├── copy-to-other-apps.sh
│ ├── generate-big-icon.sh
│ ├── generate-feature-graphic.sh
│ ├── generate-launcher-images.sh
│ └── generate-tv-banner.sh
├── build.gradle
├── docs/
│ └── en/
│ └── index.md
├── fastlane/
│ └── metadata/
│ └── android/
│ └── en-US/
│ ├── full_description.txt
│ └── short_description.txt
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── jitpack.yml
├── settings.gradle
├── terminal-emulator/
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── termux/
│ │ │ └── terminal/
│ │ │ ├── ByteQueue.java
│ │ │ ├── JNI.java
│ │ │ ├── KeyHandler.java
│ │ │ ├── Logger.java
│ │ │ ├── TerminalBuffer.java
│ │ │ ├── TerminalColorScheme.java
│ │ │ ├── TerminalColors.java
│ │ │ ├── TerminalEmulator.java
│ │ │ ├── TerminalOutput.java
│ │ │ ├── TerminalRow.java
│ │ │ ├── TerminalSession.java
│ │ │ ├── TerminalSessionClient.java
│ │ │ ├── TextStyle.java
│ │ │ └── WcWidth.java
│ │ └── jni/
│ │ ├── Android.mk
│ │ └── termux.c
│ └── test/
│ └── java/
│ └── com/
│ └── termux/
│ └── terminal/
│ ├── ApcTest.java
│ ├── ByteQueueTest.java
│ ├── ControlSequenceIntroducerTest.java
│ ├── CursorAndScreenTest.java
│ ├── DecSetTest.java
│ ├── DeviceControlStringTest.java
│ ├── HistoryTest.java
│ ├── KeyHandlerTest.java
│ ├── OperatingSystemControlTest.java
│ ├── RectangularAreasTest.java
│ ├── ResizeTest.java
│ ├── ScreenBufferTest.java
│ ├── ScrollRegionTest.java
│ ├── TerminalRowTest.java
│ ├── TerminalTest.java
│ ├── TerminalTestCase.java
│ ├── TextStyleTest.java
│ ├── UnicodeInputTest.java
│ └── WcWidthTest.java
├── terminal-view/
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── com/
│ │ └── termux/
│ │ └── view/
│ │ ├── GestureAndScaleRecognizer.java
│ │ ├── TerminalRenderer.java
│ │ ├── TerminalView.java
│ │ ├── TerminalViewClient.java
│ │ ├── support/
│ │ │ └── PopupWindowCompatGingerbread.java
│ │ └── textselection/
│ │ ├── CursorController.java
│ │ ├── TextSelectionCursorController.java
│ │ └── TextSelectionHandleView.java
│ └── res/
│ ├── drawable/
│ │ ├── text_select_handle_left_material.xml
│ │ └── text_select_handle_right_material.xml
│ └── values/
│ └── strings.xml
└── termux-shared/
├── .gitignore
├── LICENSE.md
├── build.gradle
├── proguard-rules.pro
└── src/
├── androidTest/
│ └── java/
│ └── com/
│ └── termux/
│ └── shared/
│ └── ExampleInstrumentedTest.java
└── main/
├── AndroidManifest.xml
├── cpp/
│ ├── Android.mk
│ ├── Application.mk
│ └── local-socket.cpp
├── java/
│ └── com/
│ └── termux/
│ └── shared/
│ ├── activities/
│ │ ├── ReportActivity.java
│ │ └── TextIOActivity.java
│ ├── activity/
│ │ ├── ActivityErrno.java
│ │ ├── ActivityUtils.java
│ │ └── media/
│ │ └── AppCompatActivityUtils.java
│ ├── android/
│ │ ├── AndroidUtils.java
│ │ ├── FeatureFlagUtils.java
│ │ ├── PackageUtils.java
│ │ ├── PermissionUtils.java
│ │ ├── PhantomProcessUtils.java
│ │ ├── ProcessUtils.java
│ │ ├── SELinuxUtils.java
│ │ ├── SettingsProviderUtils.java
│ │ ├── UserUtils.java
│ │ └── resource/
│ │ └── ResourceUtils.java
│ ├── crash/
│ │ └── CrashHandler.java
│ ├── data/
│ │ ├── DataUtils.java
│ │ └── IntentUtils.java
│ ├── errors/
│ │ ├── Errno.java
│ │ ├── Error.java
│ │ └── FunctionErrno.java
│ ├── file/
│ │ ├── FileUtils.java
│ │ ├── FileUtilsErrno.java
│ │ ├── filesystem/
│ │ │ ├── FileAttributes.java
│ │ │ ├── FileKey.java
│ │ │ ├── FilePermission.java
│ │ │ ├── FilePermissions.java
│ │ │ ├── FileTime.java
│ │ │ ├── FileType.java
│ │ │ ├── FileTypes.java
│ │ │ ├── NativeDispatcher.java
│ │ │ └── UnixConstants.java
│ │ └── tests/
│ │ └── FileUtilsTests.java
│ ├── interact/
│ │ ├── MessageDialogUtils.java
│ │ └── ShareUtils.java
│ ├── jni/
│ │ └── models/
│ │ └── JniResult.java
│ ├── logger/
│ │ └── Logger.java
│ ├── markdown/
│ │ └── MarkdownUtils.java
│ ├── models/
│ │ ├── ReportInfo.java
│ │ └── TextIOInfo.java
│ ├── net/
│ │ ├── socket/
│ │ │ └── local/
│ │ │ ├── ILocalSocketManager.java
│ │ │ ├── LocalClientSocket.java
│ │ │ ├── LocalServerSocket.java
│ │ │ ├── LocalSocketErrno.java
│ │ │ ├── LocalSocketManager.java
│ │ │ ├── LocalSocketManagerClientBase.java
│ │ │ ├── LocalSocketRunConfig.java
│ │ │ └── PeerCred.java
│ │ ├── uri/
│ │ │ ├── UriScheme.java
│ │ │ └── UriUtils.java
│ │ └── url/
│ │ └── UrlUtils.java
│ ├── notification/
│ │ └── NotificationUtils.java
│ ├── reflection/
│ │ └── ReflectionUtils.java
│ ├── settings/
│ │ ├── preferences/
│ │ │ ├── AppSharedPreferences.java
│ │ │ └── SharedPreferenceUtils.java
│ │ └── properties/
│ │ ├── SharedProperties.java
│ │ └── SharedPropertiesParser.java
│ ├── shell/
│ │ ├── ArgumentTokenizer.java
│ │ ├── ShellUtils.java
│ │ ├── StreamGobbler.java
│ │ ├── am/
│ │ │ ├── AmSocketServer.java
│ │ │ ├── AmSocketServerErrno.java
│ │ │ └── AmSocketServerRunConfig.java
│ │ └── command/
│ │ ├── ExecutionCommand.java
│ │ ├── ShellCommandConstants.java
│ │ ├── environment/
│ │ │ ├── AndroidShellEnvironment.java
│ │ │ ├── IShellEnvironment.java
│ │ │ ├── ShellCommandShellEnvironment.java
│ │ │ ├── ShellEnvironmentUtils.java
│ │ │ ├── ShellEnvironmentVariable.java
│ │ │ └── UnixShellEnvironment.java
│ │ ├── result/
│ │ │ ├── ResultConfig.java
│ │ │ ├── ResultData.java
│ │ │ ├── ResultSender.java
│ │ │ └── ResultSenderErrno.java
│ │ └── runner/
│ │ └── app/
│ │ └── AppShell.java
│ ├── termux/
│ │ ├── TermuxBootstrap.java
│ │ ├── TermuxConstants.java
│ │ ├── TermuxUtils.java
│ │ ├── crash/
│ │ │ └── TermuxCrashUtils.java
│ │ ├── data/
│ │ │ └── TermuxUrlUtils.java
│ │ ├── extrakeys/
│ │ │ ├── ExtraKeyButton.java
│ │ │ ├── ExtraKeysConstants.java
│ │ │ ├── ExtraKeysInfo.java
│ │ │ ├── ExtraKeysView.java
│ │ │ ├── SpecialButton.java
│ │ │ └── SpecialButtonState.java
│ │ ├── file/
│ │ │ └── TermuxFileUtils.java
│ │ ├── interact/
│ │ │ └── TextInputDialogUtils.java
│ │ ├── models/
│ │ │ └── UserAction.java
│ │ ├── notification/
│ │ │ └── TermuxNotificationUtils.java
│ │ ├── plugins/
│ │ │ └── TermuxPluginUtils.java
│ │ ├── settings/
│ │ │ ├── preferences/
│ │ │ │ ├── TermuxAPIAppSharedPreferences.java
│ │ │ │ ├── TermuxAppSharedPreferences.java
│ │ │ │ ├── TermuxBootAppSharedPreferences.java
│ │ │ │ ├── TermuxFloatAppSharedPreferences.java
│ │ │ │ ├── TermuxPreferenceConstants.java
│ │ │ │ ├── TermuxStylingAppSharedPreferences.java
│ │ │ │ ├── TermuxTaskerAppSharedPreferences.java
│ │ │ │ └── TermuxWidgetAppSharedPreferences.java
│ │ │ └── properties/
│ │ │ ├── TermuxAppSharedProperties.java
│ │ │ ├── TermuxPropertyConstants.java
│ │ │ └── TermuxSharedProperties.java
│ │ ├── shell/
│ │ │ ├── TermuxShellManager.java
│ │ │ ├── TermuxShellUtils.java
│ │ │ ├── am/
│ │ │ │ └── TermuxAmSocketServer.java
│ │ │ └── command/
│ │ │ ├── environment/
│ │ │ │ ├── TermuxAPIShellEnvironment.java
│ │ │ │ ├── TermuxAppShellEnvironment.java
│ │ │ │ ├── TermuxShellCommandShellEnvironment.java
│ │ │ │ └── TermuxShellEnvironment.java
│ │ │ └── runner/
│ │ │ └── terminal/
│ │ │ └── TermuxSession.java
│ │ ├── terminal/
│ │ │ ├── TermuxTerminalSessionClientBase.java
│ │ │ ├── TermuxTerminalViewClientBase.java
│ │ │ └── io/
│ │ │ ├── BellHandler.java
│ │ │ └── TerminalExtraKeys.java
│ │ └── theme/
│ │ └── TermuxThemeUtils.java
│ ├── theme/
│ │ ├── NightMode.java
│ │ └── ThemeUtils.java
│ └── view/
│ ├── KeyboardUtils.java
│ └── ViewUtils.java
└── res/
├── drawable/
│ ├── ic_copy.xml
│ ├── ic_error_notification.xml
│ ├── ic_info.xml
│ ├── ic_settings.xml
│ └── ic_share.xml
├── layout/
│ ├── activity_report.xml
│ ├── activity_text_io.xml
│ ├── dialog_show_message.xml
│ ├── markdown_adapter_node_code_block.xml
│ ├── markdown_adapter_node_default.xml
│ └── partial_primary_toolbar.xml
├── menu/
│ ├── menu_report.xml
│ └── menu_text_io.xml
├── raw/
│ ├── apt_info_script.sh
│ ├── bell.ogg
│ └── keep.xml
├── values/
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ ├── styles.xml
│ └── themes.xml
└── values-night/
└── themes.xml
Showing preview only (242K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2547 symbols across 200 files)
FILE: app/src/main/cpp/termux-bootstrap.c
function JNICALL (line 6) | JNICALL Java_com_termux_app_TermuxInstaller_getZip(JNIEnv *env, __attrib...
FILE: app/src/main/java/com/termux/app/RunCommandService.java
class RunCommandService (line 36) | public class RunCommandService extends Service {
class LocalBinder (line 40) | class LocalBinder extends Binder {
method onBind (line 46) | @Override
method onCreate (line 51) | @Override
method onStartCommand (line 57) | @Override
method stopService (line 242) | private int stopService() {
method runStartForeground (line 247) | private void runStartForeground() {
method runStopForeground (line 254) | private void runStopForeground() {
method buildNotification (line 260) | private Notification buildNotification() {
method setupNotificationChannel (line 280) | private void setupNotificationChannel() {
FILE: app/src/main/java/com/termux/app/TermuxActivity.java
class TermuxActivity (line 80) | public final class TermuxActivity extends AppCompatActivity implements S...
method onCreate (line 197) | @Override
method onStart (line 282) | @Override
method onResume (line 304) | @Override
method onStop (line 325) | @Override
method onDestroy (line 347) | @Override
method onSaveInstanceState (line 368) | @Override
method onServiceConnected (line 386) | @Override
method onServiceDisconnected (line 432) | @Override
method reloadProperties (line 445) | private void reloadProperties() {
method setActivityTheme (line 454) | private void setActivityTheme() {
method setMargins (line 464) | private void setMargins() {
method addTermuxActivityRootViewGlobalLayoutListener (line 473) | public void addTermuxActivityRootViewGlobalLayoutListener() {
method removeTermuxActivityRootViewGlobalLayoutListener (line 477) | public void removeTermuxActivityRootViewGlobalLayoutListener() {
method setTermuxTerminalViewAndClients (line 484) | private void setTermuxTerminalViewAndClients() {
method setTermuxSessionsListView (line 500) | private void setTermuxSessionsListView() {
method setTerminalToolbarView (line 510) | private void setTerminalToolbarView(Bundle savedInstanceState) {
method setTerminalToolbarHeight (line 530) | private void setTerminalToolbarHeight() {
method toggleTerminalToolbar (line 541) | public void toggleTerminalToolbar() {
method saveTerminalToolbarTextInput (line 554) | private void saveTerminalToolbarTextInput(Bundle savedInstanceState) {
method setSettingsButtonView (line 566) | private void setSettingsButtonView() {
method setNewSessionButtonView (line 573) | private void setNewSessionButtonView() {
method setToggleKeyboardView (line 585) | private void setToggleKeyboardView() {
method onBackPressed (line 601) | @SuppressLint("RtlHardcoded")
method finishActivityIfNotFinishing (line 611) | public void finishActivityIfNotFinishing() {
method showToast (line 619) | public void showToast(String text, boolean longDuration) {
method onCreateContextMenu (line 629) | @Override
method onCreateOptionsMenu (line 654) | @Override
method onContextItemSelected (line 660) | @Override
method onContextMenuClosed (line 706) | @Override
method showKillSessionDialog (line 713) | private void showKillSessionDialog(TerminalSession session) {
method onResetTerminalSession (line 727) | private void onResetTerminalSession(TerminalSession session) {
method showStylingDialog (line 737) | private void showStylingDialog() {
method toggleKeepScreenOn (line 751) | private void toggleKeepScreenOn() {
method requestStoragePermission (line 768) | public void requestStoragePermission(boolean isPermissionCallback) {
method onActivityResult (line 792) | @Override
method onRequestPermissionsResult (line 801) | @Override
method getNavBarHeight (line 812) | public int getNavBarHeight() {
method getTermuxActivityRootView (line 816) | public TermuxActivityRootView getTermuxActivityRootView() {
method getTermuxActivityBottomSpaceView (line 820) | public View getTermuxActivityBottomSpaceView() {
method getExtraKeysView (line 824) | public ExtraKeysView getExtraKeysView() {
method getTermuxTerminalExtraKeys (line 828) | public TermuxTerminalExtraKeys getTermuxTerminalExtraKeys() {
method setExtraKeysView (line 832) | public void setExtraKeysView(ExtraKeysView extraKeysView) {
method getDrawer (line 836) | public DrawerLayout getDrawer() {
method getTerminalToolbarViewPager (line 841) | public ViewPager getTerminalToolbarViewPager() {
method getTerminalToolbarDefaultHeight (line 845) | public float getTerminalToolbarDefaultHeight() {
method isTerminalViewSelected (line 849) | public boolean isTerminalViewSelected() {
method isTerminalToolbarTextInputViewSelected (line 853) | public boolean isTerminalToolbarTextInputViewSelected() {
method termuxSessionListNotifyUpdated (line 858) | public void termuxSessionListNotifyUpdated() {
method isVisible (line 862) | public boolean isVisible() {
method isOnResumeAfterOnCreate (line 866) | public boolean isOnResumeAfterOnCreate() {
method isActivityRecreated (line 870) | public boolean isActivityRecreated() {
method getTermuxService (line 876) | public TermuxService getTermuxService() {
method getTerminalView (line 880) | public TerminalView getTerminalView() {
method getTermuxTerminalViewClient (line 884) | public TermuxTerminalViewClient getTermuxTerminalViewClient() {
method getTermuxTerminalSessionClient (line 888) | public TermuxTerminalSessionActivityClient getTermuxTerminalSessionCli...
method getCurrentSession (line 892) | @Nullable
method getPreferences (line 900) | public TermuxAppSharedPreferences getPreferences() {
method getProperties (line 904) | public TermuxAppSharedProperties getProperties() {
method updateTermuxActivityStyling (line 911) | public static void updateTermuxActivityStyling(Context context, boolea...
method registerTermuxActivityBroadcastReceiver (line 918) | private void registerTermuxActivityBroadcastReceiver() {
method unregisterTermuxActivityBroadcastReceiver (line 927) | private void unregisterTermuxActivityBroadcastReceiver() {
method fixTermuxActivityBroadcastReceiverIntent (line 931) | private void fixTermuxActivityBroadcastReceiverIntent(Intent intent) {
class TermuxActivityBroadcastReceiver (line 941) | class TermuxActivityBroadcastReceiver extends BroadcastReceiver {
method onReceive (line 942) | @Override
method reloadActivityStyling (line 968) | private void reloadActivityStyling(boolean recreateActivity) {
method startTermuxActivity (line 1003) | public static void startTermuxActivity(@NonNull final Context context) {
method newInstance (line 1007) | public static Intent newInstance(@NonNull final Context context) {
FILE: app/src/main/java/com/termux/app/TermuxApplication.java
class TermuxApplication (line 20) | public class TermuxApplication extends Application {
method onCreate (line 24) | public void onCreate() {
method setLogConfig (line 76) | public static void setLogConfig(Context context) {
FILE: app/src/main/java/com/termux/app/TermuxInstaller.java
class TermuxInstaller (line 60) | final class TermuxInstaller {
method setupBootstrapIfNeeded (line 65) | static void setupBootstrapIfNeeded(final Activity activity, final Runn...
method showBootstrapErrorDialog (line 242) | public static void showBootstrapErrorDialog(Activity activity, Runnabl...
method sendBootstrapCrashReportNotification (line 266) | private static void sendBootstrapCrashReportNotification(Activity acti...
method setupStorageSymlinks (line 277) | static void setupStorageSymlinks(final Context context) {
method ensureDirectoryExists (line 374) | private static Error ensureDirectoryExists(File directory) {
method loadZipBytes (line 378) | public static byte[] loadZipBytes() {
method getZip (line 384) | public static native byte[] getZip();
FILE: app/src/main/java/com/termux/app/TermuxOpenReceiver.java
class TermuxOpenReceiver (line 30) | public class TermuxOpenReceiver extends BroadcastReceiver {
method onReceive (line 34) | @Override
class ContentProvider (line 127) | public static class ContentProvider extends android.content.ContentPro...
method onCreate (line 131) | @Override
method query (line 136) | @Override
method getType (line 173) | @Override
method insert (line 185) | @Override
method delete (line 190) | @Override
method update (line 195) | @Override
method openFile (line 200) | @Override
FILE: app/src/main/java/com/termux/app/TermuxService.java
class TermuxService (line 68) | public final class TermuxService extends Service implements AppShell.App...
class LocalBinder (line 71) | class LocalBinder extends Binder {
method onCreate (line 110) | @Override
method onStartCommand (line 125) | @SuppressLint("Wakelock")
method onDestroy (line 168) | @Override
method onBind (line 185) | @Override
method onUnbind (line 191) | @Override
method runStartForeground (line 204) | private void runStartForeground() {
method runStopForeground (line 210) | private void runStopForeground() {
method requestStopService (line 215) | private void requestStopService() {
method actionStopService (line 222) | private void actionStopService() {
method killAllTermuxExecutionCommands (line 263) | private synchronized void killAllTermuxExecutionCommands() {
method actionAcquireWakeLock (line 304) | @SuppressLint({"WakelockTimeout", "BatteryLife"})
method actionReleaseWakeLock (line 333) | private void actionReleaseWakeLock(boolean updateNotification) {
method actionServiceExecute (line 359) | private void actionServiceExecute(Intent intent) {
method executeTermuxTaskCommand (line 432) | private void executeTermuxTaskCommand(ExecutionCommand executionComman...
method createTermuxTask (line 457) | @Nullable
method createTermuxTask (line 464) | @Nullable
method onAppShellExited (line 507) | @Override
method executeTermuxSessionCommand (line 531) | private void executeTermuxSessionCommand(ExecutionCommand executionCom...
method createTermuxSession (line 564) | @Nullable
method createTermuxSession (line 574) | @Nullable
method removeTermuxSession (line 629) | public synchronized int removeTermuxSession(TerminalSession sessionToR...
method onTermuxSessionExited (line 639) | @Override
method processShellCreateMode (line 665) | private ShellCreateMode processShellCreateMode(@NonNull ExecutionComma...
method handleSessionAction (line 684) | private void handleSessionAction(int sessionAction, TerminalSession ne...
method startTermuxActivity (line 716) | private void startTermuxActivity() {
method getTermuxTerminalSessionClient (line 745) | public synchronized TermuxTerminalSessionClientBase getTermuxTerminalS...
method setTermuxTerminalSessionClient (line 760) | public synchronized void setTermuxTerminalSessionClient(TermuxTerminal...
method unsetTermuxTerminalSessionClient (line 771) | public synchronized void unsetTermuxTerminalSessionClient() {
method buildNotification (line 782) | private Notification buildNotification() {
method setupNotificationChannel (line 844) | private void setupNotificationChannel() {
method updateNotification (line 852) | private synchronized void updateNotification() {
method setCurrentStoredTerminalSession (line 865) | private void setCurrentStoredTerminalSession(TerminalSession terminalS...
method isTermuxSessionsEmpty (line 873) | public synchronized boolean isTermuxSessionsEmpty() {
method getTermuxSessionsSize (line 877) | public synchronized int getTermuxSessionsSize() {
method getTermuxSessions (line 881) | public synchronized List<TermuxSession> getTermuxSessions() {
method getTermuxSession (line 885) | @Nullable
method getTermuxSessionForTerminalSession (line 893) | @Nullable
method getLastTermuxSession (line 905) | public synchronized TermuxSession getLastTermuxSession() {
method getIndexOfSession (line 909) | public synchronized int getIndexOfSession(TerminalSession terminalSess...
method getTerminalSessionForHandle (line 919) | public synchronized TerminalSession getTerminalSessionForHandle(String...
method getTermuxTaskForShellName (line 929) | public synchronized AppShell getTermuxTaskForShellName(String name) {
method getTermuxSessionForShellName (line 941) | public synchronized TermuxSession getTermuxSessionForShellName(String ...
method wantsToStop (line 955) | public boolean wantsToStop() {
FILE: app/src/main/java/com/termux/app/activities/HelpActivity.java
class HelpActivity (line 19) | public final class HelpActivity extends AppCompatActivity {
method onCreate (line 23) | @Override
method onBackPressed (line 68) | @Override
FILE: app/src/main/java/com/termux/app/activities/SettingsActivity.java
class SettingsActivity (line 29) | public class SettingsActivity extends AppCompatActivity {
method onCreate (line 31) | @Override
method onSupportNavigateUp (line 49) | @Override
class RootPreferencesFragment (line 55) | public static class RootPreferencesFragment extends PreferenceFragment...
method onCreatePreferences (line 56) | @Override
method configureTermuxAPIPreference (line 76) | private void configureTermuxAPIPreference(@NonNull Context context) {
method configureTermuxFloatPreference (line 85) | private void configureTermuxFloatPreference(@NonNull Context context) {
method configureTermuxTaskerPreference (line 94) | private void configureTermuxTaskerPreference(@NonNull Context contex...
method configureTermuxWidgetPreference (line 103) | private void configureTermuxWidgetPreference(@NonNull Context contex...
method configureAboutPreference (line 112) | private void configureAboutPreference(@NonNull Context context) {
method configureDonatePreference (line 144) | private void configureDonatePreference(@NonNull Context context) {
FILE: app/src/main/java/com/termux/app/api/file/FileReceiverActivity.java
class FileReceiverActivity (line 39) | public class FileReceiverActivity extends AppCompatActivity {
method isSharedTextAnUrl (line 57) | static boolean isSharedTextAnUrl(String sharedText) {
method onResume (line 64) | @Override
method showErrorDialogAndQuit (line 128) | void showErrorDialogAndQuit(String message) {
method handleContentUri (line 137) | void handleContentUri(@NonNull final Uri uri, String subjectFromIntent) {
method promptNameAndSave (line 162) | void promptNameAndSave(final InputStream in, final String attachmentFi...
method saveStreamWithName (line 201) | public File saveStreamWithName(InputStream in, String attachmentFileNa...
method handleUrlAndFinish (line 231) | void handleUrlAndFinish(final String url) {
method updateFileReceiverActivityComponentsState (line 258) | public static void updateFileReceiverActivityComponentsState(@NonNull ...
FILE: app/src/main/java/com/termux/app/event/SystemEventReceiver.java
class SystemEventReceiver (line 19) | public class SystemEventReceiver extends BroadcastReceiver {
method getInstance (line 25) | public static synchronized SystemEventReceiver getInstance() {
method onReceive (line 32) | @Override
method onActionBootCompleted (line 54) | public synchronized void onActionBootCompleted(@NonNull Context contex...
method onActionPackageUpdated (line 58) | public synchronized void onActionPackageUpdated(@NonNull Context conte...
method registerPackageUpdateEvents (line 78) | public synchronized static void registerPackageUpdateEvents(@NonNull C...
method unregisterPackageUpdateEvents (line 87) | public synchronized static void unregisterPackageUpdateEvents(@NonNull...
FILE: app/src/main/java/com/termux/app/fragments/settings/TermuxAPIPreferencesFragment.java
class TermuxAPIPreferencesFragment (line 14) | @Keep
method onCreatePreferences (line 17) | @Override
class TermuxAPIPreferencesDataStore (line 30) | class TermuxAPIPreferencesDataStore extends PreferenceDataStore {
method TermuxAPIPreferencesDataStore (line 37) | private TermuxAPIPreferencesDataStore(Context context) {
method getInstance (line 42) | public static synchronized TermuxAPIPreferencesDataStore getInstance(C...
FILE: app/src/main/java/com/termux/app/fragments/settings/TermuxFloatPreferencesFragment.java
class TermuxFloatPreferencesFragment (line 14) | @Keep
method onCreatePreferences (line 17) | @Override
class TermuxFloatPreferencesDataStore (line 30) | class TermuxFloatPreferencesDataStore extends PreferenceDataStore {
method TermuxFloatPreferencesDataStore (line 37) | private TermuxFloatPreferencesDataStore(Context context) {
method getInstance (line 42) | public static synchronized TermuxFloatPreferencesDataStore getInstance...
FILE: app/src/main/java/com/termux/app/fragments/settings/TermuxPreferencesFragment.java
class TermuxPreferencesFragment (line 14) | @Keep
method onCreatePreferences (line 17) | @Override
class TermuxPreferencesDataStore (line 30) | class TermuxPreferencesDataStore extends PreferenceDataStore {
method TermuxPreferencesDataStore (line 37) | private TermuxPreferencesDataStore(Context context) {
method getInstance (line 42) | public static synchronized TermuxPreferencesDataStore getInstance(Cont...
FILE: app/src/main/java/com/termux/app/fragments/settings/TermuxTaskerPreferencesFragment.java
class TermuxTaskerPreferencesFragment (line 14) | @Keep
method onCreatePreferences (line 17) | @Override
class TermuxTaskerPreferencesDataStore (line 30) | class TermuxTaskerPreferencesDataStore extends PreferenceDataStore {
method TermuxTaskerPreferencesDataStore (line 37) | private TermuxTaskerPreferencesDataStore(Context context) {
method getInstance (line 42) | public static synchronized TermuxTaskerPreferencesDataStore getInstanc...
FILE: app/src/main/java/com/termux/app/fragments/settings/TermuxWidgetPreferencesFragment.java
class TermuxWidgetPreferencesFragment (line 14) | @Keep
method onCreatePreferences (line 17) | @Override
class TermuxWidgetPreferencesDataStore (line 30) | class TermuxWidgetPreferencesDataStore extends PreferenceDataStore {
method TermuxWidgetPreferencesDataStore (line 37) | private TermuxWidgetPreferencesDataStore(Context context) {
method getInstance (line 42) | public static synchronized TermuxWidgetPreferencesDataStore getInstanc...
FILE: app/src/main/java/com/termux/app/fragments/settings/termux/DebuggingPreferencesFragment.java
class DebuggingPreferencesFragment (line 19) | @Keep
method onCreatePreferences (line 22) | @Override
method configureLoggingPreferences (line 35) | private void configureLoggingPreferences(@NonNull Context context) {
method setLogLevelListPreferenceData (line 49) | public static ListPreference setLogLevelListPreferenceData(ListPrefere...
class DebuggingPreferencesDataStore (line 67) | class DebuggingPreferencesDataStore extends PreferenceDataStore {
method DebuggingPreferencesDataStore (line 74) | private DebuggingPreferencesDataStore(Context context) {
method getInstance (line 79) | public static synchronized DebuggingPreferencesDataStore getInstance(C...
method getString (line 88) | @Override
method putString (line 102) | @Override
method putBoolean (line 120) | @Override
method getBoolean (line 140) | @Override
FILE: app/src/main/java/com/termux/app/fragments/settings/termux/TerminalIOPreferencesFragment.java
class TerminalIOPreferencesFragment (line 14) | @Keep
method onCreatePreferences (line 17) | @Override
class TerminalIOPreferencesDataStore (line 30) | class TerminalIOPreferencesDataStore extends PreferenceDataStore {
method TerminalIOPreferencesDataStore (line 37) | private TerminalIOPreferencesDataStore(Context context) {
method getInstance (line 42) | public static synchronized TerminalIOPreferencesDataStore getInstance(...
method putBoolean (line 51) | @Override
method getBoolean (line 68) | @Override
FILE: app/src/main/java/com/termux/app/fragments/settings/termux/TerminalViewPreferencesFragment.java
class TerminalViewPreferencesFragment (line 14) | @Keep
method onCreatePreferences (line 17) | @Override
class TerminalViewPreferencesDataStore (line 30) | class TerminalViewPreferencesDataStore extends PreferenceDataStore {
method TerminalViewPreferencesDataStore (line 37) | private TerminalViewPreferencesDataStore(Context context) {
method getInstance (line 42) | public static synchronized TerminalViewPreferencesDataStore getInstanc...
method putBoolean (line 51) | @Override
method getBoolean (line 65) | @Override
FILE: app/src/main/java/com/termux/app/fragments/settings/termux_api/DebuggingPreferencesFragment.java
class DebuggingPreferencesFragment (line 18) | @Keep
method onCreatePreferences (line 21) | @Override
method configureLoggingPreferences (line 34) | private void configureLoggingPreferences(@NonNull Context context) {
class DebuggingPreferencesDataStore (line 50) | class DebuggingPreferencesDataStore extends PreferenceDataStore {
method DebuggingPreferencesDataStore (line 57) | private DebuggingPreferencesDataStore(Context context) {
method getInstance (line 62) | public static synchronized DebuggingPreferencesDataStore getInstance(C...
method getString (line 71) | @Override
method putString (line 85) | @Override
FILE: app/src/main/java/com/termux/app/fragments/settings/termux_float/DebuggingPreferencesFragment.java
class DebuggingPreferencesFragment (line 18) | @Keep
method onCreatePreferences (line 21) | @Override
method configureLoggingPreferences (line 34) | private void configureLoggingPreferences(@NonNull Context context) {
class DebuggingPreferencesDataStore (line 50) | class DebuggingPreferencesDataStore extends PreferenceDataStore {
method DebuggingPreferencesDataStore (line 57) | private DebuggingPreferencesDataStore(Context context) {
method getInstance (line 62) | public static synchronized DebuggingPreferencesDataStore getInstance(C...
method getString (line 71) | @Override
method putString (line 85) | @Override
method putBoolean (line 101) | @Override
method getBoolean (line 115) | @Override
FILE: app/src/main/java/com/termux/app/fragments/settings/termux_tasker/DebuggingPreferencesFragment.java
class DebuggingPreferencesFragment (line 18) | @Keep
method onCreatePreferences (line 21) | @Override
method configureLoggingPreferences (line 34) | private void configureLoggingPreferences(@NonNull Context context) {
class DebuggingPreferencesDataStore (line 50) | class DebuggingPreferencesDataStore extends PreferenceDataStore {
method DebuggingPreferencesDataStore (line 57) | private DebuggingPreferencesDataStore(Context context) {
method getInstance (line 62) | public static synchronized DebuggingPreferencesDataStore getInstance(C...
method getString (line 71) | @Override
method putString (line 85) | @Override
FILE: app/src/main/java/com/termux/app/fragments/settings/termux_widget/DebuggingPreferencesFragment.java
class DebuggingPreferencesFragment (line 18) | @Keep
method onCreatePreferences (line 21) | @Override
method configureLoggingPreferences (line 34) | private void configureLoggingPreferences(@NonNull Context context) {
class DebuggingPreferencesDataStore (line 50) | class DebuggingPreferencesDataStore extends PreferenceDataStore {
method DebuggingPreferencesDataStore (line 57) | private DebuggingPreferencesDataStore(Context context) {
method getInstance (line 62) | public static synchronized DebuggingPreferencesDataStore getInstance(C...
method getString (line 71) | @Override
method putString (line 85) | @Override
FILE: app/src/main/java/com/termux/app/models/UserAction.java
type UserAction (line 3) | public enum UserAction {
method UserAction (line 10) | UserAction(final String name) {
method getName (line 14) | public String getName() {
FILE: app/src/main/java/com/termux/app/terminal/TermuxActivityRootView.java
class TermuxActivityRootView (line 64) | public class TermuxActivityRootView extends LinearLayout implements View...
method TermuxActivityRootView (line 79) | public TermuxActivityRootView(Context context) {
method TermuxActivityRootView (line 83) | public TermuxActivityRootView(Context context, @Nullable AttributeSet ...
method TermuxActivityRootView (line 87) | public TermuxActivityRootView(Context context, @Nullable AttributeSet ...
method setActivity (line 91) | public void setActivity(TermuxActivity activity) {
method setIsRootViewLoggingEnabled (line 100) | public void setIsRootViewLoggingEnabled(boolean value) {
method onMeasure (line 104) | @Override
method onGlobalLayout (line 119) | @Override
class WindowInsetsListener (line 275) | public static class WindowInsetsListener implements View.OnApplyWindow...
method onApplyWindowInsets (line 276) | @Override
FILE: app/src/main/java/com/termux/app/terminal/TermuxSessionsListViewController.java
class TermuxSessionsListViewController (line 30) | public class TermuxSessionsListViewController extends ArrayAdapter<Termu...
method TermuxSessionsListViewController (line 37) | public TermuxSessionsListViewController(TermuxActivity activity, List<...
method getView (line 42) | @SuppressLint("SetTextI18n")
method onItemClick (line 95) | @Override
method onItemLongClick (line 102) | @Override
FILE: app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionActivityClient.java
class TermuxTerminalSessionActivityClient (line 41) | public class TermuxTerminalSessionActivityClient extends TermuxTerminalS...
method TermuxTerminalSessionActivityClient (line 53) | public TermuxTerminalSessionActivityClient(TermuxActivity activity) {
method onCreate (line 60) | public void onCreate() {
method onStart (line 68) | public void onStart() {
method onResume (line 85) | public void onResume() {
method onStop (line 95) | public void onStop() {
method onReloadActivityStyling (line 110) | public void onReloadActivityStyling() {
method onTextChanged (line 117) | @Override
method onTitleChanged (line 124) | @Override
method onSessionFinished (line 138) | @Override
method onCopyTextToClipboard (line 183) | @Override
method onPasteTextFromClipboard (line 190) | @Override
method onBell (line 199) | @Override
method onColorsChanged (line 218) | @Override
method onTerminalCursorStateChange (line 224) | @Override
method setTerminalShellPid (line 237) | @Override
method onResetTerminalSession (line 251) | public void onResetTerminalSession() {
method getTerminalCursorStyle (line 259) | @Override
method loadBellSoundPool (line 267) | private synchronized void loadBellSoundPool() {
method releaseBellSoundPool (line 283) | private synchronized void releaseBellSoundPool() {
method setCurrentSession (line 293) | public void setCurrentSession(TerminalSession session) {
method notifyOfSessionChange (line 307) | void notifyOfSessionChange() {
method switchToSession (line 316) | public void switchToSession(boolean forward) {
method switchToSession (line 334) | public void switchToSession(int index) {
method renameSession (line 343) | @SuppressLint("InflateParams")
method renameSession (line 353) | private void renameSession(TerminalSession sessionToRename, String tex...
method addNewSession (line 364) | public void addNewSession(boolean isFailSafe, String sessionName) {
method setCurrentStoredSession (line 391) | public void setCurrentStoredSession() {
method getCurrentStoredSessionOrLast (line 400) | public TerminalSession getCurrentStoredSessionOrLast() {
method getCurrentStoredSession (line 419) | private TerminalSession getCurrentStoredSession() {
method removeFinishedSession (line 433) | public void removeFinishedSession(TerminalSession finishedSession) {
method termuxSessionListNotifyUpdated (line 454) | public void termuxSessionListNotifyUpdated() {
method checkAndScrollToSession (line 458) | public void checkAndScrollToSession(TerminalSession session) {
method toToastTitle (line 474) | String toToastTitle(TerminalSession session) {
method checkForFontAndColors (line 494) | public void checkForFontAndColors() {
method updateBackgroundColor (line 520) | public void updateBackgroundColor() {
FILE: app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionServiceClient.java
class TermuxTerminalSessionServiceClient (line 14) | public class TermuxTerminalSessionServiceClient extends TermuxTerminalSe...
method TermuxTerminalSessionServiceClient (line 20) | public TermuxTerminalSessionServiceClient(TermuxService service) {
method setTerminalShellPid (line 24) | @Override
FILE: app/src/main/java/com/termux/app/terminal/TermuxTerminalViewClient.java
class TermuxTerminalViewClient (line 56) | public class TermuxTerminalViewClient extends TermuxTerminalViewClientBa...
method TermuxTerminalViewClient (line 76) | public TermuxTerminalViewClient(TermuxActivity activity, TermuxTermina...
method getActivity (line 81) | public TermuxActivity getActivity() {
method onCreate (line 88) | public void onCreate() {
method onStart (line 98) | public void onStart() {
method onResume (line 112) | public void onResume() {
method onStop (line 131) | public void onStop() {
method onReloadProperties (line 139) | public void onReloadProperties() {
method onReloadActivityStyling (line 146) | public void onReloadActivityStyling() {
method onEmulatorSet (line 157) | @Override
method onScale (line 173) | @Override
method onSingleTapUp (line 185) | @Override
method shouldBackButtonBeMappedToEscape (line 209) | @Override
method shouldEnforceCharBasedInput (line 214) | @Override
method shouldUseCtrlSpaceWorkaround (line 219) | @Override
method isTerminalViewSelected (line 224) | @Override
method copyModeChanged (line 231) | @Override
method onKeyDown (line 239) | @SuppressLint("RtlHardcoded")
method onKeyUp (line 291) | @Override
method handleVirtualKeys (line 304) | private boolean handleVirtualKeys(int keyCode, KeyEvent event, boolean...
method readControlKey (line 323) | @Override
method readAltKey (line 328) | @Override
method readShiftKey (line 333) | @Override
method readFnKey (line 338) | @Override
method readExtraKeysSpecialButton (line 343) | public boolean readExtraKeysSpecialButton(SpecialButton specialButton) {
method onLongPress (line 353) | @Override
method onCodePoint (line 360) | @Override
method setSessionShortcuts (line 499) | private void setSessionShortcuts() {
method changeFontSize (line 519) | public void changeFontSize(boolean increase) {
method onToggleSoftKeyboardRequest (line 530) | public void onToggleSoftKeyboardRequest() {
method setSoftKeyboardState (line 568) | public void setSoftKeyboardState(boolean isStartup, boolean isReloadTe...
method getShowSoftKeyboardRunnable (line 648) | private Runnable getShowSoftKeyboardRunnable() {
method setTerminalCursorBlinkerState (line 659) | public void setTerminalCursorBlinkerState(boolean start) {
method shareSessionTranscript (line 674) | public void shareSessionTranscript() {
method shareSelectedText (line 687) | public void shareSelectedText() {
method showUrlSelection (line 694) | public void showUrlSelection() {
method reportIssueFromTranscript (line 729) | public void reportIssueFromTranscript() {
method reportIssueFromTranscript (line 743) | private void reportIssueFromTranscript(String transcriptText, boolean ...
method doPaste (line 792) | public void doPaste() {
FILE: app/src/main/java/com/termux/app/terminal/io/FullScreenWorkAround.java
class FullScreenWorkAround (line 17) | public class FullScreenWorkAround {
method apply (line 25) | public static void apply(TermuxActivity activity) {
method FullScreenWorkAround (line 29) | private FullScreenWorkAround(TermuxActivity activity) {
method possiblyResizeChildOfContent (line 37) | private void possiblyResizeChildOfContent() {
method getNavBarHeight (line 57) | private int getNavBarHeight() {
method computeUsableHeight (line 61) | private int computeUsableHeight() {
FILE: app/src/main/java/com/termux/app/terminal/io/KeyboardShortcut.java
class KeyboardShortcut (line 3) | public class KeyboardShortcut {
method KeyboardShortcut (line 8) | public KeyboardShortcut(int codePoint, int shortcutAction) {
FILE: app/src/main/java/com/termux/app/terminal/io/TerminalToolbarViewPager.java
class TerminalToolbarViewPager (line 17) | public class TerminalToolbarViewPager {
class PageAdapter (line 19) | public static class PageAdapter extends PagerAdapter {
method PageAdapter (line 24) | public PageAdapter(TermuxActivity activity, String savedTextInput) {
method getCount (line 29) | @Override
method isViewFromObject (line 34) | @Override
method instantiateItem (line 39) | @NonNull
method destroyItem (line 86) | @Override
class OnPageChangeListener (line 95) | public static class OnPageChangeListener extends ViewPager.SimpleOnPag...
method OnPageChangeListener (line 100) | public OnPageChangeListener(TermuxActivity activity, ViewPager viewP...
method onPageSelected (line 105) | @Override
FILE: app/src/main/java/com/termux/app/terminal/io/TermuxTerminalExtraKeys.java
class TermuxTerminalExtraKeys (line 23) | public class TermuxTerminalExtraKeys extends TerminalExtraKeys {
method TermuxTerminalExtraKeys (line 33) | public TermuxTerminalExtraKeys(TermuxActivity activity, @NonNull Termi...
method setExtraKeys (line 49) | private void setExtraKeys() {
method getExtraKeysInfo (line 80) | public ExtraKeysInfo getExtraKeysInfo() {
method onTerminalExtraKeyButtonClick (line 84) | @SuppressLint("RtlHardcoded")
FILE: app/src/main/java/com/termux/filepicker/TermuxDocumentsProvider.java
class TermuxDocumentsProvider (line 34) | public class TermuxDocumentsProvider extends DocumentsProvider {
method queryRoots (line 65) | @Override
method queryDocument (line 82) | @Override
method queryChildDocuments (line 89) | @Override
method openDocument (line 99) | @Override
method openDocumentThumbnail (line 106) | @Override
method onCreate (line 113) | @Override
method createDocument (line 118) | @Override
method deleteDocument (line 141) | @Override
method getDocumentType (line 149) | @Override
method querySearchDocuments (line 155) | @Override
method isChildDocument (line 192) | @Override
method getDocIdForFile (line 203) | private static String getDocIdForFile(File file) {
method getFileForDocId (line 210) | private static File getFileForDocId(String docId) throws FileNotFoundE...
method getMimeType (line 216) | private static String getMimeType(File file) {
method includeFile (line 238) | private void includeFile(MatrixCursor result, String docId, File file)
FILE: app/src/test/java/com/termux/app/TermuxActivityTest.java
class TermuxActivityTest (line 11) | public class TermuxActivityTest {
method assertUrlsAre (line 13) | private void assertUrlsAre(String text, String... urls) {
method testExtractUrls (line 19) | @Test
FILE: app/src/test/java/com/termux/app/api/file/FileReceiverActivityTest.java
class FileReceiverActivityTest (line 13) | @RunWith(RobolectricTestRunner.class)
method testIsSharedTextAnUrl (line 16) | @Test
FILE: terminal-emulator/src/main/java/com/termux/terminal/ByteQueue.java
class ByteQueue (line 4) | final class ByteQueue {
method ByteQueue (line 11) | public ByteQueue(int size) {
method close (line 15) | public synchronized void close() {
method read (line 20) | public synchronized int read(byte[] buffer, boolean block) {
method write (line 59) | public boolean write(byte[] buffer, int offset, int lengthToWrite) {
FILE: terminal-emulator/src/main/java/com/termux/terminal/JNI.java
class JNI (line 6) | final class JNI {
method createSubprocess (line 26) | public static native int createSubprocess(String cmd, String cwd, Stri...
method setPtyWindowSize (line 29) | public static native void setPtyWindowSize(int fd, int rows, int cols,...
method waitFor (line 36) | public static native int waitFor(int processId);
method close (line 39) | public static native void close(int fileDescriptor);
FILE: terminal-emulator/src/main/java/com/termux/terminal/KeyHandler.java
class KeyHandler (line 57) | public final class KeyHandler {
method getCodeFromTermcap (line 132) | static String getCodeFromTermcap(String termcap, boolean cursorKeysApp...
method getCode (line 156) | public static String getCode(int keyCode, int keyMode, boolean cursorA...
method transformForModifiers (line 344) | private static String transformForModifiers(String start, int keymod, ...
FILE: terminal-emulator/src/main/java/com/termux/terminal/Logger.java
class Logger (line 9) | public class Logger {
method logError (line 11) | public static void logError(TerminalSessionClient client, String logTa...
method logWarn (line 18) | public static void logWarn(TerminalSessionClient client, String logTag...
method logInfo (line 25) | public static void logInfo(TerminalSessionClient client, String logTag...
method logDebug (line 32) | public static void logDebug(TerminalSessionClient client, String logTa...
method logVerbose (line 39) | public static void logVerbose(TerminalSessionClient client, String log...
method logStackTraceWithMessage (line 46) | public static void logStackTraceWithMessage(TerminalSessionClient clie...
method getMessageAndStackTraceString (line 50) | public static String getMessageAndStackTraceString(String message, Thr...
method getStackTraceString (line 61) | public static String getStackTraceString(Throwable throwable) {
FILE: terminal-emulator/src/main/java/com/termux/terminal/TerminalBuffer.java
class TerminalBuffer (line 11) | public final class TerminalBuffer {
method TerminalBuffer (line 31) | public TerminalBuffer(int columns, int totalRows, int screenRows) {
method getTranscriptText (line 40) | public String getTranscriptText() {
method getTranscriptTextWithoutJoinedLines (line 44) | public String getTranscriptTextWithoutJoinedLines() {
method getTranscriptTextWithFullLinesJoined (line 48) | public String getTranscriptTextWithFullLinesJoined() {
method getSelectedText (line 52) | public String getSelectedText(int selX1, int selY1, int selX2, int sel...
method getSelectedText (line 56) | public String getSelectedText(int selX1, int selY1, int selX2, int sel...
method getSelectedText (line 60) | public String getSelectedText(int selX1, int selY1, int selX2, int sel...
method getWordAtLocation (line 108) | public String getWordAtLocation(int x, int y) {
method getActiveTranscriptRows (line 147) | public int getActiveTranscriptRows() {
method getActiveRows (line 151) | public int getActiveRows() {
method externalToInternalRow (line 176) | public int externalToInternalRow(int externalRow) {
method setLineWrap (line 183) | public void setLineWrap(int row) {
method getLineWrap (line 187) | public boolean getLineWrap(int row) {
method clearLineWrap (line 191) | public void clearLineWrap(int row) {
method resize (line 203) | public void resize(int newColumns, int newRows, int newTotalRows, int[...
method blockCopyLinesDown (line 363) | private void blockCopyLinesDown(int srcInternal, int len) {
method scrollDownOneLine (line 384) | public void scrollDownOneLine(int topMargin, int bottomMargin, long st...
method blockCopy (line 420) | public void blockCopy(int sx, int sy, int w, int h, int dx, int dy) {
method blockSet (line 437) | public void blockSet(int sx, int sy, int w, int h, int val, long style) {
method allocateFullLineIfNecessary (line 447) | public TerminalRow allocateFullLineIfNecessary(int row) {
method setChar (line 451) | public void setChar(int column, int row, int codePoint, long style) {
method getStyleAt (line 458) | public long getStyleAt(int externalRow, int column) {
method setOrClearEffect (line 463) | public void setOrClearEffect(int bits, boolean setOrClear, boolean rev...
method clearTranscript (line 487) | public void clearTranscript() {
FILE: terminal-emulator/src/main/java/com/termux/terminal/TerminalColorScheme.java
class TerminalColorScheme (line 12) | public final class TerminalColorScheme {
method TerminalColorScheme (line 64) | public TerminalColorScheme() {
method reset (line 68) | private void reset() {
method updateWith (line 72) | public void updateWith(Properties props) {
method setCursorColorForBackground (line 115) | public void setCursorColorForBackground() {
FILE: terminal-emulator/src/main/java/com/termux/terminal/TerminalColors.java
class TerminalColors (line 6) | public final class TerminalColors {
method TerminalColors (line 18) | public TerminalColors() {
method reset (line 23) | public void reset(int index) {
method reset (line 28) | public void reset() {
method parse (line 37) | static int parse(String c) {
method tryParseColor (line 73) | public void tryParseColor(int intoIndex, String textParameter) {
method getPerceivedBrightnessOfColor (line 87) | public static int getPerceivedBrightnessOfColor(int color) {
FILE: terminal-emulator/src/main/java/com/termux/terminal/TerminalEmulator.java
class TerminalEmulator (line 29) | public final class TerminalEmulator {
method isDecsetInternalBitSet (line 276) | private boolean isDecsetInternalBitSet(int bit) {
method setDecsetinternalBit (line 280) | private void setDecsetinternalBit(int internalBit, boolean set) {
method mapDecSetBitToInternalBit (line 296) | static int mapDecSetBitToInternalBit(int decsetBit) {
method TerminalEmulator (line 328) | public TerminalEmulator(TerminalOutput session, int columns, int rows,...
method updateTerminalSessionClient (line 341) | public void updateTerminalSessionClient(TerminalSessionClient client) {
method getScreen (line 347) | public TerminalBuffer getScreen() {
method isAlternateBufferActive (line 351) | public boolean isAlternateBufferActive() {
method getTerminalTranscriptRows (line 355) | private int getTerminalTranscriptRows(Integer transcriptRows) {
method sendMouseEvent (line 365) | public void sendMouseEvent(int mouseButton, int column, int row, boole...
method resize (line 386) | public void resize(int columns, int rows, int cellWidthPixels, int cel...
method resizeScreen (line 416) | private void resizeScreen() {
method getCursorRow (line 424) | public int getCursorRow() {
method getCursorCol (line 428) | public int getCursorCol() {
method getCursorStyle (line 433) | public int getCursorStyle() {
method setCursorStyle (line 438) | public void setCursorStyle() {
method isReverseVideo (line 450) | public boolean isReverseVideo() {
method isCursorEnabled (line 456) | public boolean isCursorEnabled() {
method shouldCursorBeVisible (line 459) | public boolean shouldCursorBeVisible() {
method setCursorBlinkingEnabled (line 466) | public void setCursorBlinkingEnabled(boolean cursorBlinkingEnabled) {
method setCursorBlinkState (line 470) | public void setCursorBlinkState(boolean cursorBlinkState) {
method isKeypadApplicationMode (line 476) | public boolean isKeypadApplicationMode() {
method isCursorKeysApplicationMode (line 480) | public boolean isCursorKeysApplicationMode() {
method isMouseTrackingActive (line 485) | public boolean isMouseTrackingActive() {
method setDefaultTabStops (line 489) | private void setDefaultTabStops() {
method append (line 500) | public void append(byte[] buffer, int length) {
method processByte (line 505) | private void processByte(byte byteToProcess) {
method processCodePoint (line 570) | public void processCodePoint(int b) {
method doDeviceControl (line 918) | private void doDeviceControl(int b) {
method doApc (line 1043) | private void doApc(int b) {
method doApcEscape (line 1053) | private void doApcEscape(int b) {
method nextTabStop (line 1064) | private int nextTabStop(int numTabs) {
method doCsiUnsupportedParameterOrIntermediateByte (line 1084) | private void doCsiUnsupportedParameterOrIntermediateByte(int b) {
method doCsiQuestionMark (line 1102) | private void doCsiQuestionMark(int b) {
method doDecSetOrReset (line 1186) | public void doDecSetOrReset(boolean setting, int externalBit) {
method doCsiBiggerThan (line 1286) | private void doCsiBiggerThan(int b) {
method startEscapeSequence (line 1366) | private void startEscapeSequence() {
method doLinefeed (line 1373) | private void doLinefeed() {
method continueSequence (line 1390) | private void continueSequence(int state) {
method doEscPound (line 1395) | private void doEscPound(int b) {
method doEsc (line 1407) | private void doEsc(int b) {
method saveCursor (line 1501) | private void saveCursor() {
method restoreCursor (line 1515) | private void restoreCursor() {
method doCsi (line 1529) | private void doCsi(int b) {
method selectGraphicRendition (line 1856) | private void selectGraphicRendition() {
method doOsc (line 1984) | private void doOsc(int b) {
method doOscEsc (line 1998) | private void doOscEsc(int b) {
method doOscSetTextParameters (line 2014) | private void doOscSetTextParameters(String bellOrStringTerminator) {
method blockClear (line 2158) | private void blockClear(int sx, int sy, int w) {
method blockClear (line 2162) | private void blockClear(int sx, int sy, int w, int h) {
method getStyle (line 2166) | private long getStyle() {
method doSetMode (line 2171) | private void doSetMode(boolean newValue) {
method setCursorPosition (line 2195) | private void setCursorPosition(int x, int y) {
method scrollDownOneLine (line 2206) | private void scrollDownOneLine() {
method parseArg (line 2238) | private void parseArg(int b) {
method getArg0 (line 2269) | private int getArg0(int defaultValue) {
method getArg1 (line 2273) | private int getArg1(int defaultValue) {
method getArg (line 2277) | private int getArg(int index, int defaultValue, boolean treatZeroAsDef...
method collectOSCArgs (line 2285) | private void collectOSCArgs(int b) {
method unimplementedSequence (line 2294) | private void unimplementedSequence(int b) {
method unknownSequence (line 2299) | private void unknownSequence(int b) {
method unknownParameter (line 2304) | private void unknownParameter(int parameter) {
method logError (line 2309) | private void logError(String errorType) {
method finishSequenceAndLogError (line 2334) | private void finishSequenceAndLogError(String error) {
method finishSequence (line 2339) | private void finishSequence() {
method emitCodePoint (line 2348) | private void emitCodePoint(int codePoint) {
method setCursorRow (line 2498) | private void setCursorRow(int row) {
method setCursorCol (line 2503) | private void setCursorCol(int col) {
method setCursorColRespectingOriginMode (line 2509) | private void setCursorColRespectingOriginMode(int col) {
method setCursorRowCol (line 2514) | private void setCursorRowCol(int row, int col) {
method getScrollCounter (line 2520) | public int getScrollCounter() {
method clearScrollCounter (line 2524) | public void clearScrollCounter() {
method isAutoScrollDisabled (line 2528) | public boolean isAutoScrollDisabled() {
method toggleAutoScrollDisabled (line 2532) | public void toggleAutoScrollDisabled() {
method reset (line 2538) | public void reset() {
method getSelectedText (line 2570) | public String getSelectedText(int x1, int y1, int x2, int y2) {
method getTitle (line 2575) | public String getTitle() {
method setTitle (line 2580) | private void setTitle(String newTitle) {
method paste (line 2589) | public void paste(String text) {
class SavedScreenState (line 2603) | static final class SavedScreenState {
method toString (line 2611) | @Override
FILE: terminal-emulator/src/main/java/com/termux/terminal/TerminalOutput.java
class TerminalOutput (line 6) | public abstract class TerminalOutput {
method write (line 9) | public final void write(String data) {
method write (line 16) | public abstract void write(byte[] data, int offset, int count);
method titleChanged (line 19) | public abstract void titleChanged(String oldTitle, String newTitle);
method onCopyTextToClipboard (line 22) | public abstract void onCopyTextToClipboard(String text);
method onPasteTextFromClipboard (line 25) | public abstract void onPasteTextFromClipboard();
method onBell (line 28) | public abstract void onBell();
method onColorsChanged (line 30) | public abstract void onColorsChanged();
FILE: terminal-emulator/src/main/java/com/termux/terminal/TerminalRow.java
class TerminalRow (line 10) | public final class TerminalRow {
method TerminalRow (line 54) | public TerminalRow(int columns, long style) {
method copyInterval (line 62) | public void copyInterval(TerminalRow line, int sourceX1, int sourceX2,...
method getSpaceUsed (line 87) | public int getSpaceUsed() {
method findStartOfColumn (line 92) | public int findStartOfColumn(int column) {
method wideDisplayCharacterStartingAt (line 130) | private boolean wideDisplayCharacterStartingAt(int column) {
method clear (line 144) | public void clear(long style) {
method setChar (line 152) | public void setChar(int columnToSet, int codePoint, long style) {
method isBlank (line 273) | boolean isBlank() {
method getStyle (line 279) | public final long getStyle(int column) {
FILE: terminal-emulator/src/main/java/com/termux/terminal/TerminalSession.java
class TerminalSession (line 31) | public final class TerminalSession extends TerminalOutput {
method TerminalSession (line 82) | public TerminalSession(String shellPath, String cwd, String[] args, St...
method updateTerminalSessionClient (line 95) | public void updateTerminalSessionClient(TerminalSessionClient client) {
method updateSize (line 103) | public void updateSize(int columns, int rows, int cellWidthPixels, int...
method getTitle (line 113) | public String getTitle() {
method initializeEmulator (line 123) | public void initializeEmulator(int columns, int rows, int cellWidthPix...
method write (line 177) | @Override
method writeCodePoint (line 183) | public void writeCodePoint(boolean prependEscape, int codePoint) {
method getEmulator (line 219) | public TerminalEmulator getEmulator() {
method notifyScreenUpdate (line 224) | protected void notifyScreenUpdate() {
method reset (line 229) | public void reset() {
method finishIfRunning (line 235) | public void finishIfRunning() {
method cleanupResources (line 246) | void cleanupResources(int exitStatus) {
method titleChanged (line 258) | @Override
method isRunning (line 263) | public synchronized boolean isRunning() {
method getExitStatus (line 268) | public synchronized int getExitStatus() {
method onCopyTextToClipboard (line 272) | @Override
method onPasteTextFromClipboard (line 277) | @Override
method onBell (line 282) | @Override
method onColorsChanged (line 287) | @Override
method getPid (line 292) | public int getPid() {
method getCwd (line 297) | public String getCwd() {
method wrapFileDescriptor (line 317) | private static FileDescriptor wrapFileDescriptor(int fileDescriptor, T...
class MainThreadHandler (line 336) | @SuppressLint("HandlerLeak")
method handleMessage (line 341) | @Override
FILE: terminal-emulator/src/main/java/com/termux/terminal/TerminalSessionClient.java
type TerminalSessionClient (line 11) | public interface TerminalSessionClient {
method onTextChanged (line 13) | void onTextChanged(@NonNull TerminalSession changedSession);
method onTitleChanged (line 15) | void onTitleChanged(@NonNull TerminalSession changedSession);
method onSessionFinished (line 17) | void onSessionFinished(@NonNull TerminalSession finishedSession);
method onCopyTextToClipboard (line 19) | void onCopyTextToClipboard(@NonNull TerminalSession session, String te...
method onPasteTextFromClipboard (line 21) | void onPasteTextFromClipboard(@Nullable TerminalSession session);
method onBell (line 23) | void onBell(@NonNull TerminalSession session);
method onColorsChanged (line 25) | void onColorsChanged(@NonNull TerminalSession session);
method onTerminalCursorStateChange (line 27) | void onTerminalCursorStateChange(boolean state);
method setTerminalShellPid (line 29) | void setTerminalShellPid(@NonNull TerminalSession session, int pid);
method getTerminalCursorStyle (line 33) | Integer getTerminalCursorStyle();
method logError (line 37) | void logError(String tag, String message);
method logWarn (line 39) | void logWarn(String tag, String message);
method logInfo (line 41) | void logInfo(String tag, String message);
method logDebug (line 43) | void logDebug(String tag, String message);
method logVerbose (line 45) | void logVerbose(String tag, String message);
method logStackTraceWithMessage (line 47) | void logStackTraceWithMessage(String tag, String message, Exception e);
method logStackTrace (line 49) | void logStackTrace(String tag, Exception e);
FILE: terminal-emulator/src/main/java/com/termux/terminal/TextStyle.java
class TextStyle (line 15) | public final class TextStyle {
method encode (line 49) | static long encode(int foreColor, int backColor, int effect) {
method decodeForeColor (line 69) | public static int decodeForeColor(long style) {
method decodeBackColor (line 78) | public static int decodeBackColor(long style) {
method decodeEffect (line 86) | public static int decodeEffect(long style) {
FILE: terminal-emulator/src/main/java/com/termux/terminal/WcWidth.java
class WcWidth (line 14) | public final class WcWidth {
method intable (line 493) | private static boolean intable(int[][] table, int c) {
method width (line 514) | public static int width(int ucs) {
method width (line 536) | public static int width(char[] chars, int index) {
method zeroWidthCharsCount (line 545) | public static int zeroWidthCharsCount(char[] chars, int start, int end) {
FILE: terminal-emulator/src/main/jni/termux.c
function throw_runtime_exception (line 18) | static int throw_runtime_exception(JNIEnv* env, char const* message)
function create_subprocess (line 25) | static int create_subprocess(JNIEnv* env,
function JNICALL (line 117) | JNICALL Java_com_termux_terminal_JNI_createSubprocess(
function JNICALL (line 185) | JNICALL Java_com_termux_terminal_JNI_setPtyWindowSize(JNIEnv* TERMUX_UNU...
function JNICALL (line 191) | JNICALL Java_com_termux_terminal_JNI_setPtyUTF8Mode(JNIEnv* TERMUX_UNUSE...
function JNICALL (line 201) | JNICALL Java_com_termux_terminal_JNI_waitFor(JNIEnv* TERMUX_UNUSED(env),...
function JNICALL (line 215) | JNICALL Java_com_termux_terminal_JNI_close(JNIEnv* TERMUX_UNUSED(env), j...
FILE: terminal-emulator/src/test/java/com/termux/terminal/ApcTest.java
class ApcTest (line 3) | public class ApcTest extends TerminalTestCase {
method testApcConsumed (line 5) | public void testApcConsumed() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/ByteQueueTest.java
class ByteQueueTest (line 5) | public class ByteQueueTest extends TestCase {
method assertArrayEquals (line 7) | private static void assertArrayEquals(byte[] expected, byte[] actual) {
method testCompleteWrites (line 18) | public void testCompleteWrites() throws Exception {
method testQueueWraparound (line 31) | public void testQueueWraparound() throws Exception {
method testWriteNotesClosing (line 43) | public void testWriteNotesClosing() throws Exception {
method testReadNonBlocking (line 49) | public void testReadNonBlocking() throws Exception {
FILE: terminal-emulator/src/test/java/com/termux/terminal/ControlSequenceIntroducerTest.java
class ControlSequenceIntroducerTest (line 6) | public class ControlSequenceIntroducerTest extends TerminalTestCase {
method testCsiT (line 9) | public void testCsiT() {
method testCsiS (line 18) | public void testCsiS() {
method testCsiX (line 26) | public void testCsiX() {
method testCsiSGRParameters (line 35) | public void testCsiSGRParameters() {
method testRepeat (line 41) | public void testRepeat() {
method testCsi3J (line 52) | public void testCsi3J() {
method testReportPixelSize (line 67) | public void testReportPixelSize() {
method testUnderlineVariants (line 103) | public void testUnderlineVariants() {
method testManyParameters (line 117) | public void testManyParameters() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/CursorAndScreenTest.java
class CursorAndScreenTest (line 5) | public class CursorAndScreenTest extends TerminalTestCase {
method testDeleteLinesKeepsStyles (line 7) | public void testDeleteLinesKeepsStyles() {
method testDeleteCharacters (line 53) | public void testDeleteCharacters() {
method testInsertMode (line 76) | public void testInsertMode() {
method testCursorHorizontalPositionAbsolute (line 101) | public void testCursorHorizontalPositionAbsolute() {
method testCursorForward (line 111) | public void testCursorForward() {
method testCursorBack (line 120) | public void testCursorBack() {
method testCursorUp (line 130) | public void testCursorUp() {
method testCursorDown (line 138) | public void testCursorDown() {
method testReportCursorPosition (line 146) | public void testReportCursorPosition() {
method DISABLED_testHorizontalTabColorsBackground (line 167) | public void DISABLED_testHorizontalTabColorsBackground() {
method testClearingOfAutowrap (line 182) | public void testClearingOfAutowrap() {
method testBackspaceAcrossWrappedLines (line 217) | public void testBackspaceAcrossWrappedLines() {
method testCursorSaveRestoreLocation (line 226) | public void testCursorSaveRestoreLocation() {
method testCursorSaveRestoreTextStyle (line 235) | public void testCursorSaveRestoreTextStyle() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/DecSetTest.java
class DecSetTest (line 16) | public class DecSetTest extends TerminalTestCase {
method testEnableDisableCursor (line 19) | public void testEnableDisableCursor() {
method testBracketedPasteMode (line 39) | public void testBracketedPasteMode() {
method testWrapAroundMode (line 68) | public void testWrapAroundMode() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/DeviceControlStringTest.java
class DeviceControlStringTest (line 6) | public class DeviceControlStringTest extends TerminalTestCase {
method hexEncode (line 8) | private static String hexEncode(String s) {
method assertCapabilityResponse (line 15) | private void assertCapabilityResponse(String cap, String expectedRespo...
method testReportColorsAndName (line 20) | public void testReportColorsAndName() {
method testReportKeys (line 37) | public void testReportKeys() {
method testReallyLongDeviceControlString (line 42) | public void testReallyLongDeviceControlString() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/HistoryTest.java
class HistoryTest (line 4) | public class HistoryTest extends TerminalTestCase {
method testHistory (line 6) | public void testHistory() {
method testHistoryWithScrollRegion (line 21) | public void testHistoryWithScrollRegion() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/KeyHandlerTest.java
class KeyHandlerTest (line 7) | public class KeyHandlerTest extends TestCase {
method stringToHex (line 9) | private static String stringToHex(String s) {
method assertKeysEquals (line 22) | private static void assertKeysEquals(String expected, String actual) {
method testTermCaps (line 29) | public void testTermCaps() {
method testKeyCodes (line 106) | public void testKeyCodes() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/OperatingSystemControlTest.java
class OperatingSystemControlTest (line 10) | public class OperatingSystemControlTest extends TerminalTestCase {
method testSetTitle (line 12) | public void testSetTitle() throws Exception {
method testTitleStack (line 70) | public void testTitleStack() throws Exception {
method testSetColor (line 89) | public void testSetColor() throws Exception {
method assertIndexColorsMatch (line 103) | void assertIndexColorsMatch(int[] expected) {
method testResetColor (line 108) | public void testResetColor() throws Exception {
method disabledTestSetClipboard (line 140) | public void disabledTestSetClipboard() {
method testResettingTerminalResetsColor (line 145) | public void testResettingTerminalResetsColor() throws Exception {
method testSettingDynamicColors (line 154) | public void testSettingDynamicColors() {
method testReportSpecialColors (line 184) | public void testReportSpecialColors() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/RectangularAreasTest.java
class RectangularAreasTest (line 3) | public class RectangularAreasTest extends TerminalTestCase {
method testFillRectangularArea (line 6) | public void testFillRectangularArea() {
method testEraseRectangularArea (line 16) | public void testEraseRectangularArea() {
method testSelectiveEraseInDisplay (line 28) | public void testSelectiveEraseInDisplay() {
method testSelectiveEraseInLine (line 37) | public void testSelectiveEraseInLine() {
method testSelectiveEraseInRectangle (line 49) | public void testSelectiveEraseInRectangle() {
method testRectangularCopy (line 64) | public void testRectangularCopy() {
method testChangeAttributesInRectangularArea (line 83) | public void testChangeAttributesInRectangularArea() {
method testReverseAttributesInRectangularArea (line 95) | public void testReverseAttributesInRectangularArea() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/ResizeTest.java
class ResizeTest (line 3) | public class ResizeTest extends TerminalTestCase {
method testResizeWhenHasHistory (line 5) | public void testResizeWhenHasHistory() {
method testResizeWhenInAltBuffer (line 12) | public void testResizeWhenInAltBuffer() {
method testShrinkingInAltBuffer (line 30) | public void testShrinkingInAltBuffer() {
method testResizeAfterNewlineWhenInAltBuffer (line 38) | public void testResizeAfterNewlineWhenInAltBuffer() {
method testResizeAfterHistoryWraparound (line 57) | public void testResizeAfterHistoryWraparound() {
method testVerticalResize (line 83) | public void testVerticalResize() {
method testHorizontalResize (line 126) | public void testHorizontalResize() {
method testLineWrap (line 149) | public void testLineWrap() {
method testCursorPositionWhenShrinking (line 166) | public void testCursorPositionWhenShrinking() {
method testResizeWithCombiningCharInLastColumn (line 173) | public void testResizeWithCombiningCharInLastColumn() {
method testResizeWithLineWrappingContinuing (line 184) | public void testResizeWithLineWrappingContinuing() {
method testResizeWithWideChars (line 191) | public void testResizeWithWideChars() {
method testResizeWithMoreWideChars (line 200) | public void testResizeWithMoreWideChars() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/ScreenBufferTest.java
class ScreenBufferTest (line 3) | public class ScreenBufferTest extends TerminalTestCase {
method testBasics (line 5) | public void testBasics() {
method testBlockSet (line 19) | public void testBlockSet() {
method testGetSelectedText (line 27) | public void testGetSelectedText() {
method testGetSelectedTextJoinFullLines (line 41) | public void testGetSelectedTextJoinFullLines() {
method testGetWordAtLocation (line 49) | public void testGetWordAtLocation() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/ScrollRegionTest.java
class ScrollRegionTest (line 8) | public class ScrollRegionTest extends TerminalTestCase {
method testScrollRegionTop (line 10) | public void testScrollRegionTop() {
method testScrollRegionBottom (line 19) | public void testScrollRegionBottom() {
method testScrollRegionResetWithOriginMode (line 28) | public void testScrollRegionResetWithOriginMode() {
method testScrollRegionLeft (line 35) | public void testScrollRegionLeft() {
method testScrollRegionRight (line 42) | public void testScrollRegionRight() {
method testScrollRegionOnAllSides (line 49) | public void testScrollRegionOnAllSides() {
method testDECCOLMResetsScrollMargin (line 59) | public void testDECCOLMResetsScrollMargin() {
method testScrollOutsideVerticalRegion (line 66) | public void testScrollOutsideVerticalRegion() {
method testNELRespectsLeftMargin (line 71) | public void testNELRespectsLeftMargin() {
method testRiRespectsLeftMargin (line 78) | public void testRiRespectsLeftMargin() {
method testSdRespectsLeftMargin (line 83) | public void testSdRespectsLeftMargin() {
method testBackwardIndex (line 88) | public void testBackwardIndex() {
method testForwardIndex (line 98) | public void testForwardIndex() {
method testScrollDownWithScrollRegion (line 107) | public void testScrollDownWithScrollRegion() {
method testScrollDownBelowScrollRegion (line 112) | public void testScrollDownBelowScrollRegion() {
method testScrollRegionDoesNotLimitCursorMovement (line 121) | public void testScrollRegionDoesNotLimitCursorMovement() {
method testClearingWhenScrollingWithMargins (line 144) | public void testClearingWhenScrollingWithMargins() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/TerminalRowTest.java
class TerminalRowTest (line 8) | public class TerminalRowTest extends TestCase {
method setUp (line 28) | @Override
method assertLineStartsWith (line 34) | private void assertLineStartsWith(int... codePoints) {
method assertColumnCharIndicesStartsWith (line 46) | private void assertColumnCharIndicesStartsWith(int... indices) {
method testSimpleDiaresis (line 54) | public void testSimpleDiaresis() {
method testStaticConstants (line 62) | public void testStaticConstants() {
method testOneColumn (line 82) | public void testOneColumn() {
method testAscii (line 88) | public void testAscii() {
method testUnicode (line 117) | public void testUnicode() {
method testDoubleWidth (line 146) | public void testDoubleWidth() {
method testDoubleWidthSurrogage (line 167) | public void testDoubleWidthSurrogage() {
method testReplacementChar (line 187) | public void testReplacementChar() {
method testSurrogateCharsWithNormalDisplayWidth (line 193) | public void testSurrogateCharsWithNormalDisplayWidth() {
method testOverwritingDoubleDisplayWidthWithNormalDisplayWidth (line 251) | public void testOverwritingDoubleDisplayWidthWithNormalDisplayWidth() {
method testOverwritingDoubleDisplayWidthWithSelf (line 286) | public void testOverwritingDoubleDisplayWidthWithSelf() {
method testNormalCharsWithDoubleDisplayWidth (line 296) | public void testNormalCharsWithDoubleDisplayWidth() {
method testNormalCharsWithDoubleDisplayWidthOverlapping (line 333) | public void testNormalCharsWithDoubleDisplayWidthOverlapping() {
method testCrashATE145 (line 366) | public void testCrashATE145() {
method testNormalization (line 407) | public void testNormalization() {
method testInsertWideAtLastColumn (line 419) | public void testInsertWideAtLastColumn() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/TerminalTest.java
class TerminalTest (line 5) | public class TerminalTest extends TerminalTestCase {
method testCursorPositioning (line 7) | public void testCursorPositioning() throws Exception {
method testScreen (line 12) | public void testScreen() throws UnsupportedEncodingException {
method testScrollDownInAltBuffer (line 30) | public void testScrollDownInAltBuffer() {
method testMouseClick (line 43) | public void testMouseClick() throws Exception {
method testNormalization (line 68) | public void testNormalization() throws UnsupportedEncodingException {
method testReportTerminalSize (line 80) | public void testReportTerminalSize() throws Exception {
method testDeviceStatusReport (line 92) | public void testDeviceStatusReport() throws Exception {
method testSetCursorStyle (line 104) | public void testSetCursorStyle() throws Exception {
method testPaste (line 125) | public void testPaste() {
method testSelectGraphics (line 139) | public void testSelectGraphics() {
method selectGraphicsTestRun (line 144) | public void selectGraphicsTestRun(char separator) {
method testBackgroundColorErase (line 250) | public void testBackgroundColorErase() {
method testParseColor (line 295) | public void testParseColor() {
method testLineDrawing (line 311) | public void testLineDrawing() {
method testSoftTerminalReset (line 318) | public void testSoftTerminalReset() {
method testBel (line 325) | public void testBel() {
method testAutomargins (line 338) | public void testAutomargins() throws UnsupportedEncodingException {
method testTab (line 345) | public void testTab() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/TerminalTestCase.java
class TerminalTestCase (line 14) | public abstract class TerminalTestCase extends TestCase {
class MockTerminalOutput (line 19) | public static class MockTerminalOutput extends TerminalOutput {
method write (line 26) | @Override
method getOutputAndClear (line 31) | public String getOutputAndClear() {
method titleChanged (line 37) | @Override
method onCopyTextToClipboard (line 42) | @Override
method onPasteTextFromClipboard (line 47) | @Override
method onBell (line 51) | @Override
method onColorsChanged (line 56) | @Override
class ChangedTitle (line 65) | public static final class ChangedTitle {
method ChangedTitle (line 69) | public ChangedTitle(String oldTitle, String newTitle) {
method equals (line 74) | @Override
method hashCode (line 81) | @Override
method toString (line 86) | @Override
method enterString (line 93) | public TerminalTestCase enterString(String s) {
method assertEnteringStringGivesResponse (line 100) | public void assertEnteringStringGivesResponse(String input, String exp...
method setUp (line 106) | @Override
method withTerminalSized (line 112) | protected TerminalTestCase withTerminalSized(int columns, int rows) {
method assertHistoryStartsWith (line 118) | public void assertHistoryStartsWith(String... rows) {
class LineWrapper (line 126) | private static final class LineWrapper {
method LineWrapper (line 129) | public LineWrapper(TerminalRow line) {
method hashCode (line 133) | @Override
method equals (line 138) | @Override
method assertInvariants (line 144) | protected TerminalTestCase assertInvariants() {
method assertLineIs (line 183) | protected void assertLineIs(int line, String expected) {
method assertLinesAre (line 195) | public TerminalTestCase assertLinesAre(String... lines) {
method resize (line 206) | public TerminalTestCase resize(int cols, int rows) {
method assertLineWraps (line 212) | public TerminalTestCase assertLineWraps(boolean... lines) {
method assertLineStartsWith (line 218) | protected TerminalTestCase assertLineStartsWith(int line, int... codeP...
method placeCursorAndAssert (line 231) | protected TerminalTestCase placeCursorAndAssert(int row, int col) {
method assertCursorAt (line 238) | public TerminalTestCase assertCursorAt(int row, int col) {
method getStyleAt (line 247) | public long getStyleAt(int externalRow, int column) {
class EffectLine (line 251) | public static class EffectLine {
method EffectLine (line 254) | public EffectLine(int[] styles) {
method effectLine (line 259) | protected EffectLine effectLine(int... bits) {
method assertEffectAttributesSet (line 263) | public TerminalTestCase assertEffectAttributesSet(EffectLine... lines) {
method assertForegroundIndices (line 277) | public TerminalTestCase assertForegroundIndices(EffectLine... lines) {
method describeStyle (line 291) | private static String describeStyle(int styleBits) {
method assertForegroundColorAt (line 302) | public void assertForegroundColorAt(int externalRow, int column, int c...
method assertBackgroundColorAt (line 307) | public void assertBackgroundColorAt(int externalRow, int column, int c...
method assertColor (line 312) | public TerminalTestCase assertColor(int colorIndex, int expected) {
FILE: terminal-emulator/src/test/java/com/termux/terminal/TextStyleTest.java
class TextStyleTest (line 5) | public class TextStyleTest extends TestCase {
method testEncodingSingle (line 12) | public void testEncodingSingle() {
method testEncoding24Bit (line 25) | public void testEncoding24Bit() {
method testEncodingCombinations (line 41) | public void testEncodingCombinations() {
method testEncodingStrikeThrough (line 50) | public void testEncodingStrikeThrough() {
method testEncodingProtected (line 56) | public void testEncodingProtected() {
FILE: terminal-emulator/src/test/java/com/termux/terminal/UnicodeInputTest.java
class UnicodeInputTest (line 5) | public class UnicodeInputTest extends TerminalTestCase {
method testIllFormedUtf8SuccessorByteNotConsumed (line 7) | public void testIllFormedUtf8SuccessorByteNotConsumed() throws Excepti...
method testUnassignedCodePoint (line 58) | public void testUnassignedCodePoint() throws UnsupportedEncodingExcept...
method testStuff (line 68) | public void testStuff() {
method testSimpleCombining (line 77) | public void testSimpleCombining() throws Exception {
method testCombiningCharacterInFirstColumn (line 81) | public void testCombiningCharacterInFirstColumn() throws Exception {
method testCombiningCharacterInLastColumn (line 89) | public void testCombiningCharacterInLastColumn() throws Exception {
method testWideCharacterInLastColumn (line 95) | public void testWideCharacterInLastColumn() throws Exception {
method testWideCharacterDeletion (line 102) | public void testWideCharacterDeletion() throws Exception {
method testWideCharOverwriting (line 117) | public void testWideCharOverwriting() {
method testOverlongUtf8Encoding (line 121) | public void testOverlongUtf8Encoding() throws Exception {
method testWideCharacterWithoutWrapping (line 128) | public void testWideCharacterWithoutWrapping() throws Exception {
FILE: terminal-emulator/src/test/java/com/termux/terminal/WcWidthTest.java
class WcWidthTest (line 5) | public class WcWidthTest extends TestCase {
method assertWidthIs (line 7) | private static void assertWidthIs(int expectedWidth, int codePoint) {
method testPrintableAscii (line 12) | public void testPrintableAscii() {
method testSomeWidthOne (line 18) | public void testSomeWidthOne() {
method testSomeWide (line 25) | public void testSomeWide() {
method testSomeNonWide (line 41) | public void testSomeNonWide() {
method testCombining (line 46) | public void testCombining() {
method testWordJoiner (line 52) | public void testWordJoiner() {
method testSofthyphen (line 61) | public void testSofthyphen() {
method testHangul (line 71) | public void testHangul() {
method testEmojis (line 75) | public void testEmojis() {
FILE: terminal-view/src/main/java/com/termux/view/GestureAndScaleRecognizer.java
class GestureAndScaleRecognizer (line 9) | final class GestureAndScaleRecognizer {
type Listener (line 11) | public interface Listener {
method onSingleTapUp (line 12) | boolean onSingleTapUp(MotionEvent e);
method onDoubleTap (line 14) | boolean onDoubleTap(MotionEvent e);
method onScroll (line 16) | boolean onScroll(MotionEvent e2, float dx, float dy);
method onFling (line 18) | boolean onFling(MotionEvent e, float velocityX, float velocityY);
method onScale (line 20) | boolean onScale(float focusX, float focusY, float scale);
method onDown (line 22) | boolean onDown(float x, float y);
method onUp (line 24) | boolean onUp(MotionEvent e);
method onLongPress (line 26) | void onLongPress(MotionEvent e);
method GestureAndScaleRecognizer (line 34) | public GestureAndScaleRecognizer(Context context, Listener listener) {
method onTouchEvent (line 91) | public void onTouchEvent(MotionEvent event) {
method isInProgress (line 108) | public boolean isInProgress() {
FILE: terminal-view/src/main/java/com/termux/view/TerminalRenderer.java
class TerminalRenderer (line 19) | public final class TerminalRenderer {
method TerminalRenderer (line 36) | public TerminalRenderer(int textSize, Typeface typeface) {
method render (line 57) | public final void render(TerminalEmulator mEmulator, Canvas canvas, in...
method drawTextRun (line 159) | private void drawTextRun(Canvas canvas, char[] text, int[] palette, fl...
method getFontWidth (line 242) | public float getFontWidth() {
method getFontLineSpacing (line 246) | public int getFontLineSpacing() {
FILE: terminal-view/src/main/java/com/termux/view/TerminalView.java
class TerminalView (line 46) | public final class TerminalView extends View {
method TerminalView (line 136) | public TerminalView(Context context, AttributeSet attributes) { // NO_...
method setTerminalViewClient (line 270) | public void setTerminalViewClient(TerminalViewClient client) {
method setIsTerminalViewKeyLoggingEnabled (line 279) | public void setIsTerminalViewKeyLoggingEnabled(boolean value) {
method attachSession (line 290) | public boolean attachSession(TerminalSession session) {
method onCreateInputConnection (line 306) | @Override
method computeVerticalScrollRange (line 438) | @Override
method computeVerticalScrollExtent (line 443) | @Override
method computeVerticalScrollOffset (line 448) | @Override
method onScreenUpdated (line 453) | public void onScreenUpdated() {
method onScreenUpdated (line 457) | public void onScreenUpdated(boolean skipScrolling) {
method onContextMenuClosed (line 504) | public void onContextMenuClosed(Menu menu) {
method setTextSize (line 514) | public void setTextSize(int textSize) {
method setTypeface (line 519) | public void setTypeface(Typeface newTypeface) {
method onCheckIsTextEditor (line 525) | @Override
method isOpaque (line 530) | @Override
method getColumnAndRow (line 546) | public int[] getColumnAndRow(MotionEvent event, boolean relativeToScro...
method sendMouseEventCode (line 556) | void sendMouseEventCode(MotionEvent e, int button, boolean pressed) {
method doScroll (line 574) | void doScroll(MotionEvent event, int rowsDown) {
method onGenericMotionEvent (line 592) | @Override
method onTouchEvent (line 603) | @SuppressLint("ClickableViewAccessibility")
method onKeyPreIme (line 645) | @Override
method onKeyDown (line 768) | @Override
method inputCodePoint (line 846) | public void inputCodePoint(int eventSource, int codePoint, boolean con...
method handleKeyCode (line 912) | public boolean handleKeyCode(int keyCode, int keyMod) {
method handleKeyCodeAction (line 927) | public boolean handleKeyCodeAction(int keyCode, int keyMod) {
method onKeyUp (line 954) | @Override
method onSizeChanged (line 978) | @Override
method updateSize (line 984) | public void updateSize() {
method onDraw (line 1008) | @Override
method getCurrentSession (line 1026) | public TerminalSession getCurrentSession() {
method getText (line 1030) | private CharSequence getText() {
method getCursorX (line 1034) | public int getCursorX(float x) {
method getCursorY (line 1038) | public int getCursorY(float y) {
method getPointX (line 1042) | public int getPointX(int cx) {
method getPointY (line 1049) | public int getPointY(int cy) {
method getTopRow (line 1053) | public int getTopRow() {
method setTopRow (line 1057) | public void setTopRow(int mTopRow) {
method autofill (line 1066) | @RequiresApi(api = Build.VERSION_CODES.O)
method getAutofillType (line 1076) | @RequiresApi(api = Build.VERSION_CODES.O)
method getAutofillHints (line 1082) | @RequiresApi(api = Build.VERSION_CODES.O)
method getAutofillValue (line 1088) | @RequiresApi(api = Build.VERSION_CODES.O)
method getImportantForAutofill (line 1094) | @RequiresApi(api = Build.VERSION_CODES.O)
method resetAutoFill (line 1100) | @RequiresApi(api = Build.VERSION_CODES.O)
method getAutoFillManagerService (line 1108) | public AutofillManager getAutoFillManagerService() {
method isAutoFillEnabled (line 1121) | public boolean isAutoFillEnabled() {
method requestAutoFillUsername (line 1133) | public synchronized void requestAutoFillUsername() {
method requestAutoFillPassword (line 1139) | public synchronized void requestAutoFillPassword() {
method requestAutoFill (line 1145) | public synchronized void requestAutoFill(String[] autoFillHints) {
method cancelRequestAutoFill (line 1166) | public synchronized void cancelRequestAutoFill() {
method setTerminalCursorBlinkerRate (line 1195) | public synchronized boolean setTerminalCursorBlinkerRate(int blinkRate) {
method setTerminalCursorBlinkerState (line 1266) | public synchronized void setTerminalCursorBlinkerState(boolean start, ...
method stopTerminalCursorBlinker (line 1299) | private void stopTerminalCursorBlinker() {
class TerminalCursorBlinkerRunnable (line 1307) | private class TerminalCursorBlinkerRunnable implements Runnable {
method TerminalCursorBlinkerRunnable (line 1315) | public TerminalCursorBlinkerRunnable(TerminalEmulator emulator, int ...
method setEmulator (line 1320) | public void setEmulator(TerminalEmulator emulator) {
method run (line 1324) | public void run() {
method getTextSelectionCursorController (line 1348) | TextSelectionCursorController getTextSelectionCursorController() {
method showTextSelectionCursors (line 1361) | private void showTextSelectionCursors(MotionEvent event) {
method hideTextSelectionCursors (line 1365) | private boolean hideTextSelectionCursors() {
method renderTextSelection (line 1369) | private void renderTextSelection() {
method isSelectingText (line 1374) | public boolean isSelectingText() {
method getSelectedText (line 1383) | public String getSelectedText() {
method getStoredSelectedText (line 1391) | @Nullable
method unsetStoredSelectedText (line 1397) | public void unsetStoredSelectedText() {
method getTextSelectionActionMode (line 1401) | private ActionMode getTextSelectionActionMode() {
method startTextSelectionMode (line 1409) | public void startTextSelectionMode(MotionEvent event) {
method stopTextSelectionMode (line 1420) | public void stopTextSelectionMode() {
method decrementYTextSelectionCursors (line 1427) | private void decrementYTextSelectionCursors(int decrement) {
method onAttachedToWindow (line 1433) | @Override
method onDetachedFromWindow (line 1442) | @Override
method run (line 1462) | @RequiresApi(api = Build.VERSION_CODES.M)
method showFloatingToolbar (line 1471) | @RequiresApi(api = Build.VERSION_CODES.M)
method hideFloatingToolbar (line 1479) | @RequiresApi(api = Build.VERSION_CODES.M)
method updateFloatingToolbarVisibility (line 1487) | public void updateFloatingToolbarVisibility(MotionEvent event) {
FILE: terminal-view/src/main/java/com/termux/view/TerminalViewClient.java
type TerminalViewClient (line 17) | public interface TerminalViewClient {
method onScale (line 22) | float onScale(float scale);
method onSingleTapUp (line 29) | void onSingleTapUp(MotionEvent e);
method shouldBackButtonBeMappedToEscape (line 31) | boolean shouldBackButtonBeMappedToEscape();
method shouldEnforceCharBasedInput (line 33) | boolean shouldEnforceCharBasedInput();
method shouldUseCtrlSpaceWorkaround (line 35) | boolean shouldUseCtrlSpaceWorkaround();
method isTerminalViewSelected (line 37) | boolean isTerminalViewSelected();
method copyModeChanged (line 41) | void copyModeChanged(boolean copyMode);
method onKeyDown (line 45) | boolean onKeyDown(int keyCode, KeyEvent e, TerminalSession session);
method onKeyUp (line 47) | boolean onKeyUp(int keyCode, KeyEvent e);
method onLongPress (line 49) | boolean onLongPress(MotionEvent event);
method readControlKey (line 53) | boolean readControlKey();
method readAltKey (line 55) | boolean readAltKey();
method readShiftKey (line 57) | boolean readShiftKey();
method readFnKey (line 59) | boolean readFnKey();
method onCodePoint (line 63) | boolean onCodePoint(int codePoint, boolean ctrlDown, TerminalSession s...
method onEmulatorSet (line 66) | void onEmulatorSet();
method logError (line 69) | void logError(String tag, String message);
method logWarn (line 71) | void logWarn(String tag, String message);
method logInfo (line 73) | void logInfo(String tag, String message);
method logDebug (line 75) | void logDebug(String tag, String message);
method logVerbose (line 77) | void logVerbose(String tag, String message);
method logStackTraceWithMessage (line 79) | void logStackTraceWithMessage(String tag, String message, Exception e);
method logStackTrace (line 81) | void logStackTrace(String tag, Exception e);
FILE: terminal-view/src/main/java/com/termux/view/support/PopupWindowCompatGingerbread.java
class PopupWindowCompatGingerbread (line 27) | public class PopupWindowCompatGingerbread {
method setWindowLayoutType (line 34) | public static void setWindowLayoutType(PopupWindow popupWindow, int la...
method getWindowLayoutType (line 54) | public static int getWindowLayoutType(PopupWindow popupWindow) {
FILE: terminal-view/src/main/java/com/termux/view/textselection/CursorController.java
type CursorController (line 12) | public interface CursorController extends ViewTreeObserver.OnTouchModeCh...
method show (line 17) | void show(MotionEvent event);
method hide (line 23) | boolean hide();
method render (line 28) | void render();
method updatePosition (line 33) | void updatePosition(TextSelectionHandleView handle, int x, int y);
method onTouchEvent (line 41) | boolean onTouchEvent(MotionEvent event);
method onDetached (line 48) | void onDetached();
method isActive (line 53) | boolean isActive();
FILE: terminal-view/src/main/java/com/termux/view/textselection/TextSelectionCursorController.java
class TextSelectionCursorController (line 21) | public class TextSelectionCursorController implements CursorController {
method TextSelectionCursorController (line 37) | public TextSelectionCursorController(TerminalView terminalView) {
method show (line 45) | @Override
method hide (line 56) | @Override
method render (line 81) | @Override
method setInitialTextSelectionPosition (line 93) | public void setInitialTextSelectionPosition(MotionEvent event) {
method setActionModeCallBacks (line 110) | public void setActionModeCallBacks() {
method updatePosition (line 217) | @Override
method getValidCurX (line 307) | private int getValidCurX(TerminalBuffer screen, int cy, int cx) {
method decrementYTextSelectionCursors (line 338) | public void decrementYTextSelectionCursors(int decrement) {
method onTouchEvent (line 343) | public boolean onTouchEvent(MotionEvent event) {
method onTouchModeChanged (line 347) | public void onTouchModeChanged(boolean isInTouchMode) {
method onDetached (line 353) | @Override
method isActive (line 357) | @Override
method getSelectors (line 362) | public void getSelectors(int[] sel) {
method getSelectedText (line 374) | public String getSelectedText() {
method getStoredSelectedText (line 379) | @Nullable
method unsetStoredSelectedText (line 385) | public void unsetStoredSelectedText() {
method getActionMode (line 389) | public ActionMode getActionMode() {
method isSelectionStartDragged (line 396) | public boolean isSelectionStartDragged() {
method isSelectionEndDragged (line 403) | public boolean isSelectionEndDragged() {
FILE: terminal-view/src/main/java/com/termux/view/textselection/TextSelectionHandleView.java
class TextSelectionHandleView (line 20) | @SuppressLint("ViewConstructor")
method TextSelectionHandleView (line 56) | public TextSelectionHandleView(TerminalView terminalView, CursorContro...
method initHandle (line 68) | private void initHandle() {
method setOrientation (line 88) | public void setOrientation(int orientation) {
method show (line 115) | public void show() {
method hide (line 137) | public void hide() {
method removeFromParent (line 150) | public void removeFromParent() {
method positionAtCursor (line 156) | public void positionAtCursor(final int cx, final int cy, boolean force...
method moveTo (line 162) | private void moveTo(int x, int y, boolean forceOrientationCheck) {
method changeOrientation (line 199) | public void changeOrientation(int orientation) {
method checkChangedOrientation (line 205) | private void checkChangedOrientation(int posX, boolean force) {
method isPositionVisible (line 244) | private boolean isPositionVisible() {
method onDraw (line 279) | @Override
method onTouchEvent (line 287) | @SuppressLint("ClickableViewAccessibility")
method onMeasure (line 323) | @Override
method getHandleHeight (line 329) | public int getHandleHeight() {
method getHandleWidth (line 333) | public int getHandleWidth() {
method isShowing (line 337) | public boolean isShowing() {
method isParentNull (line 344) | public boolean isParentNull() {
method isDragging (line 348) | public boolean isDragging() {
FILE: termux-shared/src/androidTest/java/com/termux/shared/ExampleInstrumentedTest.java
class ExampleInstrumentedTest (line 18) | @RunWith(AndroidJUnit4.class)
method useAppContext (line 20) | @Test
FILE: termux-shared/src/main/cpp/local-socket.cpp
function string (line 23) | string jstring_to_stdstr(JNIEnv *env, jstring jString) {
function string (line 35) | string get_string_till_first_delim(string str, char delim) {
function string (line 46) | string replace_null_with_space(string str) {
function string (line 66) | string get_class_name(JNIEnv *env, jclass clazz) {
function string (line 80) | string get_process_cmdline(const pid_t pid) {
function string (line 98) | string get_process_name_from_cmdline(string cmdline) {
function string (line 103) | string get_process_cmdline_spaced(string cmdline) {
function log_error (line 109) | void log_error(string message) {
function log_warn (line 114) | void log_warn(string message) {
function string (line 119) | string get_title_and_message(JNIEnv *env, jstring title, string message) {
function timespec_to_milliseconds (line 127) | int64_t timespec_to_milliseconds(const struct timespec* const time) {
function timeval (line 132) | timeval milliseconds_to_timeval(int milliseconds) {
function checkJniException (line 144) | bool checkJniException(JNIEnv *env) {
function string (line 157) | string getJniResultString(const int retvalParam, const int errnoParam,
function jobject (line 164) | jobject getJniResult(JNIEnv *env, jstring title, const int retvalParam, ...
function jobject (line 200) | jobject getJniResult(JNIEnv *env, jstring title, const int retvalParam, ...
function jobject (line 204) | jobject getJniResult(JNIEnv *env, jstring title, const int retvalParam, ...
function jobject (line 208) | jobject getJniResult(JNIEnv *env, jstring title, const int retvalParam, ...
function jobject (line 212) | jobject getJniResult(JNIEnv *env, jstring title, const int intDataParam) {
function jobject (line 216) | jobject getJniResult(JNIEnv *env, jstring title) {
function string (line 222) | string setIntField(JNIEnv *env, jobject obj, jclass clazz, const string ...
function string (line 237) | string setStringField(JNIEnv *env, jobject obj, jclass clazz, const stri...
function JNIEXPORT (line 254) | JNIEXPORT jobject JNICALL
function JNIEXPORT (line 318) | JNIEXPORT jobject JNICALL
function JNIEXPORT (line 334) | JNIEXPORT jobject JNICALL
function JNIEXPORT (line 352) | JNIEXPORT jobject JNICALL
function JNIEXPORT (line 415) | JNIEXPORT jobject JNICALL
function JNIEXPORT (line 472) | JNIEXPORT jobject JNICALL
function set_socket_timeout (line 490) | int set_socket_timeout(int fd, int option, int timeout) {
function JNIEXPORT (line 497) | JNIEXPORT jobject JNICALL
function JNIEXPORT (line 515) | JNIEXPORT jobject JNICALL
function JNIEXPORT (line 534) | JNIEXPORT jobject JNICALL
FILE: termux-shared/src/main/java/com/termux/shared/activities/ReportActivity.java
class ReportActivity (line 50) | public class ReportActivity extends AppCompatActivity {
method onCreate (line 72) | @Override
method onNewIntent (line 97) | @Override
method updateUI (line 111) | private void updateUI() {
method onSaveInstanceState (line 174) | @Override
method onDestroy (line 184) | @Override
method onCreateOptionsMenu (line 192) | @Override
method onBackPressed (line 206) | @Override
method onOptionsItemSelected (line 212) | @Override
method onRequestPermissionsResult (line 228) | @Override
method generateReportActivityMarkdownString (line 246) | private void generateReportActivityMarkdownString() {
class NewInstanceResult (line 289) | public static class NewInstanceResult {
method NewInstanceResult (line 297) | NewInstanceResult(Intent contentIntent, Intent deleteIntent) {
method startReportActivity (line 309) | public static void startReportActivity(@NonNull final Context context,...
method newInstance (line 331) | @NonNull
method createContentIntent (line 354) | private static Intent createContentIntent(@NonNull final Context conte...
method createDeleteIntent (line 374) | private static Intent createDeleteIntent(@NonNull final Context contex...
method getReportInfoDirectoryPath (line 391) | @NotNull
method deleteReportInfoFile (line 397) | private static void deleteReportInfoFile(Context context, String repor...
method deleteReportInfoFilesOlderThanXDays (line 430) | public static Error deleteReportInfoFilesOlderThanXDays(@NonNull final...
method deleteReportInfoFilesOlderThanXDaysInner (line 444) | private static Error deleteReportInfoFilesOlderThanXDaysInner(@NonNull...
class ReportActivityBroadcastReceiver (line 456) | public static class ReportActivityBroadcastReceiver extends BroadcastR...
method onReceive (line 459) | @Override
FILE: termux-shared/src/main/java/com/termux/shared/activities/TextIOActivity.java
class TextIOActivity (line 44) | public class TextIOActivity extends AppCompatActivity {
method onCreate (line 61) | @Override
method onNewIntent (line 90) | @Override
method updateUI (line 101) | @SuppressLint("ClickableViewAccessibility")
method updateTextIOInfoText (line 189) | private void updateTextIOInfoText() {
method updateTextIOTextCharacterUsage (line 194) | private void updateTextIOTextCharacterUsage(String text) {
method onSaveInstanceState (line 200) | @Override
method onCreateOptionsMenu (line 208) | @Override
method onOptionsItemSelected (line 215) | @Override
method onBackPressed (line 235) | @Override
method confirm (line 241) | private void confirm() {
method cancel (line 249) | private void cancel() {
method getResultIntent (line 255) | @NotNull
method newInstance (line 270) | public static Intent newInstance(@NonNull final Context context, @NonN...
FILE: termux-shared/src/main/java/com/termux/shared/activity/ActivityErrno.java
class ActivityErrno (line 5) | public class ActivityErrno extends Errno {
method ActivityErrno (line 16) | ActivityErrno(final String type, final int code, final String message) {
FILE: termux-shared/src/main/java/com/termux/shared/activity/ActivityUtils.java
class ActivityUtils (line 16) | public class ActivityUtils {
method startActivity (line 23) | public static Error startActivity(@NonNull Context context, @NonNull I...
method startActivity (line 38) | public static Error startActivity(Context context, @NonNull Intent int...
method startActivityForResult (line 67) | public static Error startActivityForResult(Context context, int reques...
method startActivityForResult (line 74) | public static Error startActivityForResult(Context context, int reques...
method startActivityForResult (line 100) | public static Error startActivityForResult(Context context, int reques...
FILE: termux-shared/src/main/java/com/termux/shared/activity/media/AppCompatActivityUtils.java
class AppCompatActivityUtils (line 14) | public class AppCompatActivityUtils {
method setNightMode (line 26) | public static void setNightMode(AppCompatActivity activity, String nam...
method setToolbar (line 46) | public static void setToolbar(@NonNull AppCompatActivity activity, @Id...
method setToolbarTitle (line 59) | public static void setToolbarTitle(@NonNull AppCompatActivity activity...
method setToolbarSubtitle (line 86) | public static void setToolbarSubtitle(@NonNull AppCompatActivity activ...
method setShowBackButtonInActionBar (line 106) | public static void setShowBackButtonInActionBar(@NonNull AppCompatActi...
FILE: termux-shared/src/main/java/com/termux/shared/android/AndroidUtils.java
class AndroidUtils (line 28) | public class AndroidUtils {
method getAppInfoMarkdownString (line 39) | public static String getAppInfoMarkdownString(@NonNull final Context c...
method getAppInfoMarkdownString (line 72) | public static String getAppInfoMarkdownString(@NonNull final Context c...
method getDeviceInfoMarkdownString (line 103) | public static String getDeviceInfoMarkdownString(@NonNull final Contex...
method getDeviceInfoMarkdownString (line 114) | public static String getDeviceInfoMarkdownString(@NonNull final Contex...
method getSystemProperties (line 170) | public static Properties getSystemProperties() {
method getSystemPropertyWithAndroidAPI (line 216) | public static String getSystemPropertyWithAndroidAPI(@NonNull String p...
method appendPropertyToMarkdownIfSet (line 225) | public static void appendPropertyToMarkdownIfSet(StringBuilder markdow...
method appendPropertyToMarkdown (line 231) | public static void appendPropertyToMarkdown(StringBuilder markdownStri...
method getPropertyMarkdown (line 235) | public static String getPropertyMarkdown(String label, Object value) {
method appendLiteralPropertyToMarkdown (line 239) | public static void appendLiteralPropertyToMarkdown(StringBuilder markd...
method getLiteralPropertyMarkdown (line 243) | public static String getLiteralPropertyMarkdown(String label, Object v...
method getCurrentTimeStamp (line 249) | public static String getCurrentTimeStamp() {
method getCurrentMilliSecondUTCTimeStamp (line 256) | public static String getCurrentMilliSecondUTCTimeStamp() {
method getCurrentMilliSecondLocalTimeStamp (line 263) | public static String getCurrentMilliSecondLocalTimeStamp() {
FILE: termux-shared/src/main/java/com/termux/shared/android/FeatureFlagUtils.java
class FeatureFlagUtils (line 53) | public class FeatureFlagUtils {
type FeatureFlagValue (line 55) | public enum FeatureFlagValue {
method FeatureFlagValue (line 71) | FeatureFlagValue(final String name) {
method getName (line 75) | public String getName() {
method getAllFeatureFlags (line 88) | @SuppressWarnings("unchecked")
method featureFlagExists (line 109) | @Nullable
method getFeatureFlagValueString (line 123) | @NonNull
method isFeatureEnabled (line 150) | @Nullable
FILE: termux-shared/src/main/java/com/termux/shared/android/PackageUtils.java
class PackageUtils (line 29) | public class PackageUtils {
method getContextForPackage (line 40) | @Nullable
method getContextForPackage (line 53) | @Nullable
method getContextForPackageOrExitApp (line 73) | @Nullable
method getPackageInfoForPackage (line 100) | public static PackageInfo getPackageInfoForPackage(@NonNull final Cont...
method getPackageInfoForPackage (line 111) | @Nullable
method getPackageInfoForPackage (line 123) | public static PackageInfo getPackageInfoForPackage(@NonNull final Cont...
method getPackageInfoForPackage (line 138) | @Nullable
method getApplicationInfoForPackage (line 156) | @Nullable
method getApplicationInfoForPackage (line 172) | @Nullable
method getApplicationInfoPrivateFlagsForPackage (line 187) | @Nullable
method getApplicationInfoSeInfoForPackage (line 215) | @Nullable
method getApplicationInfoSeInfoUserForPackage (line 235) | @Nullable
method getApplicationInfoStaticIntFieldValue (line 254) | @Nullable
method isApplicationInfoPrivateFlagSetForPackage (line 274) | @Nullable
method getAppNameForPackage (line 295) | public static String getAppNameForPackage(@NonNull final Context conte...
method getAppNameForPackage (line 306) | public static String getAppNameForPackage(@NonNull final Context conte...
method getPackageNameForPackage (line 318) | public static String getPackageNameForPackage(@NonNull final Context c...
method getPackageNameForPackage (line 328) | public static String getPackageNameForPackage(@NonNull final Applicati...
method getUidForPackage (line 340) | public static int getUidForPackage(@NonNull final Context context) {
method getUidForPackage (line 350) | public static int getUidForPackage(@NonNull final ApplicationInfo appl...
method getTargetSDKForPackage (line 362) | public static int getTargetSDKForPackage(@NonNull final Context contex...
method getTargetSDKForPackage (line 372) | public static int getTargetSDKForPackage(@NonNull final ApplicationInf...
method getBaseAPKPathForPackage (line 384) | public static String getBaseAPKPathForPackage(@NonNull final Context c...
method getBaseAPKPathForPackage (line 394) | public static String getBaseAPKPathForPackage(@NonNull final Applicati...
method isAppForPackageADebuggableBuild (line 407) | public static boolean isAppForPackageADebuggableBuild(@NonNull final C...
method isAppForPackageADebuggableBuild (line 418) | public static boolean isAppForPackageADebuggableBuild(@NonNull final A...
method isAppInstalledOnExternalStorage (line 431) | public static boolean isAppInstalledOnExternalStorage(@NonNull final C...
method isAppInstalledOnExternalStorage (line 442) | public static boolean isAppInstalledOnExternalStorage(@NonNull final A...
method hasRequestedLegacyExternalStorage (line 457) | @Nullable
method hasRequestedLegacyExternalStorage (line 471) | @Nullable
method getVersionCodeForPackage (line 484) | @Nullable
method getVersionCodeForPackage (line 496) | @Nullable
method getVersionCodeForPackage (line 507) | @Nullable
method getVersionNameForPackage (line 520) | @Nullable
method getVersionNameForPackage (line 532) | @Nullable
method getVersionNameForPackage (line 544) | @Nullable
method getSigningCertificateSHA256DigestForPackage (line 557) | @Nullable
method getSigningCertificateSHA256DigestForPackage (line 569) | @Nullable
method getUserIdForPackage (line 596) | @RequiresApi(api = Build.VERSION_CODES.N)
method isCurrentUserThePrimaryUser (line 611) | @RequiresApi(api = Build.VERSION_CODES.N)
method getProfileOwnerPackageNameForUser (line 624) | @Nullable
method getPackagePID (line 650) | @Nullable
method isAppInstalled (line 699) | public static String isAppInstalled(@NonNull final Context context, St...
method setComponentState (line 715) | public static String setComponentState(@NonNull final Context context,...
method setComponentState (line 734) | @Nullable
method isComponentDisabled (line 786) | public static Boolean isComponentDisabled(@NonNull final Context conte...
method doesActivityComponentExist (line 814) | public static boolean doesActivityComponentExist(@NonNull final Contex...
FILE: termux-shared/src/main/java/com/termux/shared/android/PermissionUtils.java
class PermissionUtils (line 35) | public class PermissionUtils {
method checkPermission (line 52) | public static boolean checkPermission(@NonNull Context context, @NonNu...
method checkPermissions (line 63) | public static boolean checkPermissions(@NonNull Context context, @NonN...
method requestPermission (line 96) | @RequiresApi(api = Build.VERSION_CODES.M)
method requestPermissions (line 120) | @RequiresApi(api = Build.VERSION_CODES.M)
method isPermissionRequested (line 171) | public static boolean isPermissionRequested(@NonNull Context context, ...
method getPermissionsNotRequested (line 183) | @NonNull
method checkAndRequestLegacyOrManageExternalStoragePermissionIfPathOnPrimaryExternalStorage (line 220) | @SuppressLint("SdCardPath")
method checkAndRequestLegacyOrManageExternalStoragePermission (line 262) | public static boolean checkAndRequestLegacyOrManageExternalStoragePerm...
method checkStoragePermission (line 309) | public static boolean checkStoragePermission(@NonNull Context context,...
method requestLegacyStorageExternalPermission (line 329) | @RequiresApi(api = Build.VERSION_CODES.M)
method requestManageStorageExternalPermission (line 336) | @RequiresApi(api = Build.VERSION_CODES.R)
method requestManageStorageExternalPermission (line 352) | @RequiresApi(api = Build.VERSION_CODES.R)
method isLegacyExternalStoragePossible (line 389) | public static boolean isLegacyExternalStoragePossible(@NonNull Context...
method checkIfHasRequestedLegacyExternalStorage (line 405) | public static boolean checkIfHasRequestedLegacyExternalStorage(@NonNul...
method hasRequestedLegacyExternalStorage (line 424) | public static boolean hasRequestedLegacyExternalStorage(@NonNull Conte...
method checkDisplayOverOtherAppsPermission (line 450) | public static boolean checkDisplayOverOtherAppsPermission(@NonNull Con...
method requestDisplayOverOtherAppsPermission (line 458) | public static Error requestDisplayOverOtherAppsPermission(@NonNull Con...
method requestDisplayOverOtherAppsPermission (line 473) | public static Error requestDisplayOverOtherAppsPermission(@NonNull Con...
method validateDisplayOverOtherAppsPermissionForPostAndroid10 (line 501) | public static boolean validateDisplayOverOtherAppsPermissionForPostAnd...
method checkIfBatteryOptimizationsDisabled (line 527) | public static boolean checkIfBatteryOptimizationsDisabled(@NonNull Con...
method requestDisableBatteryOptimizations (line 536) | public static Error requestDisableBatteryOptimizations(@NonNull Contex...
method requestDisableBatteryOptimizations (line 552) | @SuppressLint("BatteryLife")
FILE: termux-shared/src/main/java/com/termux/shared/android/PhantomProcessUtils.java
class PhantomProcessUtils (line 22) | public class PhantomProcessUtils {
method getFeatureFlagMonitorPhantomProcsValueString (line 62) | @NonNull
method getActivityManagerMaxPhantomProcesses (line 74) | @Nullable
method getSettingsGlobalDeviceConfigSyncDisabled (line 109) | @Nullable
FILE: termux-shared/src/main/java/com/termux/shared/android/ProcessUtils.java
class ProcessUtils (line 13) | public class ProcessUtils {
method getAppProcessNameForPid (line 35) | @Nullable
FILE: termux-shared/src/main/java/com/termux/shared/android/SELinuxUtils.java
class SELinuxUtils (line 13) | public class SELinuxUtils {
method getContext (line 25) | @Nullable
method getPidContext (line 51) | @Nullable
method getFileContext (line 77) | @Nullable
FILE: termux-shared/src/main/java/com/termux/shared/android/SettingsProviderUtils.java
class SettingsProviderUtils (line 11) | public class SettingsProviderUtils {
type SettingNamespace (line 16) | public enum SettingNamespace {
type SettingType (line 28) | public enum SettingType {
method getSettingsValue (line 46) | @Nullable
FILE: termux-shared/src/main/java/com/termux/shared/android/UserUtils.java
class UserUtils (line 14) | public class UserUtils {
method getNameForUid (line 26) | @Nullable
method getNameForUidFromPackageManager (line 48) | @Nullable
method getNameForUidFromLibcore (line 86) | @Nullable
FILE: termux-shared/src/main/java/com/termux/shared/android/resource/ResourceUtils.java
class ResourceUtils (line 11) | public class ResourceUtils {
method getResourceId (line 25) | @Nullable
method getResourceId (line 47) | @Nullable
method getColorResourceId (line 75) | @Nullable
method getDrawableResourceId (line 86) | @Nullable
method getIdResourceId (line 97) | @Nullable
method getLayoutResourceId (line 108) | @Nullable
method getStringResourceId (line 119) | @Nullable
method getStyleResourceId (line 130) | @Nullable
FILE: termux-shared/src/main/java/com/termux/shared/crash/CrashHandler.java
class CrashHandler (line 18) | public class CrashHandler implements Thread.UncaughtExceptionHandler {
method CrashHandler (line 27) | private CrashHandler(@NonNull final Context context, @NonNull final Cr...
method uncaughtException (line 35) | public void uncaughtException(@NonNull Thread thread, @NonNull Throwab...
method setDefaultCrashHandler (line 47) | public static void setDefaultCrashHandler(@NonNull final Context conte...
method setCrashHandler (line 56) | public static void setCrashHandler(@NonNull final Context context, @No...
method getCrashHandler (line 63) | public static CrashHandler getCrashHandler(@NonNull final Context cont...
method logCrash (line 75) | public static void logCrash(@NonNull Context context,
method logCrash (line 82) | public void logCrash(@NonNull Thread thread, @NonNull Throwable throwa...
method logCrashToFile (line 89) | public void logCrashToFile(@NonNull Context context,
type CrashHandlerClient (line 117) | public interface CrashHandlerClient {
method onPreLogCrash (line 128) | boolean onPreLogCrash(Context context, Thread thread, Throwable thro...
method onPostLogCrash (line 137) | void onPostLogCrash(Context context, Thread thread, Throwable throwa...
method getCrashLogFilePath (line 145) | @NonNull
method getAppInfoMarkdownString (line 154) | String getAppInfoMarkdownString(Context context);
FILE: termux-shared/src/main/java/com/termux/shared/data/DataUtils.java
class DataUtils (line 15) | public class DataUtils {
method getTruncatedCommandOutput (line 23) | public static String getTruncatedCommandOutput(String text, int maxLen...
method replaceSubStringsInStringArrayItems (line 60) | public static void replaceSubStringsInStringArrayItems(String[] array,...
method getFloatFromString (line 76) | public static float getFloatFromString(String value, float def) {
method getIntFromString (line 95) | public static int getIntFromString(String value, int def) {
method getStringFromInteger (line 113) | public static String getStringFromInteger(Integer value, String def) {
method bytesToHex (line 123) | public static String bytesToHex(byte[] bytes) {
method getIntStoredAsStringFromBundle (line 143) | public static int getIntStoredAsStringFromBundle(Bundle bundle, String...
method clamp (line 153) | public static int clamp(int value, int min, int max) {
method rangedOrDefault (line 160) | public static float rangedOrDefault(float value, float def, float min,...
method getSpaceIndentedString (line 176) | public static String getSpaceIndentedString(String string, int count) {
method getTabIndentedString (line 190) | public static String getTabIndentedString(String string, int count) {
method getIndentedString (line 205) | public static String getIndentedString(String string, @NonNull String ...
method getDefaultIfNull (line 221) | public static <T> T getDefaultIfNull(@Nullable T object, @Nullable T d...
method getDefaultIfUnset (line 232) | public static String getDefaultIfUnset(@Nullable String value, String ...
method isNullOrEmpty (line 237) | public static boolean isNullOrEmpty(String string) {
method getSerializedSize (line 244) | public static long getSerializedSize(Serializable object) {
FILE: termux-shared/src/main/java/com/termux/shared/data/IntentUtils.java
class IntentUtils (line 11) | public class IntentUtils {
method getStringExtraIfSet (line 26) | public static String getStringExtraIfSet(@NonNull Intent intent, Strin...
method getStringExtraIfSet (line 41) | public static String getStringExtraIfSet(@NonNull Intent intent, Strin...
method getIntegerExtraIfSet (line 61) | public static Integer getIntegerExtraIfSet(@NonNull Intent intent, Str...
method getStringArrayExtraIfSet (line 87) | public static String[] getStringArrayExtraIfSet(@NonNull Intent intent...
method getStringArrayExtraIfSet (line 102) | public static String[] getStringArrayExtraIfSet(Intent intent, String ...
method getIntentString (line 113) | public static String getIntentString(Intent intent) {
method getBundleString (line 119) | public static String getBundleString(Bundle bundle) {
FILE: termux-shared/src/main/java/com/termux/shared/errors/Errno.java
class Errno (line 15) | public class Errno {
method Errno (line 37) | public Errno(@NonNull final String type, final int code, @NonNull fina...
method toString (line 44) | @NonNull
method getType (line 50) | @NonNull
method getCode (line 55) | public int getCode() {
method getMessage (line 59) | @NonNull
method valueOf (line 72) | public static Errno valueOf(String type, Integer code) {
method getError (line 79) | public Error getError() {
method getError (line 83) | public Error getError(Object... args) {
method getError (line 93) | public Error getError(Throwable throwable, Object... args) {
method getError (line 100) | public Error getError(List<Throwable> throwablesList, Object... args) {
method equalsErrorTypeAndCode (line 113) | public boolean equalsErrorTypeAndCode(Error error) {
FILE: termux-shared/src/main/java/com/termux/shared/errors/Error.java
class Error (line 15) | public class Error implements Serializable {
method Error (line 31) | public Error() {
method Error (line 35) | public Error(String type, Integer code, String message, List<Throwable...
method Error (line 39) | public Error(String type, Integer code, String message, Throwable thro...
method Error (line 43) | public Error(String type, Integer code, String message) {
method Error (line 47) | public Error(Integer code, String message, List<Throwable> throwablesL...
method Error (line 51) | public Error(Integer code, String message, Throwable throwable) {
method Error (line 55) | public Error(Integer code, String message) {
method Error (line 59) | public Error(String message, Throwable throwable) {
method Error (line 63) | public Error(String message, List<Throwable> throwablesList) {
method Error (line 67) | public Error(String message) {
method InitError (line 71) | private void InitError(String type, Integer code, String message, List...
method setLabel (line 88) | public Error setLabel(String label) {
method getLabel (line 93) | public String getLabel() {
method getType (line 98) | public String getType() {
method getCode (line 102) | public Integer getCode() {
method getMessage (line 106) | public String getMessage() {
method prependMessage (line 110) | public void prependMessage(String message) {
method appendMessage (line 115) | public void appendMessage(String message) {
method getThrowablesList (line 120) | public List<Throwable> getThrowablesList() {
method setStateFailed (line 125) | public synchronized boolean setStateFailed(@NonNull Error error) {
method setStateFailed (line 129) | public synchronized boolean setStateFailed(@NonNull Error error, Throw...
method setStateFailed (line 132) | public synchronized boolean setStateFailed(@NonNull Error error, List<...
method setStateFailed (line 136) | public synchronized boolean setStateFailed(int code, String message) {
method setStateFailed (line 140) | public synchronized boolean setStateFailed(int code, String message, T...
method setStateFailed (line 144) | public synchronized boolean setStateFailed(int code, String message, L...
method setStateFailed (line 148) | public synchronized boolean setStateFailed(String type, int code, Stri...
method isStateFailed (line 165) | public boolean isStateFailed() {
method toString (line 170) | @NonNull
method logErrorAndShowToast (line 185) | public static void logErrorAndShowToast(Context context, String logTag...
method logErrorAndShowToast (line 190) | public void logErrorAndShowToast(Context context, String logTag) {
method getErrorLogString (line 202) | public static String getErrorLogString(final Error error) {
method getErrorLogString (line 207) | public String getErrorLogString() {
method getMinimalErrorLogString (line 224) | public static String getMinimalErrorLogString(final Error error) {
method getMinimalErrorLogString (line 229) | public String getMinimalErrorLogString() {
method getMinimalErrorString (line 244) | public static String getMinimalErrorString(final Error error) {
method getMinimalErrorString (line 249) | public String getMinimalErrorString() {
method getErrorMarkdownString (line 264) | public static String getErrorMarkdownString(final Error error) {
method getErrorMarkdownString (line 269) | public String getErrorMarkdownString() {
method getCodeString (line 282) | public String getCodeString() {
method getTypeAndMessageLogString (line 286) | public String getTypeAndMessageLogString() {
method geStackTracesLogString (line 290) | public String geStackTracesLogString() {
method geStackTracesMarkdownString (line 294) | public String geStackTracesMarkdownString() {
FILE: termux-shared/src/main/java/com/termux/shared/errors/FunctionErrno.java
class FunctionErrno (line 4) | public class FunctionErrno extends Errno {
method FunctionErrno (line 18) | FunctionErrno(final String type, final int code, final String message) {
FILE: termux-shared/src/main/java/com/termux/shared/file/FileUtils.java
class FileUtils (line 43) | public class FileUtils {
method getCanonicalPath (line 71) | public static String getCanonicalPath(String path, final String prefix...
method normalizePath (line 102) | @Nullable
method sanitizeFileName (line 125) | public static String sanitizeFileName(String fileName, boolean sanitiz...
method isPathInDirPath (line 149) | public static boolean isPathInDirPath(String path, final String dirPat...
method isPathInDirPaths (line 163) | public static boolean isPathInDirPaths(String path, final List<String>...
method validateDirectoryFileEmptyOrOnlyContainsSpecificFiles (line 207) | public static Error validateDirectoryFileEmptyOrOnlyContainsSpecificFi...
method nonIgnoredSubFileExists (line 268) | public static boolean nonIgnoredSubFileExists(File[] subFiles, @NonNul...
method regularFileExists (line 310) | public static boolean regularFileExists(final String filePath, final b...
method directoryFileExists (line 323) | public static boolean directoryFileExists(final String filePath, final...
method symlinkFileExists (line 333) | public static boolean symlinkFileExists(final String filePath) {
method regularOrDirectoryFileExists (line 346) | public static boolean regularOrDirectoryFileExists(final String filePa...
method fileExists (line 360) | public static boolean fileExists(final String filePath, final boolean ...
method getFileType (line 378) | @NonNull
method validateRegularFileExistenceAndPermissions (line 406) | public static Error validateRegularFileExistenceAndPermissions(String ...
method validateDirectoryFileExistenceAndPermissions (line 487) | public static Error validateDirectoryFileExistenceAndPermissions(Strin...
method createRegularFile (line 566) | public static Error createRegularFile(final String filePath) {
method createRegularFile (line 581) | public static Error createRegularFile(final String label, final String...
method createRegularFile (line 602) | public static Error createRegularFile(String label, final String fileP...
method createParentDirectoryFile (line 655) | public static Error createParentDirectoryFile(final String label, fina...
method createDirectoryFile (line 678) | public static Error createDirectoryFile(final String filePath) {
method createDirectoryFile (line 693) | public static Error createDirectoryFile(final String label, final Stri...
method createDirectoryFile (line 714) | public static Error createDirectoryFile(final String label, final Stri...
method createSymlinkFile (line 738) | public static Error createSymlinkFile(final String targetFilePath, fin...
method createSymlinkFile (line 758) | public static Error createSymlinkFile(String label, final String targe...
method createSymlinkFile (line 779) | public static Error createSymlinkFile(String label, final String targe...
method copyRegularFile (line 860) | public static Error copyRegularFile(final String label, final String s...
method moveRegularFile (line 882) | public static Error moveRegularFile(final String label, final String s...
method copyDirectoryFile (line 904) | public static Error copyDirectoryFile(final String label, final String...
method moveDirectoryFile (line 926) | public static Error moveDirectoryFile(final String label, final String...
method copySymlinkFile (line 948) | public static Error copySymlinkFile(final String label, final String s...
method moveSymlinkFile (line 970) | public static Error moveSymlinkFile(final String label, final String s...
method copyFile (line 992) | public static Error copyFile(final String label, final String srcFileP...
method moveFile (line 1014) | public static Error moveFile(final String label, final String srcFileP...
method copyOrMoveFile (line 1051) | public static Error copyOrMoveFile(String label, final String srcFileP...
method deleteRegularFile (line 1198) | public static Error deleteRegularFile(String label, final String fileP...
method deleteDirectoryFile (line 1213) | public static Error deleteDirectoryFile(String label, final String fil...
method deleteSymlinkFile (line 1228) | public static Error deleteSymlinkFile(String label, final String fileP...
method deleteSocketFile (line 1243) | public static Error deleteSocketFile(String label, final String filePa...
method deleteFile (line 1258) | public static Error deleteFile(String label, final String filePath, fi...
method deleteFile (line 1283) | public static Error deleteFile(String label, final String filePath, fi...
method clearDirectory (line 1375) | public static Error clearDirectory(String filePath) {
method clearDirectory (line 1390) | public static Error clearDirectory(String label, final String filePath) {
method deleteFilesOlderThanXDays (line 1453) | public static Error deleteFilesOlderThanXDays(String label, final Stri...
method readTextFromFile (line 1523) | public static Error readTextFromFile(String label, final String filePa...
class ReadSerializableObjectResult (line 1583) | public static class ReadSerializableObjectResult {
method ReadSerializableObjectResult (line 1587) | ReadSerializableObjectResult(Error error, Serializable serializableO...
method readSerializableObjectFromFile (line 1603) | @NonNull
method writeTextToFile (line 1662) | public static Error writeTextToFile(String label, final String filePat...
method writeSerializableObjectToFile (line 1708) | public static <T extends Serializable> Error writeSerializableObjectTo...
method preWriteToFile (line 1739) | private static Error preWriteToFile(String label, String filePath) {
method isCharsetSupported (line 1765) | public static Error isCharsetSupported(final Charset charset) {
method closeCloseable (line 1786) | public static void closeCloseable(final Closeable closeable) {
method setFilePermissions (line 1806) | public static void setFilePermissions(final String filePath, final Str...
method setFilePermissions (line 1818) | public static void setFilePermissions(String label, final String fileP...
method setMissingFilePermissions (line 1877) | public static void setMissingFilePermissions(final String filePath, fi...
method setMissingFilePermissions (line 1889) | public static void setMissingFilePermissions(String label, final Strin...
method checkMissingFilePermissions (line 1927) | public static Error checkMissingFilePermissions(final String filePath,...
method checkMissingFilePermissions (line 1941) | public static Error checkMissingFilePermissions(String label, final St...
method isValidPermissionString (line 1979) | public static boolean isValidPermissionString(final String string) {
method getShortFileUtilsError (line 1992) | public static Error getShortFileUtilsError(final Error error) {
method getFileDirname (line 2013) | public static String getFileDirname(String filePath) {
method getFileBasename (line 2025) | public static String getFileBasename(String filePath) {
method getFileBasenameWithoutExtension (line 2037) | public static String getFileBasenameWithoutExtension(String filePath) {
FILE: termux-shared/src/main/java/com/termux/shared/file/FileUtilsErrno.java
class FileUtilsErrno (line 9) | public class FileUtilsErrno extends Errno {
method FileUtilsErrno (line 92) | FileUtilsErrno(final String type, final int code, final String message) {
FILE: termux-shared/src/main/java/com/termux/shared/file/filesystem/FileAttributes.java
class FileAttributes (line 45) | public class FileAttributes {
method FileAttributes (line 71) | private FileAttributes(String filePath) {
method FileAttributes (line 75) | private FileAttributes(FileDescriptor fileDescriptor) {
method get (line 80) | public static FileAttributes get(String filePath, boolean followLinks)...
method get (line 100) | public static FileAttributes get(FileDescriptor fileDescriptor) throws...
method file (line 106) | public String file() {
method isSameFile (line 116) | public boolean isSameFile(FileAttributes attrs) {
method mode (line 121) | public int mode() {
method blksize (line 125) | public long blksize() {
method blocks (line 129) | public long blocks() {
method ino (line 133) | public long ino() {
method dev (line 137) | public long dev() {
method rdev (line 141) | public long rdev() {
method nlink (line 145) | public long nlink() {
method uid (line 149) | public int uid() {
method gid (line 153) | public int gid() {
method toFileTime (line 157) | private static FileTime toFileTime(long sec, long nsec) {
method lastAccessTime (line 169) | public FileTime lastAccessTime() {
method lastModifiedTime (line 173) | public FileTime lastModifiedTime() {
method lastChangeTime (line 177) | public FileTime lastChangeTime() {
method creationTime (line 181) | public FileTime creationTime() {
method isRegularFile (line 185) | public boolean isRegularFile() {
method isDirectory (line 189) | public boolean isDirectory() {
method isSymbolicLink (line 193) | public boolean isSymbolicLink() {
method isCharacter (line 197) | public boolean isCharacter() {
method isFifo (line 201) | public boolean isFifo() {
method isSocket (line 205) | public boolean isSocket() {
method isBlock (line 209) | public boolean isBlock() {
method isOther (line 213) | public boolean isOther() {
method isDevice (line 220) | public boolean isDevice() {
method size (line 227) | public long size() {
method fileKey (line 231) | public FileKey fileKey() {
method owner (line 242) | public String owner() {
method group (line 253) | public String group() {
method permissions (line 264) | public Set<FilePermission> permissions() {
method loadFromStructStat (line 292) | public void loadFromStructStat(StructStat structStat) {
method getFileString (line 321) | public String getFileString() {
method getTypeString (line 325) | public String getTypeString() {
method getSizeString (line 329) | public String getSizeString() {
method getBlocksString (line 333) | public String getBlocksString() {
method getIOBlockString (line 337) | public String getIOBlockString() {
method getDeviceString (line 341) | public String getDeviceString() {
method getInodeString (line 345) | public String getInodeString() {
method getLinksString (line 349) | public String getLinksString() {
method getDeviceTypeString (line 353) | public String getDeviceTypeString() {
method getOwnerString (line 357) | public String getOwnerString() {
method getGroupString (line 361) | public String getGroupString() {
method getPermissionString (line 365) | public String getPermissionString() {
method getAccessTimeString (line 369) | public String getAccessTimeString() {
method getModifiedTimeString (line 373) | public String getModifiedTimeString() {
method getChangeTimeString (line 377) | public String getChangeTimeString() {
method toString (line 381) | @NonNull
method getFileAttributesLogString (line 387) | public static String getFileAttributesLogString(final FileAttributes f...
FILE: termux-shared/src/main/java/com/termux/shared/file/filesystem/FileKey.java
class FileKey (line 33) | public class FileKey {
method FileKey (line 37) | FileKey(long st_dev, long st_ino) {
method hashCode (line 42) | @Override
method equals (line 48) | @Override
method toString (line 58) | @Override
FILE: termux-shared/src/main/java/com/termux/shared/file/filesystem/FilePermission.java
type FilePermission (line 41) | public enum FilePermission {
FILE: termux-shared/src/main/java/com/termux/shared/file/filesystem/FilePermissions.java
class FilePermissions (line 41) | public final class FilePermissions {
method FilePermissions (line 42) | private FilePermissions() { }
method writeBits (line 45) | private static void writeBits(StringBuilder sb, boolean r, boolean w, ...
method toString (line 76) | public static String toString(Set<FilePermission> perms) {
method isSet (line 87) | private static boolean isSet(char c, char setValue) {
method isR (line 94) | private static boolean isR(char c) { return isSet(c, 'r'); }
method isW (line 95) | private static boolean isW(char c) { return isSet(c, 'w'); }
method isX (line 96) | private static boolean isX(char c) { return isSet(c, 'x'); }
method fromString (line 129) | public static Set<FilePermission> fromString(String perms) {
FILE: termux-shared/src/main/java/com/termux/shared/file/filesystem/FileTime.java
class FileTime (line 51) | public final class FileTime {
method FileTime (line 74) | private FileTime(long value, TimeUnit unit) {
method from (line 91) | public static FileTime from(long value, @NonNull TimeUnit unit) {
method fromMillis (line 105) | public static FileTime fromMillis(long value) {
method to (line 122) | public long to(TimeUnit unit) {
method toMillis (line 136) | public long toMillis() {
method toString (line 140) | @NonNull
method getDate (line 146) | public static String getDate(long milliSeconds, String format) {
FILE: termux-shared/src/main/java/com/termux/shared/file/filesystem/FileType.java
type FileType (line 4) | public enum FileType {
method FileType (line 19) | FileType(final String name, final int value) {
method getName (line 24) | public String getName() {
method getValue (line 28) | public int getValue() {
FILE: termux-shared/src/main/java/com/termux/shared/file/filesystem/FileTypes.java
class FileTypes (line 11) | public class FileTypes {
method convertFileTypeFlagsToNamesString (line 19) | public static String convertFileTypeFlagsToNamesString(int fileTypeFla...
method getFileType (line 85) | @NonNull
method getFileType (line 100) | public static FileType getFileType(@NonNull final FileAttributes fileA...
FILE: termux-shared/src/main/java/com/termux/shared/file/filesystem/NativeDispatcher.java
class NativeDispatcher (line 10) | public class NativeDispatcher {
method stat (line 12) | public static void stat(String filePath, FileAttributes fileAttributes...
method lstat (line 22) | public static void lstat(String filePath, FileAttributes fileAttribute...
method fstat (line 32) | public static void fstat(FileDescriptor fileDescriptor, FileAttributes...
method validateFileExistence (line 42) | public static void validateFileExistence(String filePath) throws IOExc...
method validateFileDescriptor (line 51) | public static void validateFileDescriptor(FileDescriptor fileDescripto...
FILE: termux-shared/src/main/java/com/termux/shared/file/filesystem/UnixConstants.java
class UnixConstants (line 43) | public class UnixConstants {
method UnixConstants (line 44) | private UnixConstants() { }
method get_S_IAMB (line 148) | private static int get_S_IAMB() {
FILE: termux-shared/src/main/java/com/termux/shared/file/tests/FileUtilsTests.java
class FileUtilsTests (line 18) | public class FileUtilsTests {
method runTests (line 34) | public static void runTests(@NonNull final Context context, @NonNull f...
method runTestsInner (line 50) | private static void runTestsInner(@NonNull final String testRootDirect...
method assertEqual (line 362) | public static void assertEqual(@NonNull final String message, final St...
method assertEqual (line 368) | public static void assertEqual(@NonNull final String message, final St...
method equalsRegardingNull (line 373) | private static boolean equalsRegardingNull(final String expected, fina...
method assertErrnoEqual (line 381) | public static void assertErrnoEqual(@NonNull final String message, fin...
method isEquals (line 388) | private static boolean isEquals(String expected, String actual) {
method throwException (line 392) | public static void throwException(@NonNull final String message) throw...
FILE: termux-shared/src/main/java/com/termux/shared/interact/MessageDialogUtils.java
class MessageDialogUtils (line 16) | public class MessageDialogUtils {
method showMessage (line 27) | public static void showMessage(Context context, String titleText, Stri...
method showMessage (line 47) | public static void showMessage(Context context, String titleText, Stri...
method exitAppWithErrorMessage (line 95) | public static void exitAppWithErrorMessage(Context context, String tit...
FILE: termux-shared/src/main/java/com/termux/shared/interact/ShareUtils.java
class ShareUtils (line 28) | public class ShareUtils {
method openSystemAppChooser (line 39) | public static void openSystemAppChooser(final Context context, final I...
method shareText (line 60) | public static void shareText(final Context context, final String subje...
method shareText (line 72) | public static void shareText(final Context context, final String subje...
method copyTextToClipboard (line 86) | public static void copyTextToClipboard(Context context, final String t...
method copyTextToClipboard (line 91) | public static void copyTextToClipboard(Context context, final String t...
method copyTextToClipboard (line 104) | public static void copyTextToClipboard(Context context, @Nullable fina...
method getTextStringFromClipboardIfSet (line 125) | @Nullable
method getTextFromClipboard (line 141) | @Nullable
method openUrl (line 165) | public static void openUrl(final Context context, final String url) {
method saveTextToFile (line 195) | public static void saveTextToFile(final Context context, final String ...
FILE: termux-shared/src/main/java/com/termux/shared/jni/models/JniResult.java
class JniResult (line 15) | @Keep
method JniResult (line 52) | public JniResult(int retval, int errno, String errmsg) {
method JniResult (line 66) | public JniResult(int retval, int errno, String errmsg, int intData) {
method JniResult (line 77) | public JniResult(String message, Throwable throwable) {
method getErrorString (line 87) | @NonNull
method getErrorString (line 94) | @NonNull
FILE: termux-shared/src/main/java/com/termux/shared/logger/Logger.java
class Logger (line 21) | public class Logger {
method logMessage (line 56) | public static void logMessage(int logPriority, String tag, String mess...
method logExtendedMessage (line 69) | public static void logExtendedMessage(int logLevel, String tag, String...
method logError (line 105) | public static void logError(String tag, String message) {
method logError (line 109) | public static void logError(String message) {
method logErrorExtended (line 113) | public static void logErrorExtended(String tag, String message) {
method logErrorExtended (line 117) | public static void logErrorExtended(String message) {
method logErrorPrivate (line 123) | public static void logErrorPrivate(String tag, String message) {
method logErrorPrivate (line 128) | public static void logErrorPrivate(String message) {
method logErrorPrivateExtended (line 133) | public static void logErrorPrivateExtended(String tag, String message) {
method logErrorPrivateExtended (line 138) | public static void logErrorPrivateExtended(String message) {
method logWarn (line 145) | public static void logWarn(String tag, String message) {
method logWarn (line 149) | public static void logWarn(String message) {
method logWarnExtended (line 153) | public static void logWarnExtended(String tag, String message) {
method logWarnExtended (line 157) | public static void logWarnExtended(String message) {
method logInfo (line 163) | public static void logInfo(String tag, String message) {
method logInfo (line 167) | public static void logInfo(String message) {
method logInfoExtended (line 171) | public static void logInfoExtended(String tag, String message) {
method logInfoExtended (line 175) | public static void logInfoExtended(String message) {
method logDebug (line 181) | public static void logDebug(String tag, String message) {
method logDebug (line 185) | public static void logDebug(String message) {
method logDebugExtended (line 189) | public static void logDebugExtended(String tag, String message) {
method logDebugExtended (line 193) | public static void logDebugExtended(String message) {
method logVerbose (line 199) | public static void logVerbose(String tag, String message) {
method logVerbose (line 203) | public static void logVerbose(String message) {
method logVerboseExtended (line 207) | public static void logVerboseExtended(String tag, String message) {
method logVerboseExtended (line 211) | public static void logVerboseExtended(String message) {
method logVerboseForce (line 215) | public static void logVerboseForce(String tag, String message) {
method logInfoAndShowToast (line 221) | public static void logInfoAndShowToast(Context context, String tag, St...
method logInfoAndShowToast (line 228) | public static void logInfoAndShowToast(Context context, String message) {
method logErrorAndShowToast (line 234) | public static void logErrorAndShowToast(Context context, String tag, S...
method logErrorAndShowToast (line 241) | public static void logErrorAndShowToast(Context context, String messag...
method logDebugAndShowToast (line 247) | public static void logDebugAndShowToast(Context context, String tag, S...
method logDebugAndShowToast (line 254) | public static void logDebugAndShowToast(Context context, String messag...
method logStackTraceWithMessage (line 260) | public static void logStackTraceWithMessage(String tag, String message...
method logStackTraceWithMessage (line 264) | public static void logStackTraceWithMessage(String message, Throwable ...
method logStackTrace (line 268) | public static void logStackTrace(String tag, Throwable throwable) {
method logStackTrace (line 272) | public static void logStackTrace(Throwable throwable) {
method logStackTracesWithMessage (line 278) | public static void logStackTracesWithMessage(String tag, String messag...
method getMessageAndStackTraceString (line 284) | public static String getMessageAndStackTraceString(String message, Thr...
method getMessageAndStackTracesString (line 295) | public static String getMessageAndStackTracesString(String message, Li...
method getStackTraceString (line 308) | public static String getStackTraceString(Throwable throwable) {
method getStackTracesStringArray (line 329) | public static String[] getStackTracesStringArray(Throwable throwable) {
method getStackTracesStringArray (line 333) | public static String[] getStackTracesStringArray(List<Throwable> throw...
method getStackTracesString (line 344) | public static String getStackTracesString(String label, String[] stack...
method getStackTracesMarkdownString (line 362) | public static String getStackTracesMarkdownString(String label, String...
method getSingleLineLogStringEntry (line 382) | public static String getSingleLineLogStringEntry(String label, Object ...
method getMultiLineLogStringEntry (line 389) | public static String getMultiLineLogStringEntry(String label, Object o...
method showToast (line 398) | public static void showToast(final Context context, final String toast...
method getLogLevelsArray (line 406) | public static CharSequence[] getLogLevelsArray() {
method getLogLevelLabelsArray (line 415) | public static CharSequence[] getLogLevelLabelsArray(Context context, C...
method getLogLevelLabel (line 427) | public static String getLogLevelLabel(final Context context, final int...
method getDefaultLogTag (line 445) | @NonNull
method setDefaultLogTag (line 453) | public static void setDefaultLogTag(@NonNull String defaultLogTag) {
method getLogLevel (line 459) | public static int getLogLevel() {
method setLogLevel (line 463) | public static int setLogLevel(Context context, int logLevel) {
method getFullTag (line 481) | public static String getFullTag(String tag) {
method isLogLevelValid (line 488) | public static boolean isLogLevelValid(Integer logLevel) {
method shouldEnableLoggingForCustomLogLevel (line 494) | public static boolean shouldEnableLoggingForCustomLogLevel(Integer cus...
FILE: termux-shared/src/main/java/com/termux/shared/markdown/MarkdownUtils.java
class MarkdownUtils (line 40) | public class MarkdownUtils {
method getMarkdownCodeForString (line 53) | public static String getMarkdownCodeForString(String string, boolean c...
method getMaxConsecutiveBackTicksCount (line 89) | public static int getMaxConsecutiveBackTicksCount(String string) {
method getLiteralSingleLineMarkdownStringEntry (line 109) | public static String getLiteralSingleLineMarkdownStringEntry(String la...
method getSingleLineMarkdownStringEntry (line 113) | public static String getSingleLineMarkdownStringEntry(String label, Ob...
method getMultiLineMarkdownStringEntry (line 120) | public static String getMultiLineMarkdownStringEntry(String label, Obj...
method getLinkMarkdownString (line 127) | public static String getLinkMarkdownString(String label, String url) {
method getRecyclerMarkwonBuilder (line 140) | public static Markwon getRecyclerMarkwonBuilder(Context context) {
method getSpannedMarkwonBuilder (line 177) | public static Markwon getSpannedMarkwonBuilder(Context context) {
method getSpannedMarkdownText (line 201) | public static Spanned getSpannedMarkdownText(Context context, String s...
FILE: termux-shared/src/main/java/com/termux/shared/models/ReportInfo.java
class ReportInfo (line 13) | public class ReportInfo implements Serializable {
method ReportInfo (line 59) | public ReportInfo(String userAction, String sender, String reportTitle) {
method setReportStringPrefix (line 66) | public void setReportStringPrefix(String reportStringPrefix) {
method setReportString (line 70) | public void setReportString(String reportString) {
method setReportStringSuffix (line 74) | public void setReportStringSuffix(String reportStringSuffix) {
method setAddReportInfoHeaderToMarkdown (line 78) | public void setAddReportInfoHeaderToMarkdown(boolean addReportInfoHead...
method setReportSaveFileLabelAndPath (line 82) | public void setReportSaveFileLabelAndPath(String reportSaveFileLabel, ...
method setReportSaveFileLabel (line 87) | public void setReportSaveFileLabel(String reportSaveFileLabel) {
method setReportSaveFilePath (line 91) | public void setReportSaveFilePath(String reportSaveFilePath) {
method getReportInfoMarkdownString (line 101) | public static String getReportInfoMarkdownString(final ReportInfo repo...
FILE: termux-shared/src/main/java/com/termux/shared/models/TextIOInfo.java
class TextIOInfo (line 21) | public class TextIOInfo implements Serializable {
method TextIOInfo (line 98) | public TextIOInfo(@NonNull String action, @NonNull String sender) {
method getAction (line 104) | public String getAction() {
method getSender (line 108) | public String getSender() {
method getTitle (line 113) | public String getTitle() {
method setTitle (line 117) | public void setTitle(String title) {
method shouldShowBackButtonInActionBar (line 121) | public boolean shouldShowBackButtonInActionBar() {
method setShowBackButtonInActionBar (line 125) | public void setShowBackButtonInActionBar(boolean showBackButtonInActio...
method isLabelEnabled (line 130) | public boolean isLabelEnabled() {
method setLabelEnabled (line 134) | public void setLabelEnabled(boolean labelEnabled) {
method getLabel (line 138) | public String getLabel() {
method setLabel (line 142) | public void setLabel(String label) {
method getLabelSize (line 146) | public int getLabelSize() {
method setLabelSize (line 150) | public void setLabelSize(int labelSize) {
method getLabelColor (line 155) | public int getLabelColor() {
method setLabelColor (line 159) | public void setLabelColor(int labelColor) {
method getLabelTypeFaceFamily (line 163) | public String getLabelTypeFaceFamily() {
method setLabelTypeFaceFamily (line 167) | public void setLabelTypeFaceFamily(String labelTypeFaceFamily) {
method getLabelTypeFaceStyle (line 171) | public int getLabelTypeFaceStyle() {
method setLabelTypeFaceStyle (line 175) | public void setLabelTypeFaceStyle(int labelTypeFaceStyle) {
method getText (line 180) | public String getText() {
method setText (line 184) | public void setText(String text) {
method getTextSize (line 188) | public int getTextSize() {
method setTextSize (line 192) | public void setTextSize(int textSize) {
method getTextLengthLimit (line 197) | public int getTextLengthLimit() {
method setTextLengthLimit (line 201) | public void setTextLengthLimit(int textLengthLimit) {
method getTextColor (line 206) | public int getTextColor() {
method setTextColor (line 210) | public void setTextColor(int textColor) {
method getTextTypeFaceFamily (line 214) | public String getTextTypeFaceFamily() {
method setTextTypeFaceFamily (line 218) | public void setTextTypeFaceFamily(String textTypeFaceFamily) {
method getTextTypeFaceStyle (line 222) | public int getTextTypeFaceStyle() {
method setTextTypeFaceStyle (line 226) | public void setTextTypeFaceStyle(int textTypeFaceStyle) {
method isHorizontallyScrollable (line 230) | public boolean isHorizontallyScrollable() {
method setTextHorizontallyScrolling (line 234) | public void setTextHorizontallyScrolling(boolean textHorizontallyScrol...
method shouldShowTextCharacterUsage (line 238) | public boolean shouldShowTextCharacterUsage() {
method setShowTextCharacterUsage (line 242) | public void setShowTextCharacterUsage(boolean showTextCharacterUsage) {
method isEditingTextDisabled (line 246) | public boolean isEditingTextDisabled() {
method setEditingTextDisabled (line 250) | public void setEditingTextDisabled(boolean editingTextDisabled) {
FILE: termux-shared/src/main/java/com/termux/shared/net/socket/local/ILocalSocketManager.java
type ILocalSocketManager (line 11) | public interface ILocalSocketManager {
method getLocalSocketManagerClientThreadUEH (line 21) | @Nullable
method onError (line 39) | void onError(@NonNull LocalSocketManager localSocketManager,
method onDisallowedClientConnected (line 54) | void onDisallowedClientConnected(@NonNull LocalSocketManager localSock...
method onClientAccepted (line 69) | void onClientAccepted(@NonNull LocalSocketManager localSocketManager,
FILE: termux-shared/src/main/java/com/termux/shared/net/socket/local/LocalClientSocket.java
class LocalClientSocket (line 20) | public class LocalClientSocket implements Closeable {
method LocalClientSocket (line 55) | LocalClientSocket(@NonNull LocalSocketManager localSocketManager, int ...
method closeClientSocket (line 69) | public synchronized Error closeClientSocket(boolean logErrorMessage) {
method closeClientSocket (line 83) | public static void closeClientSocket(@NonNull LocalSocketManager local...
method close (line 88) | @Override
method read (line 123) | public Error read(@NonNull byte[] data, MutableInt bytesRead) {
method send (line 158) | public Error send(@NonNull byte[] data) {
method readDataOnInputStream (line 187) | public Error readDataOnInputStream(@NonNull StringBuilder data, boolea...
method sendDataToOutputStream (line 226) | public Error sendDataToOutputStream(@NonNull String data, boolean clos...
method available (line 257) | public Error available(MutableInt available) {
method available (line 265) | public Error available(MutableInt available, boolean checkDeadline) {
method setReadTimeout (line 290) | public Error setReadTimeout() {
method setWriteTimeout (line 303) | public Error setWriteTimeout() {
method getFD (line 318) | public int getFD() {
method setFD (line 323) | private void setFD(int fd) {
method getPeerCred (line 331) | public PeerCred getPeerCred() {
method getCreationTime (line 336) | public long getCreationTime() {
method getOutputStream (line 341) | public OutputStream getOutputStream() {
method getOutputStreamWriter (line 346) | @NonNull
method getInputStream (line 352) | public InputStream getInputStream() {
method getInputStreamReader (line 357) | @NonNull
method getLogString (line 365) | @NonNull
method getMarkdownString (line 380) | @NonNull
class MutableInt (line 399) | public static final class MutableInt {
method MutableInt (line 402) | public MutableInt(int value) {
class SocketInputStream (line 410) | protected class SocketInputStream extends InputStream {
method read (line 413) | @Override
method read (line 428) | @Override
method available (line 447) | @Override
class SocketOutputStream (line 461) | protected class SocketOutputStream extends OutputStream {
method write (line 464) | @Override
method write (line 474) | @Override
FILE: termux-shared/src/main/java/com/termux/shared/net/socket/local/LocalServerSocket.java
class LocalServerSocket (line 16) | public class LocalServerSocket implements Closeable {
method LocalServerSocket (line 44) | protected LocalServerSocket(@NonNull LocalSocketManager localSocketMan...
method start (line 52) | public synchronized Error start() {
method stop (line 127) | public synchronized Error stop() {
method closeServerSocket (line 143) | public synchronized Error closeServerSocket(boolean logErrorMessage) {
method close (line 159) | @Override
method deleteServerSocketFile (line 179) | private Error deleteServerSocketFile() {
method accept (line 187) | public LocalClientSocket accept() {
class ClientSocketListener (line 249) | protected class ClientSocketListener implements Runnable {
method run (line 251) | @Override
FILE: termux-shared/src/main/java/com/termux/shared/net/socket/local/LocalSocketErrno.java
class LocalSocketErrno (line 5) | public class LocalSocketErrno extends Errno {
method LocalSocketErrno (line 39) | LocalSocketErrno(final String type, final int code, final String messa...
FILE: termux-shared/src/main/java/com/termux/shared/net/socket/local/LocalSocketManager.java
class LocalSocketManager (line 23) | public class LocalSocketManager {
method LocalSocketManager (line 58) | public LocalSocketManager(@NonNull Context context, @NonNull LocalSock...
method start (line 70) | public synchronized Error start() {
method stop (line 92) | public synchronized Error stop() {
method createServerSocket (line 124) | @Nullable
method closeSocket (line 143) | @Nullable
method accept (line 163) | @Nullable
method read (line 191) | @Nullable
method send (line 215) | @Nullable
method available (line 234) | @Nullable
method setSocketReadTimeout (line 254) | @Nullable
method setSocketSendTimeout (line 274) | @Nullable
method getPeerCred (line 294) | @Nullable
method onError (line 308) | public void onError(@NonNull Error error) {
method onError (line 313) | public void onError(@Nullable LocalClientSocket clientSocket, @NonNull...
method onDisallowedClientConnected (line 319) | public void onDisallowedClientConnected(@NonNull LocalClientSocket cli...
method onClientAccepted (line 325) | public void onClientAccepted(@NonNull LocalClientSocket clientSocket) {
method startLocalSocketManagerClientThread (line 331) | public void startLocalSocketManagerClientThread(@NonNull Runnable runn...
method getContext (line 344) | public Context getContext() {
method getLocalSocketRunConfig (line 349) | public LocalSocketRunConfig getLocalSocketRunConfig() {
method getLocalSocketManagerClient (line 354) | public ILocalSocketManager getLocalSocketManagerClient() {
method getServerSocket (line 359) | public LocalServerSocket getServerSocket() {
method getLocalSocketManagerClientThreadUEH (line 364) | public Thread.UncaughtExceptionHandler getLocalSocketManagerClientThre...
method getLocalSocketManagerClientThreadUEHOrDefault (line 373) | protected Thread.UncaughtExceptionHandler getLocalSocketManagerClientT...
method isRunning (line 383) | public boolean isRunning() {
method getErrorLogString (line 390) | public static String getErrorLogString(@NonNull Error error,
method getErrorMarkdownString (line 410) | public static String getErrorMarkdownString(@NonNull Error error,
method createServerSocketNative (line 432) | @Nullable private static native JniResult createServerSocketNative(@No...
method closeSocketNative (line 434) | @Nullable private static native JniResult closeSocketNative(@NonNull S...
method acceptNative (line 436) | @Nullable private static native JniResult acceptNative(@NonNull String...
method readNative (line 438) | @Nullable private static native JniResult readNative(@NonNull String s...
method sendNative (line 440) | @Nullable private static native JniResult sendNative(@NonNull String s...
method availableNative (line 442) | @Nullable private static native JniResult availableNative(@NonNull Str...
method setSocketReadTimeoutNative (line 444) | private static native JniResult setSocketReadTimeoutNative(@NonNull St...
method setSocketSendTimeoutNative (line 446) | @Nullable private static native JniResult setSocketSendTimeoutNative(@...
method getPeerCredNative (line 448) | @Nullable private static native JniResult getPeerCredNative(@NonNull S...
FILE: termux-shared/src/main/java/com/termux/shared/net/socket/local/LocalSocketManagerClientBase.java
class LocalSocketManagerClientBase (line 10) | public abstract class LocalSocketManagerClientBase implements ILocalSock...
method getLocalSocketManagerClientThreadUEH (line 12) | @Nullable
method onError (line 19) | @Override
method onDisallowedClientConnected (line 28) | @Override
method onClientAccepted (line 36) | @Override
method getLogTag (line 45) | protected abstract String getLogTag();
FILE: termux-shared/src/main/java/com/termux/shared/net/socket/local/LocalSocketRunConfig.java
class LocalSocketRunConfig (line 16) | public class LocalSocketRunConfig implements Serializable {
method LocalSocketRunConfig (line 105) | public LocalSocketRunConfig(@NonNull String title, @NonNull String pat...
method getTitle (line 119) | public String getTitle() {
method getLogTitle (line 124) | public String getLogTitle() {
method getPath (line 129) | public String getPath() {
method isAbstractNamespaceSocket (line 134) | public boolean isAbstractNamespaceSocket() {
method getLocalSocketManagerClient (line 139) | public ILocalSocketManager getLocalSocketManagerClient() {
method getFD (line 144) | public Integer getFD() {
method setFD (line 149) | public void setFD(int fd) {
method getReceiveTimeout (line 157) | public Integer getReceiveTimeout() {
method setReceiveTimeout (line 162) | public void setReceiveTimeout(Integer receiveTimeout) {
method getSendTimeout (line 167) | public Integer getSendTimeout() {
method setSendTimeout (line 172) | public void setSendTimeout(Integer sendTimeout) {
method getDeadline (line 177) | public Long getDeadline() {
method setDeadline (line 182) | public void setDeadline(Long deadline) {
method getBacklog (line 187) | public Integer getBacklog() {
method setBacklog (line 192) | public void setBacklog(Integer backlog) {
method getRunConfigLogString (line 204) | @NonNull
method getLogString (line 211) | @NonNull
method getRunConfigMarkdownString (line 234) | public static String getRunConfigMarkdownString(final LocalSocketRunCo...
method getMarkdownString (line 240) | @NonNull
method toString (line 259) | @NonNull
FILE: termux-shared/src/main/java/com/termux/shared/net/socket/local/PeerCred.java
class PeerCred (line 14) | @Keep
method PeerCred (line 37) | PeerCred() {
method fillPeerCred (line 43) | public void fillPeerCred(@NonNull Context context) {
method fillUnameAndGname (line 49) | public void fillUnameAndGname(@NonNull Context context) {
method fillPname (line 59) | public void fillPname(@NonNull Context context) {
method getPeerCredLogString (line 73) | @NonNull
method getLogString (line 80) | @NonNull
method getPeerCredMarkdownString (line 101) | public static String getPeerCredMarkdownString(final PeerCred peerCred) {
method getMarkdownString (line 107) | @NonNull
method getMinimalString (line 122) | @NonNull
method getProcessString (line 127) | @NonNull
method getUserString (line 132) | @NonNull
method getGroupString (line 137) | @NonNull
FILE: termux-shared/src/main/java/com/termux/shared/net/uri/UriScheme.java
class UriScheme (line 11) | public class UriScheme {
FILE: termux-shared/src/main/java/com/termux/shared/net/uri/UriUtils.java
class UriUtils (line 11) | public class UriUtils {
method getUriFilePathWithFragment (line 28) | @Nullable
method getUriFileBasename (line 45) | @Nullable
method getFileUri (line 66) | public static Uri getFileUri(@NonNull String path) {
method getFileUri (line 77) | public static Uri getFileUri(@NonNull String authority, @NonNull Strin...
method getContentUri (line 87) | public static Uri getContentUri(@NonNull String path) {
method getContentUri (line 98) | public static Uri getContentUri(@NonNull String authority, @NonNull St...
FILE: termux-shared/src/main/java/com/termux/shared/net/url/UrlUtils.java
class UrlUtils (line 11) | public class UrlUtils {
type UrlPart (line 14) | public enum UrlPart {
method joinUrl (line 37) | @Nullable
method getUrl (line 55) | @Nullable
method getUrlPart (line 72) | @Nullable
method removeProtocol (line 102) | public static String removeProtocol(String urlString) {
method areUrlsEqual (line 107) | public static boolean areUrlsEqual(String url1, String url2) {
FILE: termux-shared/src/main/java/com/termux/shared/notification/NotificationUtils.java
class NotificationUtils (line 14) | public class NotificationUtils {
method getNotificationManager (line 43) | @Nullable
method geNotificationBuilder (line 65) | @Nullable
method setupNotificationChannel (line 98) | public static void setupNotificationChannel(final Context context, fin...
method setNotificationDefaults (line 108) | public static Notification.Builder setNotificationDefaults(Notificatio...
FILE: termux-shared/src/main/java/com/termux/shared/reflection/ReflectionUtils.java
class ReflectionUtils (line 17) | public class ReflectionUtils {
method bypassHiddenAPIReflectionRestrictions (line 28) | public static void bypassHiddenAPIReflectionRestrictions() {
method areHiddenAPIReflectionRestrictionsBypassed (line 42) | public static boolean areHiddenAPIReflectionRestrictionsBypassed() {
method getDeclaredField (line 57) | @Nullable
class FieldInvokeResult (line 72) | public static class FieldInvokeResult {
method FieldInvokeResult (line 76) | FieldInvokeResult(boolean success, Object value) {
method invokeField (line 95) | @NonNull
method getDeclaredMethod (line 114) | @Nullable
method getDeclaredMethod (line 127) | @Nullable
method invokeVoidMethod (line 144) | public static boolean invokeVoidMethod(@NonNull Method method, Object ...
method invokeVoidMethod (line 157) | public static boolean invokeVoidMethod(@NonNull Method method, Object ...
class MethodInvokeResult (line 171) | public static class MethodInvokeResult {
method MethodInvokeResult (line 175) | MethodInvokeResult(boolean success, Object value) {
method invokeMethod (line 184) | @NonNull
method invokeMethod (line 200) | @NonNull
method getConstructor (line 216) | @Nullable
method getConstructor (line 225) | @Nullable
method getConstructor (line 242) | @Nullable
method invokeConstructor (line 259) | @Nullable
method invokeConstructor (line 271) | @Nullable
FILE: termux-shared/src/main/java/com/termux/shared/settings/preferences/AppSharedPreferences.java
class AppSharedPreferences (line 10) | public class AppSharedPreferences {
method AppSharedPreferences (line 21) | protected AppSharedPreferences(@NonNull Context context, @Nullable Sha...
method AppSharedPreferences (line 25) | protected AppSharedPreferences(@NonNull Context context, @Nullable Sha...
method getContext (line 35) | public Context getContext() {
method getSharedPreferences (line 40) | public SharedPreferences getSharedPreferences() {
method getMultiProcessSharedPreferences (line 45) | public SharedPreferences getMultiProcessSharedPreferences() {
FILE: termux-shared/src/main/java/com/termux/shared/settings/preferences/SharedPreferenceUtils.java
class SharedPreferenceUtils (line 11) | public class SharedPreferenceUtils {
method getPrivateSharedPreferences (line 25) | public static SharedPreferences getPrivateSharedPreferences(Context co...
method getPrivateAndMultiProcessSharedPreferences (line 39) | public static SharedPreferences getPrivateAndMultiProcessSharedPrefere...
method getBoolean (line 54) | public static boolean getBoolean(SharedPreferences sharedPreferences, ...
method setBoolean (line 79) | @SuppressLint("ApplySharedPref")
method getFloat (line 104) | public static float getFloat(SharedPreferences sharedPreferences, Stri...
method setFloat (line 129) | @SuppressLint("ApplySharedPref")
method getInt (line 153) | public static int getInt(SharedPreferences sharedPreferences, String k...
method setInt (line 178) | @SuppressLint("ApplySharedPref")
method getAndIncrementInt (line 205) | @SuppressLint("ApplySharedPref")
method getLong (line 234) | public static long getLong(SharedPreferences sharedPreferences, String...
method setLong (line 259) | @SuppressLint("ApplySharedPref")
method getString (line 284) | public static String getString(SharedPreferences sharedPreferences, St...
method setString (line 313) | @SuppressLint("ApplySharedPref")
method getStringSet (line 337) | public static Set<String> getStringSet(SharedPreferences sharedPrefere...
method setStringSet (line 362) | @SuppressLint("ApplySharedPref")
method getIntStoredAsString (line 387) | public static int getIntStoredAsString(SharedPreferences sharedPrefere...
method setIntStoredAsString (line 419) | @SuppressLint("ApplySharedPref")
FILE: termux-shared/src/main/java/com/termux/shared/settings/properties/SharedProperties.java
class SharedProperties (line 45) | public class SharedProperties {
method SharedProperties (line 96) | public SharedProperties(@NonNull Context context, @Nullable File prope...
method loadPropertiesFromDisk (line 112) | public void loadPropertiesFromDisk() {
method getProperties (line 160) | public Properties getProperties(boolean cached) {
method getProperty (line 180) | public String getProperty(String key, boolean cached) {
method getInternalProperties (line 192) | public Map<String, Object> getInternalProperties() {
method getInternalProperty (line 209) | public Object getInternalProperty(String key) {
method getPropertiesFromFile (line 233) | public static Properties getPropertiesFromFile(Context context, File p...
method getPropertiesFileFromList (line 268) | public static File getPropertiesFileFromList(List<String> propertiesFi...
method getProperty (line 293) | public static String getProperty(Context context, File propertiesFile,...
method getProperty (line 308) | public static String getProperty(Context context, File propertiesFile,...
method getInternalProperty (line 323) | public static Object getInternalProperty(Context context, File propert...
method isPropertyValueTrue (line 332) | public static boolean isPropertyValueTrue(Context context, File proper...
method isPropertyValueTrue (line 350) | public static boolean isPropertyValueTrue(Context context, File proper...
method isPropertyValueFalse (line 355) | public static boolean isPropertyValueFalse(Context context, File prope...
method isPropertyValueFalse (line 373) | public static boolean isPropertyValueFalse(Context context, File prope...
method putToMap (line 392) | public static boolean putToMap(HashMap<String, Object> map, String key...
method putToProperties (line 435) | public static boolean putToProperties(Properties properties, String ke...
method getPropertiesCopy (line 458) | public static Properties getPropertiesCopy(Properties inputProperties) {
method getMapCopy (line 469) | public static Map<String, Object> getMapCopy(Map<String, Object> map) {
method getBooleanValueForStringValue (line 486) | public static Boolean getBooleanValueForStringValue(String value) {
method getBooleanValueForStringValue (line 501) | public static boolean getBooleanValueForStringValue(String key, String...
method getInvertedBooleanValueForStringValue (line 516) | public static boolean getInvertedBooleanValueForStringValue(String key...
method getDefaultIfNotInMap (line 535) | public static Object getDefaultIfNotInMap(String key, @NonNull BiMap<?...
method getDefaultIfNotInRange (line 570) | public static int getDefaultIfNotInRange(String key, int value, int de...
method getDefaultIfNotInRange (line 599) | public static float getDefaultIfNotInRange(String key, float value, fl...
method getDefaultIfNull (line 620) | public static <T> T getDefaultIfNull(@Nullable T object, @Nullable T d...
method getDefaultIfNullOrEmpty (line 631) | public static String getDefaultIfNullOrEmpty(@Nullable String object, ...
method toLowerCase (line 641) | public static String toLowerCase(String value) {
FILE: termux-shared/src/main/java/com/termux/shared/settings/properties/SharedPropertiesParser.java
type SharedPropertiesParser (line 13) | public interface SharedPropertiesParser {
method preProcessPropertiesOnReadFromDisk (line 23) | @NonNull
method getInternalPropertyValueFromValue (line 35) | Object getInternalPropertyValueFromValue(@NonNull Context context, Str...
FILE: termux-shared/src/main/java/com/termux/shared/shell/ArgumentTokenizer.java
class ArgumentTokenizer (line 51) | public abstract class ArgumentTokenizer {
method tokenize (line 61) | public static List<String> tokenize(String arguments) {
method tokenize (line 70) | public static List<String> tokenize(String arguments, boolean stringif...
method _escapeQuotesAndBackslashes (line 193) | protected static String _escapeQuotesAndBackslashes(String s) {
FILE: termux-shared/src/main/java/com/termux/shared/shell/ShellUtils.java
class ShellUtils (line 17) | public class ShellUtils {
method getPid (line 20) | public static int getPid(Process p) {
method setupShellCommandArguments (line 35) | @NonNull
method getExecutableBasename (line 44) | @Nullable
method getTerminalSessionTranscriptText (line 52) | public static String getTerminalSessionTranscriptText(TerminalSession ...
FILE: termux-shared/src/main/java/com/termux/shared/shell/StreamGobbler.java
class StreamGobbler (line 39) | @SuppressWarnings({"WeakerAccess"})
method incThreadCounter (line 42) | private static int incThreadCounter() {
type OnLineListener (line 53) | public interface OnLineListener {
method onLine (line 63) | void onLine(String line);
type OnStreamClosedListener (line 69) | public interface OnStreamClosedListener {
method onStreamClosed (line 73) | void onStreamClosed();
method StreamGobbler (line 110) | @AnyThread
method StreamGobbler (line 142) | @AnyThread
method StreamGobbler (line 173) | @AnyThread
method run (line 191) | @Override
method resumeGobbling (line 245) | @AnyThread
method suspendGobbling (line 260) | @AnyThread
method waitForSuspend (line 273) | @WorkerThread
method isSuspended (line 291) | @AnyThread
method getInputStream (line 303) | @NonNull
method getOnLineListener (line 314) | @Nullable
method conditionalJoin (line 320) | void conditionalJoin() throws InterruptedException {
FILE: termux-shared/src/main/java/com/termux/shared/shell/am/AmSocketServer.java
class AmSocketServer (line 60) | public class AmSocketServer {
method start (line 70) | public static synchronized LocalSocketManager start(@NonNull Context c...
method processAmClient (line 82) | public static void processAmClient(@NonNull LocalSocketManager localSo...
method sendResultToClient (line 136) | public static void sendResultToClient(@NonNull LocalSocketManager loca...
method sanitizeExitCode (line 162) | public static int sanitizeExitCode(@NonNull LocalClientSocket clientSo...
method parseAmCommand (line 183) | public static Error parseAmCommand(String amCommandString, List<String...
method runAmCommand (line 210) | public static Error runAmCommand(@NonNull Context context,
class AmSocketServerClient (line 247) | public abstract static class AmSocketServerClient extends LocalSocketM...
method onClientAccepted (line 249) | @Override
FILE: termux-shared/src/main/java/com/termux/shared/shell/am/AmSocketServerErrno.java
class AmSocketServerErrno (line 5) | public class AmSocketServerErrno extends Errno {
method AmSocketServerErrno (line 14) | AmSocketServerErrno(final String type, final int code, final String me...
FILE: termux-shared/src/main/java/com/termux/shared/shell/am/AmSocketServerRunConfig.java
class AmSocketServerRunConfig (line 17) | public class AmSocketServerRunConfig extends LocalSocketRunConfig implem...
method AmSocketServerRunConfig (line 36) | public AmSocketServerRunConfig(@NonNull String title, @NonNull String ...
method shouldCheckDisplayOverAppsPermission (line 42) | public boolean shouldCheckDisplayOverAppsPermission() {
method setCheckDisplayOverAppsPermission (line 47) | public void setCheckDisplayOverAppsPermission(Boolean checkDisplayOver...
method getRunConfigLogString (line 59) | @NonNull
method getLogString (line 66) | @NonNull
method getRunConfigMarkdownString (line 83) | public static String getRunConfigMarkdownString(final AmSocketServerRu...
method getMarkdownString (line 89) | @NonNull
method toString (line 102) | @NonNull
FILE: termux-shared/src/main/java/com/termux/shared/shell/command/ExecutionCommand.java
class ExecutionCommand (line 22) | public class ExecutionCommand {
type ExecutionState (line 33) | public enum ExecutionState {
method ExecutionState (line 44) | ExecutionState(final String name, final int value) {
method getName (line 49) | public String getName() {
method getValue (line 53) | public int getValue() {
type Runner (line 60) | public enum Runner {
method Runner (line 76) | Runner(final String name) {
method getName (line 80) | public String getName() {
method equalsRunner (line 84) | public boolean equalsRunner(String runner) {
method runnerOf (line 89) | @Nullable
method runnerOf (line 100) | @NonNull
type ShellCreateMode (line 108) | public enum ShellCreateMode {
method ShellCreateMode (line 118) | ShellCreateMode(final String mode) {
method getMode (line 122) | public String getMode() {
method equalsMode (line 126) | public boolean equalsMode(String sessionCreateMode) {
method modeOf (line 131) | @Nullable
method ExecutionCommand (line 241) | public ExecutionCommand() {
method ExecutionCommand (line 244) | public ExecutionCommand(Integer id) {
method ExecutionCommand (line 248) | public ExecutionCommand(Integer id, String executable, String[] argume...
method isPluginExecutionCommandWithPendingResult (line 259) | public boolean isPluginExecutionCommandWithPendingResult() {
method setState (line 264) | public synchronized boolean setState(ExecutionState newState) {
method hasExecuted (line 281) | public synchronized boolean hasExecuted() {
method isExecuting (line 285) | public synchronized boolean isExecuting() {
method isSuccessful (line 289) | public synchronized boolean isSuccessful() {
method setStateFailed (line 294) | public synchronized boolean setStateFailed(@NonNull Error error) {
method setStateFailed (line 298) | public synchronized boolean setStateFailed(@NonNull Error error, Throw...
method setStateFailed (line 301) | public synchronized boolean setStateFailed(@NonNull Error error, List<...
method setStateFailed (line 305) | public synchronized boolean setStateFailed(int code, String message) {
method setStateFailed (line 309) | public synchronized boolean setStateFailed(int code, String message, T...
method setStateFailed (line 313) | public synchronized boolean setStateFailed(int code, String message, L...
method setStateFailed (line 316) | public synchronized boolean setStateFailed(String type, int code, Stri...
method shouldNotProcessResults (line 324) | public synchronized boolean shouldNotProcessResults() {
method isStateFailed (line 333) | public synchronized boolean isStateFailed() {
method toString (line 346) | @NonNull
method getExecutionInputLogString (line 364) | public static String getExecutionInputLogString(final ExecutionCommand...
method getExecutionOutputLogString (line 424) | public static String getExecutionOutputLogString(final ExecutionComman...
method getDetailedLogString (line 446) | public static String getDetailedLogString(final ExecutionCommand execu...
method getExecutionCommandMarkdownString (line 467) | public static String getExecutionCommandMarkdownString(final Execution...
method getIdLogString (line 524) | public String getIdLogString() {
method getPidLogString (line 531) | public String getPidLogString() {
method getCurrentStateLogString (line 535) | public String getCurrentStateLogString() {
method getPreviousStateLogString (line 539) | public String getPreviousStateLogString() {
method getCommandLabelLogString (line 543) | public String getCommandLabelLogString() {
method getCommandIdAndLabelLogString (line 550) | public String getCommandIdAndLabelLogString() {
method getExecutableLogString (line 554) | public String getExecutableLogString() {
method getArgumentsLogString (line 558) | public String getArgumentsLogString() {
method getWorkingDirectoryLogString (line 562) | public String getWorkingDirectoryLogString() {
method getRunnerLogString (line 566) | public String getRunnerLogString() {
method getIsFailsafeLogString (line 570) | public String getIsFailsafeLogString() {
method getStdinLogString (line 574) | public String getStdinLogString() {
method getBackgroundCustomLogLevelLogString (line 581) | public String getBackgroundCustomLogLevelLogString() {
method getSessionActionLogString (line 585) | public String getSessionActionLogString() {
method getShellNameLogString (line 589) | public String getShellNameLogString() {
method getShellCreateModeLogString (line 593) | public String getShellCreateModeLogString() {
method getSetRunnerShellEnvironmentLogString (line 597) | public String getSetRunnerShellEnvironmentLogString() {
method getCommandDescriptionLogString (line 601) | public String getCommandDescriptionLogString() {
method getCommandHelpLogString (line 605) | public String getCommandHelpLogString() {
method getPluginAPIHelpLogString (line 609) | public String getPluginAPIHelpLogString() {
method getCommandIntentLogString (line 613) | public String getCommandIntentLogString() {
method getIsPluginExecutionCommandLogString (line 620) | public String getIsPluginExecutionCommandLogString() {
method getArgumentsLogString (line 639) | public static String getArgumentsLogString(String label, final String[...
method getArgumentsMarkdownString (line 676) | public static String getArgumentsMarkdownString(String label, final St...
FILE: termux-shared/src/main/java/com/termux/shared/shell/command/ShellCommandConstants.java
class ShellCommandConstants (line 9) | public class ShellCommandConstants {
class RESULT_SENDER (line 14) | public static final class RESULT_SENDER {
FILE: termux-shared/src/main/java/com/termux/shared/shell/command/environment/AndroidShellEnvironment.java
class AndroidShellEnvironment (line 21) | public class AndroidShellEnvironment extends UnixShellEnvironment {
method AndroidShellEnvironment (line 25) | public AndroidShellEnvironment() {
method getEnvironment (line 30) | @NonNull
method getDefaultWorkingDirectoryPath (line 69) | @NonNull
method getDefaultBinPath (line 76) | @NonNull
method setupShellCommandEnvironment (line 82) | @NonNull
FILE: termux-shared/src/main/java/com/termux/shared/shell/command/environment/IShellEnvironment.java
type IShellEnvironment (line 12) | public interface IShellEnvironment {
method getDefaultWorkingDirectoryPath (line 20) | @NonNull
method getDefaultBinPath (line 28) | @NonNull
method setupShellCommandArguments (line 38) | @NonNull
method setupShellCommandEnvironment (line 48) | @NonNull
FILE: termux-shared/src/main/java/com/termux/shared/shell/command/environment/ShellCommandShellEnvironment.java
class ShellCommandShellEnvironment (line 14) | public class ShellCommandShellEnvironment {
method getEnvironment (line 46) | @NonNull
FILE: termux-shared/src/main/java/com/termux/shared/shell/command/environment/ShellEnvironmentUtils.java
class ShellEnvironmentUtils (line 18) | public class ShellEnvironmentUtils {
method convertEnvironmentToEnviron (line 33) | @NonNull
method convertEnvironmentToDotEnvFile (line 49) | @NonNull
method convertEnvironmentToDotEnvFile (line 73) | @NonNull
method convertEnvironmentMapToEnvironmentVariableList (line 91) | @NonNull
method isValidEnvironmentVariableNameValuePair (line 107) | public static boolean isValidEnvironmentVariableNameValuePair(@Nullabl...
method isValidEnvironmentVariableName (line 128) | public static boolean isValidEnvironmentVariableName(@Nullable String ...
method isValidEnvironmentVariableValue (line 136) | public static boolean isValidEnvironmentVariableValue(@Nullable String...
method putToEnvIfInSystemEnv (line 143) | public static void putToEnvIfInSystemEnv(@NonNull HashMap<String, Stri...
method putToEnvIfSet (line 152) | public static void putToEnvIfSet(@NonNull HashMap<String, String> envi...
method putToEnvIfSet (line 160) | public static void putToEnvIfSet(@NonNull HashMap<String, String> envi...
method createHomeDir (line 170) | public static void createHomeDir(@NonNull HashMap<String, String> envi...
FILE: termux-shared/src/main/java/com/termux/shared/shell/command/environment/ShellEnvironmentVariable.java
class ShellEnvironmentVariable (line 3) | public class ShellEnvironmentVariable implements Comparable<ShellEnviron...
method ShellEnvironmentVariable (line 14) | public ShellEnvironmentVariable(String name, String value) {
method ShellEnvironmentVariable (line 18) | public ShellEnvironmentVariable(String name, String value, boolean esc...
method compareTo (line 24) | @Override
FILE: termux-shared/src/main/java/com/termux/shared/shell/command/environment/UnixShellEnvironment.java
class UnixShellEnvironment (line 19) | public abstract class UnixShellEnvironment implements IShellEnvironment {
method getEnvironment (line 60) | @NonNull
method getDefaultWorkingDirectoryPath (line 64) | @NonNull
method getDefaultBinPath (line 68) | @NonNull
method setupShellCommandArguments (line 72) | @NonNull
method setupShellCommandEnvironment (line 78) | @NonNull
FILE: termux-shared/src/main/java/com/termux/shared/shell/command/result/ResultConfig.java
class ResultConfig (line 12) | public class ResultConfig {
method ResultConfig (line 54) | public ResultConfig() {
method isCommandWithPendingResult (line 58) | public boolean isCommandWithPendingResult() {
method toString (line 63) | @NonNull
method getResultConfigLogString (line 76) | public static String getResultConfigLogString(final ResultConfig resul...
method getResultPendingIntentVariablesLogString (line 95) | public String getResultPendingIntentVariablesLogString(boolean ignoreN...
method getResultDirectoryVariablesLogString (line 122) | public String getResultDirectoryVariablesLogString(boolean ignoreNull) {
method getResultConfigMarkdownString (line 148) | public static String getResultConfigMarkdownString(final ResultConfig ...
FILE: termux-shared/src/main/java/com/termux/shared/shell/command/result/ResultData.java
class ResultData (line 16) | public class ResultData implements Serializable {
method ResultData (line 29) | public ResultData() {
method clearStdout (line 33) | public void clearStdout() {
method prependStdout (line 37) | public StringBuilder prependStdout(String message) {
method prependStdoutLn (line 41) | public StringBuilder prependStdoutLn(String message) {
method appendStdout (line 45) | public StringBuilder appendStdout(String message) {
method appendStdoutLn (line 49) | public StringBuilder appendStdoutLn(String message) {
method clearStderr (line 54) | public void clearStderr() {
method prependStderr (line 58) | public StringBuilder prependStderr(String message) {
method prependStderrLn (line 62) | public StringBuilder prependStderrLn(String message) {
method appendStderr (line 66) | public StringBuilder appendStderr(String message) {
method appendStderrLn (line 70) | public StringBuilder appendStderrLn(String message) {
method setStateFailed (line 75) | public synchronized boolean setStateFailed(@NonNull Error error) {
method setStateFailed (line 79) | public synchronized boolean setStateFailed(@NonNull Error error, Throw...
method setStateFailed (line 82) | public synchronized boolean setStateFailed(@NonNull Error error, List<...
method setStateFailed (line 86) | public synchronized boolean setStateFailed(int code, String message) {
method setStateFailed (line 90) | public synchronized boolean setStateFailed(int code, String message, T...
method setStateFailed (line 94) | public synchronized boolean setStateFailed(int code, String message, L...
method setStateFailed (line 98) | public synchronized boolean setStateFailed(String type, int code, Stri...
method isStateFailed (line 108) | public boolean isStateFailed() {
method getErrCode (line 118) | public int getErrCode() {
method toString (line 126) | @NonNull
method getResultDataLogString (line 139) | public static String getResultDataLogString(final ResultData resultDat...
method getStdoutLogString (line 157) | public String getStdoutLogString() {
method getStderrLogString (line 164) | public String getStderrLogString() {
method getExitCodeLogString (line 171) | public String getExitCodeLogString() {
method getErrorsListLogString (line 175) | public static String getErrorsListLogString(final ResultData resultDat...
method getResultDataMarkdownString (line 199) | public static String getResultDataMarkdownString(final ResultData resu...
method getErrorsListMarkdownString (line 222) | public static String getErrorsListMarkdownString(final ResultData resu...
method getErrorsListMinimalString (line 240) | public static String getErrorsListMinimalString(final ResultData resul...
FILE: termux-shared/src/main/java/com/termux/shared/shell/command/result/ResultSender.java
class ResultSender (line 19) | public class ResultSender {
method sendCommandResultData (line 38) | public static Error sendCommandResultData(Context context, String logT...
method sendCommandResultDataWithPendingIntent (line 69) | public static Error sendCommandResultDataWithPendingIntent(Context con...
method sendCommandResultDataToDirectory (line 160) | public static Error sendCommandResultDataToDirectory(Context context, ...
FILE: termux-shared/src/main/java/com/termux/shared/shell/command/result/ResultSenderErrno.java
class ResultSenderErrno (line 6) | public class ResultSenderErrno extends Errno {
method ResultSenderErrno (line 18) | ResultSenderErrno(final String type, final int code, final String mess...
FILE: termux-shared/src/main/java/com/termux/shared/shell/command/runner/app/AppShell.java
class AppShell (line 37) | public final class AppShell {
method AppShell (line 45) | private AppShell(@NonNull final Process process, @NonNull final Execut...
method execute (line 78) | public static AppShell execute(@NonNull final Context currentPackageCo...
method executeInner (line 170) | private void executeInner(@NonNull final Context context) throws Illeg...
method killIfExecuting (line 256) | public void killIfExecuting(@NonNull final Context context, boolean pr...
method kill (line 280) | public void kill() {
method processAppShellResult (line 305) | private static void processAppShellResult(final AppShell appShell, Exe...
method getProcess (line 328) | public Process getProcess() {
method getExecutionCommand (line 332) | public ExecutionCommand getExecutionCommand() {
type AppShellClient (line 338) | public interface AppShellClient {
method onAppShellExited (line 345) | void onAppShellExited(AppShell appShell);
FILE: termux-shared/src/main/java/com/termux/shared/termux/TermuxBootstrap.java
class TermuxBootstrap (line 11) | public class TermuxBootstrap {
method setTermuxPackageManagerAndVariant (line 27) | public static void setTermuxPackageManagerAndVariant(@Nullable String ...
method setTermuxPackageManagerAndVariantFromTermuxApp (line 55) | public static void setTermuxPackageManagerAndVariantFromTermuxApp(@Non...
method getTermuxAppBuildConfigPackageVariantFromTermuxApp (line 73) | public static String getTermuxAppBuildConfigPackageVariantFromTermuxAp...
method isAppPackageManagerAPT (line 85) | public static boolean isAppPackageManagerAPT() {
method isAppPackageVariantAPTAndroid7 (line 102) | public static boolean isAppPackageVariantAPTAndroid7() {
method isAppPackageVariantAPTAndroid5 (line 107) | public static boolean isAppPackageVariantAPTAndroid5() {
type PackageManager (line 124) | public enum PackageManager {
method PackageManager (line 148) | PackageManager(final String name) {
method getName (line 152) | public String getName() {
method equalsManager (line 156) | public boolean equalsManager(String manager) {
method managerOf (line 161) | @Nullable
type PackageVariant (line 177) | public enum PackageVariant {
method PackageVariant (line 193) | PackageVariant(final String name) {
method getName (line 197) | public String getName() {
method equalsVariant (line 201) | public boolean equalsVariant(String variant) {
method variantOf (line 206) | @Nullable
FILE: termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java
class TermuxConstants (line 326) | public final class TermuxConstants {
class TERMUX_APP (line 918) | public static final class TERMUX_APP {
class TERMUX_ACTIVITY (line 943) | public static final class TERMUX_ACTIVITY {
class TERMUX_SERVICE (line 984) | public static final class TERMUX_SERVICE {
class RUN_COMMAND_SERVICE (line 1128) | public static final class RUN_COMMAND_SERVICE {
class TERMUX_API_APP (line 1200) | public static final class TERMUX_API_APP {
class TERMUX_BOOT_APP (line 1217) | public static final class TERMUX_BOOT_APP {
class TERMUX_FLOAT_APP (line 1234) | public static final class TERMUX_FLOAT_APP {
class TERMUX_FLOAT_SERVICE (line 1245) | public static final class TERMUX_FLOAT_SERVICE {
class TERMUX_STYLING_APP (line 1267) | public static final class TERMUX_STYLING_APP {
class TERMUX_TASKER_APP (line 1288) | public static final class TERMUX_TASKER_APP {
class TERMUX_WIDGET_APP (line 1305) | public static final class TERMUX_WIDGET_APP {
class TERMUX_WIDGET_PROVIDER (line 1321) | public static final class TERMUX_WIDGET_PROVIDER {
FILE: termux-shared/src/main/java/com/termux/shared/termux/TermuxUtils.java
class TermuxUtils (line 37) | public class TermuxUtils {
type AppInfoMode (line 40) | public enum AppInfoMode {
method getTermuxPackageContext (line 62) | public static Context getTermuxPackageContext(@NonNull Context context) {
method getTermuxPackageContextWithCode (line 73) | public static Context getTermuxPackageContextWithCode(@NonNull Context...
method getTermuxAPIPackageContext (line 83) | public static Context getTermuxAPIPackageContext(@NonNull Context cont...
method getTermuxBootPackageContext (line 93) | public static Context getTermuxBootPackageContext(@NonNull Context con...
method getTermuxFloatPackageContext (line 103) | public static Context getTermuxFloatPackageContext(@NonNull Context co...
method getTermuxStylingPackageContext (line 113) | public static Context getTermuxStylingPackageContext(@NonNull Context ...
method getTermuxTaskerPackageContext (line 123) | public static Context getTermuxTaskerPackageContext(@NonNull Context c...
method getTermuxWidgetPackageContext (line 133) | public static Context getTermuxWidgetPackageContext(@NonNull Context c...
method getContextForPackageOrExitApp (line 138) | public static Context getContextForPackageOrExitApp(@NonNull Context c...
method isTermuxAppInstalled (line 167) | public static String isTermuxAppInstalled(@NonNull final Context conte...
method isTermuxAPIAppInstalled (line 179) | public static String isTermuxAPIAppInstalled(@NonNull final Context co...
method isTermuxAppAccessible (line 198) | public static String isTermuxAppAccessible(@NonNull final Context curr...
method getTermuxAppAPKBuildConfigClassField (line 236) | public static Object getTermuxAppAPKBuildConfigClassField(@NonNull Con...
method getTermuxAppAPKClassField (line 260) | public static Object getTermuxAppAPKClassField(@NonNull Context curren...
method isUriDataForTermuxOrPluginPackage (line 278) | public static boolean isUriDataForTermuxOrPluginPackage(@NonNull Uri d...
method isUriDataForTermuxPluginPackage (line 284) | public static boolean isUriDataForTermuxPluginPackage(@NonNull Uri dat...
method sendTermuxOpenedBroadcast (line 294) | public static void sendTermuxOpenedBroadcast(@NonNull Context context) {
method getAppInfoMarkdownString (line 318) | public static String getAppInfoMarkdownString(final Context currentPac...
method getAppInfoMarkdownString (line 335) | public static String getAppInfoMarkdownString(final Context currentPac...
method getTermuxPluginAppsInfoMarkdownString (line 394) | public static String getTermuxPluginAppsInfoMarkdownString(final Conte...
method getAppInfoMarkdownString (line 431) | public static String getAppInfoMarkdownString(final Context currentPac...
method getAppInfoMarkdownStringInner (line 474) | public static String getAppInfoMarkdownStringInner(@NonNull final Cont...
method getReportIssueMarkdownString (line 506) | public static String getReportIssueMarkdownString(@NonNull final Conte...
method getImportantLinksMarkdownString (line 544) | public static String getImportantLinksMarkdownString(@NonNull final Co...
method geAPTInfoMarkdownString (line 587) | public static String geAPTInfoMarkdownString(@NonNull final Context co...
method getTermuxDebugMarkdownString (line 636) | public static String getTermuxDebugMarkdownString(@NonNull final Conte...
method getLogcatDumpMarkdownString (line 655) | public static String getLogcatDumpMarkdownString(@NonNull final Contex...
method getAPKRelease (line 701) | public static String getAPKRelease(String signingCertificateSHA256Dige...
method getTermuxAppPID (line 726) | public static String getTermuxAppPID(final Context context) {
FILE: termux-shared/src/main/java/com/termux/shared/termux/crash/TermuxCrashUtils.java
class TermuxCrashUtils (line 34) | public class TermuxCrashUtils implements CrashHandler.CrashHandlerClient {
type TYPE (line 36) | public enum TYPE {
method TermuxCrashUtils (line 45) | TermuxCrashUtils(TYPE type) {
method setDefaultCrashHandler (line 53) | public static void setDefaultCrashHandler(@NonNull final Context conte...
method setCrashHandler (line 61) | public static void setCrashHandler(@NonNull final Context context) {
method getCrashHandler (line 69) | public static CrashHandler getCrashHandler(@NonNull final Context cont...
method logCrash (line 80) | public static void logCrash(@NonNull final Context context, final Thro...
method onPreLogCrash (line 85) | @Override
method onPostLogCrash (line 90) | @Override
method getCrashLogFilePath (line 118) | @NonNull
method getAppInfoMarkdownString (line 124) | @Override
method notifyAppCrashFromCrashLogFile (line 144) | public static void notifyAppCrashFromCrashLogFile(final Context curren...
method notifyAppCrashFromCrashLogFileInner (line 169) | private static synchronized void notifyAppCrashFromCrashLogFileInner(f...
method sendCrashReportNotification (line 214) | public static void sendCrashReportNotification(final Context currentPa...
method sendCrashReportNotification (line 232) | public static void sendCrashReportNotification(final Context currentPa...
method sendCrashReportNotification (line 256) | public static void sendCrashReportNotification(final Context currentPa...
method sendCrashReportNotification (line 284) | public static void sendCrashReportNotification(final Context currentPa...
method getCrashReportsNotificationBuilder (line 384) | @Nullable
method setupCrashReportsNotificationChannel (line 405) | public static void setupCrashReportsNotificationChannel(final Context ...
FILE: termux-shared/src/main/java/com/termux/shared/termux/data/TermuxUrlUtils.java
class TermuxUrlUtils (line 7) | public class TermuxUrlUtils {
method getUrlMatchRegex (line 11) | public static Pattern getUrlMatchRegex() {
method extractUrls (line 90) | public static LinkedHashSet<CharSequence> extractUrls(String text) {
FILE: termux-shared/src/main/java/com/termux/shared/termux/extrakeys/ExtraKeyButton.java
class ExtraKeyButton (line 14) | public class ExtraKeyButton {
method ExtraKeyButton (line 62) | public ExtraKeyButton(@NonNull JSONObject config,
method ExtraKeyButton (line 79) | public ExtraKeyButton(@NonNull JSONObject config, @Nullable ExtraKeyBu...
method getStringFromJson (line 115) | public String getStringFromJson(@NonNull JSONObject config, @NonNull S...
method getKey (line 124) | public String getKey() {
method isMacro (line 129) | public boolean isMacro() {
method getDisplay (line 134) | public String getDisplay() {
method getPopup (line 139) | @Nullable
method replaceAlias (line 147) | public static String replaceAlias(@NonNull ExtraKeysConstants.ExtraKey...
FILE: termux-shared/src/main/java/com/termux/shared/termux/extrakeys/ExtraKeysConstants.java
class ExtraKeysConstants (line 10) | public class ExtraKeysConstants {
class CleverMap (line 57) | static class CleverMap<K,V> extends HashMap<K,V> {
method get (line 58) | V get(K key, V defaultValue) {
class ExtraKeyDisplayMap (line 66) | public static class ExtraKeyDisplayMap extends CleverMap<String, Strin...
class EXTRA_KEY_DISPLAY_MAPS (line 75) | public static class EXTRA_KEY_DISPLAY_MAPS {
FILE: termux-shared/src/main/java/com/termux/shared/termux/extrakeys/ExtraKeysInfo.java
class ExtraKeysInfo (line 89) | public class ExtraKeysInfo {
method ExtraKeysInfo (line 109) | public ExtraKeysInfo(@NonNull String propertiesInfo, String style,
method ExtraKeysInfo (line 128) | public ExtraKeysInfo(@NonNull String propertiesInfo,
method initExtraKeysInfo (line 134) | private ExtraKeyButton[][] initExtraKeysInfo(@NonNull String propertie...
method normalizeKeyConfig (line 180) | private static JSONObject normalizeKeyConfig(Object key) throws JSONEx...
method getMatrix (line 193) | public ExtraKeyButton[][] getMatrix() {
me
Condensed preview — 318 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,341K chars).
[
{
"path": ".editorconfig",
"chars": 442,
"preview": "# Copying and distribution of this file, with or without modification,\n# are permitted in any medium without royalty pro"
},
{
"path": ".gitattributes",
"chars": 120,
"preview": "* text=auto\n*.bat text eol=crlf\n*.gradle text eol=lf\n*.mk text eol=lf\n*.sh text eol=lf\n"
},
{
"path": ".github/FUNDING.yml",
"chars": 34,
"preview": "custom: https://termux.dev/donate\n"
},
{
"path": ".github/ISSUE_TEMPLATE/01-bug-report.yml",
"chars": 1865,
"preview": "name: \"Bug report\"\ndescription: \"Create a report to help us improve\"\ntitle: \"[Bug]: \"\nlabels: [\"bug report\"]\nbody:\n - t"
},
{
"path": ".github/ISSUE_TEMPLATE/02-feature-request.yml",
"chars": 552,
"preview": "name: \"Feature request\"\ndescription: \"Suggest a new feature for Termux application\"\ntitle: \"[Feature]: \"\nlabels: [\"featu"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 184,
"preview": "blank_issues_enabled: false\ncontact_links:\n - name: Want ask questions about the project?\n url: https://github.com/t"
},
{
"path": ".github/dependabot.yml",
"chars": 193,
"preview": "version: 2\nupdates:\n- package-ecosystem: github-actions\n directory: /\n schedule:\n interval: daily\n commit-message:"
},
{
"path": ".github/workflows/attach_debug_apks_to_release.yml",
"chars": 3584,
"preview": "name: Attach Debug APKs To Release\n\non:\n release:\n types:\n - published\n\njobs:\n attach-apks:\n runs-on: ubunt"
},
{
"path": ".github/workflows/debug_build.yml",
"chars": 5554,
"preview": "name: Build\n\non:\n push:\n branches:\n - master\n - 'github-releases/**'\n pull_request:\n branches:\n -"
},
{
"path": ".github/workflows/dependency-submission.yml",
"chars": 489,
"preview": "name: Automatic Dependency Submission\n\non:\n push:\n branches: [ 'master' ]\n workflow_dispatch:\n\npermissions:\n conte"
},
{
"path": ".github/workflows/gradle-wrapper-validation.yml",
"chars": 323,
"preview": "name: \"Validate Gradle Wrapper\"\n\non:\n push:\n branches:\n - master\n - android-10\n pull_request:\n branche"
},
{
"path": ".github/workflows/run_tests.yml",
"chars": 452,
"preview": "name: Unit tests\n\non:\n push:\n branches:\n - master\n - android-10\n pull_request:\n branches:\n - mast"
},
{
"path": ".github/workflows/trigger_library_builds_on_jitpack.yml",
"chars": 1114,
"preview": "name: Trigger Termux Library Builds on Jitpack\n\non:\n release:\n types:\n - published\n\njobs:\n trigger-termux-libr"
},
{
"path": ".gitignore",
"chars": 455,
"preview": "# From https://gist.github.com/iainconnor/8605514\n# with the addition of the /captures below.\n/captures\n\n# Built applica"
},
{
"path": "LICENSE.md",
"chars": 533,
"preview": "The `termux/termux-app` repository is released under [GPLv3 only](https://www.gnu.org/licenses/gpl-3.0.html) license.\n\n#"
},
{
"path": "README.md",
"chars": 25971,
"preview": "# Termux application\n\n[](https://github.c"
},
{
"path": "SECURITY.md",
"chars": 106,
"preview": "Check https://termux.dev/security for info on Termux security policies and how to report vulnerabilities.\n"
},
{
"path": "app/build.gradle",
"chars": 10316,
"preview": "plugins {\n id \"com.android.application\"\n}\n\next {\n // The packageVariant defines the bootstrap variant that will be"
},
{
"path": "app/proguard-rules.pro",
"chars": 462,
"preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in an"
},
{
"path": "app/src/main/AndroidManifest.xml",
"chars": 9762,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:to"
},
{
"path": "app/src/main/cpp/Android.mk",
"chars": 179,
"preview": "LOCAL_PATH:= $(call my-dir)\ninclude $(CLEAR_VARS)\nLOCAL_MODULE := libtermux-bootstrap\nLOCAL_SRC_FILES := termux-bootstra"
},
{
"path": "app/src/main/cpp/termux-bootstrap-zip.S",
"chars": 385,
"preview": " .global blob\n .global blob_size\n .section .rodata\n blob:\n #if defined __i686__\n .incbin \"bootstrap-i686"
},
{
"path": "app/src/main/cpp/termux-bootstrap.c",
"chars": 330,
"preview": "#include <jni.h>\n\nextern jbyte blob[];\nextern int blob_size;\n\nJNIEXPORT jbyteArray JNICALL Java_com_termux_app_TermuxIns"
},
{
"path": "app/src/main/java/com/termux/app/RunCommandService.java",
"chars": 16976,
"preview": "package com.termux.app;\n\nimport android.app.Notification;\nimport android.app.NotificationManager;\nimport android.app.Ser"
},
{
"path": "app/src/main/java/com/termux/app/TermuxActivity.java",
"chars": 39697,
"preview": "package com.termux.app;\n\nimport android.annotation.SuppressLint;\nimport android.app.AlertDialog;\nimport android.content."
},
{
"path": "app/src/main/java/com/termux/app/TermuxApplication.java",
"chars": 3572,
"preview": "package com.termux.app;\n\nimport android.app.Application;\nimport android.content.Context;\n\nimport com.termux.BuildConfig;"
},
{
"path": "app/src/main/java/com/termux/app/TermuxInstaller.java",
"chars": 21656,
"preview": "package com.termux.app;\n\nimport android.app.Activity;\nimport android.app.AlertDialog;\nimport android.app.ProgressDialog;"
},
{
"path": "app/src/main/java/com/termux/app/TermuxOpenReceiver.java",
"chars": 9507,
"preview": "package com.termux.app;\n\nimport android.content.ActivityNotFoundException;\nimport android.content.BroadcastReceiver;\nimp"
},
{
"path": "app/src/main/java/com/termux/app/TermuxService.java",
"chars": 46738,
"preview": "package com.termux.app;\n\nimport android.annotation.SuppressLint;\nimport android.app.Notification;\nimport android.app.Not"
},
{
"path": "app/src/main/java/com/termux/app/activities/HelpActivity.java",
"chars": 2679,
"preview": "package com.termux.app.activities;\n\nimport android.content.ActivityNotFoundException;\nimport android.content.Intent;\nimp"
},
{
"path": "app/src/main/java/com/termux/app/activities/SettingsActivity.java",
"chars": 8149,
"preview": "package com.termux.app.activities;\n\nimport android.content.Context;\nimport android.os.Bundle;\nimport android.os.Environm"
},
{
"path": "app/src/main/java/com/termux/app/api/file/FileReceiverActivity.java",
"chars": 12912,
"preview": "package com.termux.app.api.file;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.database"
},
{
"path": "app/src/main/java/com/termux/app/event/SystemEventReceiver.java",
"chars": 3614,
"preview": "package com.termux.app.event;\n\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android."
},
{
"path": "app/src/main/java/com/termux/app/fragments/settings/TermuxAPIPreferencesFragment.java",
"chars": 1541,
"preview": "package com.termux.app.fragments.settings;\n\nimport android.content.Context;\nimport android.os.Bundle;\n\nimport androidx.a"
},
{
"path": "app/src/main/java/com/termux/app/fragments/settings/TermuxFloatPreferencesFragment.java",
"chars": 1563,
"preview": "package com.termux.app.fragments.settings;\n\nimport android.content.Context;\nimport android.os.Bundle;\n\nimport androidx.a"
},
{
"path": "app/src/main/java/com/termux/app/fragments/settings/TermuxPreferencesFragment.java",
"chars": 1507,
"preview": "package com.termux.app.fragments.settings;\n\nimport android.content.Context;\nimport android.os.Bundle;\n\nimport androidx.a"
},
{
"path": "app/src/main/java/com/termux/app/fragments/settings/TermuxTaskerPreferencesFragment.java",
"chars": 1574,
"preview": "package com.termux.app.fragments.settings;\n\nimport android.content.Context;\nimport android.os.Bundle;\n\nimport androidx.a"
},
{
"path": "app/src/main/java/com/termux/app/fragments/settings/TermuxWidgetPreferencesFragment.java",
"chars": 1574,
"preview": "package com.termux.app.fragments.settings;\n\nimport android.content.Context;\nimport android.os.Bundle;\n\nimport androidx.a"
},
{
"path": "app/src/main/java/com/termux/app/fragments/settings/termux/DebuggingPreferencesFragment.java",
"chars": 5247,
"preview": "package com.termux.app.fragments.settings.termux;\n\nimport android.content.Context;\nimport android.os.Bundle;\n\nimport and"
},
{
"path": "app/src/main/java/com/termux/app/fragments/settings/termux/TerminalIOPreferencesFragment.java",
"chars": 2534,
"preview": "package com.termux.app.fragments.settings.termux;\n\nimport android.content.Context;\nimport android.os.Bundle;\n\nimport and"
},
{
"path": "app/src/main/java/com/termux/app/fragments/settings/termux/TerminalViewPreferencesFragment.java",
"chars": 2277,
"preview": "package com.termux.app.fragments.settings.termux;\n\nimport android.content.Context;\nimport android.os.Bundle;\n\nimport and"
},
{
"path": "app/src/main/java/com/termux/app/fragments/settings/termux_api/DebuggingPreferencesFragment.java",
"chars": 3326,
"preview": "package com.termux.app.fragments.settings.termux_api;\n\nimport android.content.Context;\nimport android.os.Bundle;\n\nimport"
},
{
"path": "app/src/main/java/com/termux/app/fragments/settings/termux_float/DebuggingPreferencesFragment.java",
"chars": 4067,
"preview": "package com.termux.app.fragments.settings.termux_float;\n\nimport android.content.Context;\nimport android.os.Bundle;\n\nimpo"
},
{
"path": "app/src/main/java/com/termux/app/fragments/settings/termux_tasker/DebuggingPreferencesFragment.java",
"chars": 3347,
"preview": "package com.termux.app.fragments.settings.termux_tasker;\n\nimport android.content.Context;\nimport android.os.Bundle;\n\nimp"
},
{
"path": "app/src/main/java/com/termux/app/fragments/settings/termux_widget/DebuggingPreferencesFragment.java",
"chars": 3347,
"preview": "package com.termux.app.fragments.settings.termux_widget;\n\nimport android.content.Context;\nimport android.os.Bundle;\n\nimp"
},
{
"path": "app/src/main/java/com/termux/app/models/UserAction.java",
"chars": 306,
"preview": "package com.termux.app.models;\n\npublic enum UserAction {\n\n ABOUT(\"about\"),\n REPORT_ISSUE_FROM_TRANSCRIPT(\"report i"
},
{
"path": "app/src/main/java/com/termux/app/terminal/TermuxActivityRootView.java",
"chars": 15620,
"preview": "package com.termux.app.terminal;\n\nimport android.content.Context;\nimport android.graphics.Rect;\nimport android.inputmeth"
},
{
"path": "app/src/main/java/com/termux/app/terminal/TermuxSessionsListViewController.java",
"chars": 4602,
"preview": "package com.termux.app.terminal;\n\nimport android.annotation.SuppressLint;\nimport android.graphics.Color;\nimport android."
},
{
"path": "app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionActivityClient.java",
"chars": 21107,
"preview": "package com.termux.app.terminal;\n\nimport android.annotation.SuppressLint;\nimport android.app.Activity;\nimport android.ap"
},
{
"path": "app/src/main/java/com/termux/app/terminal/TermuxTerminalSessionServiceClient.java",
"chars": 1134,
"preview": "package com.termux.app.terminal;\n\nimport android.app.Service;\n\nimport androidx.annotation.NonNull;\n\nimport com.termux.ap"
},
{
"path": "app/src/main/java/com/termux/app/terminal/TermuxTerminalViewClient.java",
"chars": 35097,
"preview": "package com.termux.app.terminal;\n\nimport android.annotation.SuppressLint;\nimport android.app.AlertDialog;\nimport android"
},
{
"path": "app/src/main/java/com/termux/app/terminal/io/FullScreenWorkAround.java",
"chars": 2520,
"preview": "package com.termux.app.terminal.io;\n\nimport android.graphics.Rect;\nimport android.view.View;\nimport android.view.ViewGro"
},
{
"path": "app/src/main/java/com/termux/app/terminal/io/KeyboardShortcut.java",
"chars": 296,
"preview": "package com.termux.app.terminal.io;\n\npublic class KeyboardShortcut {\n\n public final int codePoint;\n public final i"
},
{
"path": "app/src/main/java/com/termux/app/terminal/io/TerminalToolbarViewPager.java",
"chars": 4333,
"preview": "package com.termux.app.terminal.io;\n\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.V"
},
{
"path": "app/src/main/java/com/termux/app/terminal/io/TermuxTerminalExtraKeys.java",
"chars": 5430,
"preview": "package com.termux.app.terminal.io;\n\nimport android.annotation.SuppressLint;\nimport android.view.Gravity;\nimport android"
},
{
"path": "app/src/main/java/com/termux/filepicker/TermuxDocumentsProvider.java",
"chars": 10889,
"preview": "package com.termux.filepicker;\n\nimport android.content.res.AssetFileDescriptor;\nimport android.database.Cursor;\nimport a"
},
{
"path": "app/src/main/res/drawable/current_session.xml",
"chars": 179,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\" android:shape=\""
},
{
"path": "app/src/main/res/drawable/current_session_black.xml",
"chars": 179,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\" android:shape=\""
},
{
"path": "app/src/main/res/drawable/ic_foreground.xml",
"chars": 745,
"preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:height=\"108dp\"\n android:width=\"108dp\"\n"
},
{
"path": "app/src/main/res/drawable/ic_new_session.xml",
"chars": 618,
"preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:width=\"24dp\"\n android:height=\""
},
{
"path": "app/src/main/res/drawable/ic_service_notification.xml",
"chars": 668,
"preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:width=\"24dp\"\n android:height=\"24dp\"\n "
},
{
"path": "app/src/main/res/drawable/ic_settings.xml",
"chars": 1186,
"preview": "<vector android:height=\"24dp\" android:tint=\"#FF000000\"\n android:viewportHeight=\"24\" android:viewportWidth=\"24\"\n an"
},
{
"path": "app/src/main/res/drawable/session_background_black_selected.xml",
"chars": 310,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <item "
},
{
"path": "app/src/main/res/drawable/session_background_selected.xml",
"chars": 297,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <item "
},
{
"path": "app/src/main/res/drawable/session_ripple.xml",
"chars": 243,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ripple xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:co"
},
{
"path": "app/src/main/res/drawable/session_ripple_black.xml",
"chars": 253,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ripple xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:co"
},
{
"path": "app/src/main/res/drawable/terminal_scroll_shape.xml",
"chars": 491,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n <solid a"
},
{
"path": "app/src/main/res/layout/activity_settings.xml",
"chars": 506,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n andr"
},
{
"path": "app/src/main/res/layout/activity_termux.xml",
"chars": 5069,
"preview": "<com.termux.app.terminal.TermuxActivityRootView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:app"
},
{
"path": "app/src/main/res/layout/item_terminal_sessions_list.xml",
"chars": 452,
"preview": "<com.google.android.material.textview.MaterialTextView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n an"
},
{
"path": "app/src/main/res/layout/preference_markdown_text.xml",
"chars": 843,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n ~ https://android.googlesource.com/platform/frameworks/support/+/refs/head"
},
{
"path": "app/src/main/res/layout/view_terminal_toolbar_extra_keys.xml",
"chars": 404,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.termux.shared.termux.extrakeys.ExtraKeysView xmlns:android=\"http://schemas.a"
},
{
"path": "app/src/main/res/layout/view_terminal_toolbar_text_input.xml",
"chars": 671,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<EditText xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:to"
},
{
"path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
"chars": 311,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <b"
},
{
"path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
"chars": 311,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <b"
},
{
"path": "app/src/main/res/values/attrs.xml",
"chars": 203,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <attr name=\"termuxActivityDrawerBackground\" format=\"reference\" />"
},
{
"path": "app/src/main/res/values/colors.xml",
"chars": 64,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n</resources>\n"
},
{
"path": "app/src/main/res/values/strings.xml",
"chars": 12571,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<!DOCTYPE resources [\n <!ENTITY TERMUX_PACKAGE_NAME \"com.termux\">\n <!ENTIT"
},
{
"path": "app/src/main/res/values/styles.xml",
"chars": 733,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n <styl"
},
{
"path": "app/src/main/res/values/themes.xml",
"chars": 2348,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <!--\n https://material.io/develop/android/theming/dark\n --"
},
{
"path": "app/src/main/res/values-night/themes.xml",
"chars": 1949,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <!--\n https://material.io/develop/android/theming/dark\n --"
},
{
"path": "app/src/main/res/xml/root_preferences.xml",
"chars": 1880,
"preview": "<PreferenceScreen xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n <Preference\n app:key=\"termux\"\n "
},
{
"path": "app/src/main/res/xml/shortcuts.xml",
"chars": 2194,
"preview": "<shortcuts xmlns:tools=\"http://schemas.android.com/tools\"\n xmlns:android=\"http://schemas.android.com/apk/res/android\""
},
{
"path": "app/src/main/res/xml/termux_api_debugging_preferences.xml",
"chars": 417,
"preview": "<PreferenceScreen xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n <PreferenceCategory\n app:key=\"logging"
},
{
"path": "app/src/main/res/xml/termux_api_preferences.xml",
"chars": 338,
"preview": "<PreferenceScreen xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n <Preference\n app:title=\"@string/termu"
},
{
"path": "app/src/main/res/xml/termux_debugging_preferences.xml",
"chars": 1424,
"preview": "<PreferenceScreen xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n <PreferenceCategory\n app:key=\"logging"
},
{
"path": "app/src/main/res/xml/termux_float_debugging_preferences.xml",
"chars": 750,
"preview": "<PreferenceScreen xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n <PreferenceCategory\n app:key=\"logging"
},
{
"path": "app/src/main/res/xml/termux_float_preferences.xml",
"chars": 340,
"preview": "<PreferenceScreen xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n <Preference\n app:title=\"@string/termu"
},
{
"path": "app/src/main/res/xml/termux_preferences.xml",
"chars": 834,
"preview": "<PreferenceScreen xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n <Preference\n app:title=\"@string/termu"
},
{
"path": "app/src/main/res/xml/termux_tasker_debugging_preferences.xml",
"chars": 417,
"preview": "<PreferenceScreen xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n <PreferenceCategory\n app:key=\"logging"
},
{
"path": "app/src/main/res/xml/termux_tasker_preferences.xml",
"chars": 341,
"preview": "<PreferenceScreen xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n <Preference\n app:title=\"@string/termu"
},
{
"path": "app/src/main/res/xml/termux_terminal_io_preferences.xml",
"chars": 873,
"preview": "<PreferenceScreen xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n <PreferenceCategory\n app:key=\"keyboar"
},
{
"path": "app/src/main/res/xml/termux_terminal_view_preferences.xml",
"chars": 576,
"preview": "<PreferenceScreen xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n <PreferenceCategory\n app:key=\"view\"\n "
},
{
"path": "app/src/main/res/xml/termux_widget_debugging_preferences.xml",
"chars": 417,
"preview": "<PreferenceScreen xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n <PreferenceCategory\n app:key=\"logging"
},
{
"path": "app/src/main/res/xml/termux_widget_preferences.xml",
"chars": 341,
"preview": "<PreferenceScreen xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n <Preference\n app:title=\"@string/termu"
},
{
"path": "app/src/test/java/com/termux/app/TermuxActivityTest.java",
"chars": 1089,
"preview": "package com.termux.app;\n\nimport com.termux.shared.termux.data.TermuxUrlUtils;\n\nimport org.junit.Assert;\nimport org.junit"
},
{
"path": "app/src/test/java/com/termux/app/api/file/FileReceiverActivityTest.java",
"chars": 1282,
"preview": "package com.termux.app.api.file;\n\nimport com.termux.app.api.file.FileReceiverActivity;\n\nimport org.junit.Assert;\nimport "
},
{
"path": "art/copy-to-other-apps.sh",
"chars": 360,
"preview": "#!/bin/sh\nset -e -u\n\nfor APP in api boot styling tasker widget; do\n\tAPPDIR=../../termux-$APP\n\tfor file in ic_foreground "
},
{
"path": "art/generate-big-icon.sh",
"chars": 535,
"preview": "#!/bin/sh\nset -e -u\n\necho \"Generating ~/termux-icons/ic_launcher.png...\"\nmkdir -p ~/termux-icons/\n\nvector2svg ../app/src"
},
{
"path": "art/generate-feature-graphic.sh",
"chars": 191,
"preview": "#!/bin/bash\n\necho \"Generating feature graphics to ~/termux-icons/termux-feature-graphic.png...\"\nmkdir -p ~/termux-icons/"
},
{
"path": "art/generate-launcher-images.sh",
"chars": 404,
"preview": "#!/bin/sh\n\nfor DENSITY in mdpi hdpi xhdpi xxhdpi xxxhdpi; do\n\tcase $DENSITY in\n\t\tmdpi) SIZE=48;;\n\t\thdpi) SIZE=72;;\n\t\txhd"
},
{
"path": "art/generate-tv-banner.sh",
"chars": 389,
"preview": "#!/bin/bash\n\necho \"Generating feature graphics to ~/termux-icons/termux-feature-graphic.png...\"\nmkdir -p ~/termux-icons/"
},
{
"path": "build.gradle",
"chars": 289,
"preview": "buildscript {\n repositories {\n mavenCentral()\n google()\n }\n dependencies {\n classpath \"com"
},
{
"path": "docs/en/index.md",
"chars": 204,
"preview": "---\npage_ref: /docs/apps/termux/index.html\n---\n\n# Termux App Docs\n\n<!--- DOC_HEADER_PLACEHOLDER -->\n\nWelcome to document"
},
{
"path": "fastlane/metadata/android/en-US/full_description.txt",
"chars": 1166,
"preview": "Termux is a terminal emulator application enhanced with a large set of command line utilities ported to Android OS. The "
},
{
"path": "fastlane/metadata/android/en-US/short_description.txt",
"chars": 65,
"preview": "Terminal emulator app with a large set of command line utilities\n"
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 252,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "gradle.properties",
"chars": 884,
"preview": "## Project-wide Gradle settings.\n#\n# For more details on how to configure your build environment visit\n# http://www.grad"
},
{
"path": "gradlew",
"chars": 8595,
"preview": "#!/bin/sh\n\n#\n# Copyright © 2015 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\")"
},
{
"path": "gradlew.bat",
"chars": 2896,
"preview": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (th"
},
{
"path": "jitpack.yml",
"chars": 63,
"preview": "jdk:\n - openjdk17\nenv:\n JITPACK_NDK_VERSION: \"29.0.14206865\"\n"
},
{
"path": "settings.gradle",
"chars": 73,
"preview": "include ':app', ':termux-shared', ':terminal-emulator', ':terminal-view'\n"
},
{
"path": "terminal-emulator/build.gradle",
"chars": 2086,
"preview": "apply plugin: 'com.android.library'\napply plugin: 'maven-publish'\n\nandroid {\n namespace \"com.termux.emulator\"\n\n co"
},
{
"path": "terminal-emulator/proguard-rules.pro",
"chars": 933,
"preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /U"
},
{
"path": "terminal-emulator/src/main/AndroidManifest.xml",
"chars": 23,
"preview": "<manifest>\n</manifest>\n"
},
{
"path": "terminal-emulator/src/main/java/com/termux/terminal/ByteQueue.java",
"chars": 3804,
"preview": "package com.termux.terminal;\n\n/** A circular byte buffer allowing one producer and one consumer thread. */\nfinal class B"
},
{
"path": "terminal-emulator/src/main/java/com/termux/terminal/JNI.java",
"chars": 1928,
"preview": "package com.termux.terminal;\n\n/**\n * Native methods for creating and managing pseudoterminal subprocesses. C code is in "
},
{
"path": "terminal-emulator/src/main/java/com/termux/terminal/KeyHandler.java",
"chars": 18070,
"preview": "package com.termux.terminal;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static android.view.KeyEvent.KEYCO"
},
{
"path": "terminal-emulator/src/main/java/com/termux/terminal/Logger.java",
"chars": 2477,
"preview": "package com.termux.terminal;\n\nimport android.util.Log;\n\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport j"
},
{
"path": "terminal-emulator/src/main/java/com/termux/terminal/TerminalBuffer.java",
"chars": 23758,
"preview": "package com.termux.terminal;\n\nimport java.util.Arrays;\n\n/**\n * A circular buffer of {@link TerminalRow}:s which keeps no"
},
{
"path": "terminal-emulator/src/main/java/com/termux/terminal/TerminalColorScheme.java",
"chars": 7044,
"preview": "package com.termux.terminal;\n\nimport java.util.Map;\nimport java.util.Properties;\n\n/**\n * Color scheme for a terminal wit"
},
{
"path": "terminal-emulator/src/main/java/com/termux/terminal/TerminalColors.java",
"chars": 3870,
"preview": "package com.termux.terminal;\n\nimport android.graphics.Color;\n\n/** Current terminal colors (if different from default). *"
},
{
"path": "terminal-emulator/src/main/java/com/termux/terminal/TerminalEmulator.java",
"chars": 130938,
"preview": "package com.termux.terminal;\n\nimport android.util.Base64;\n\nimport java.nio.charset.StandardCharsets;\nimport java.util.Ar"
},
{
"path": "terminal-emulator/src/main/java/com/termux/terminal/TerminalOutput.java",
"chars": 1217,
"preview": "package com.termux.terminal;\n\nimport java.nio.charset.StandardCharsets;\n\n/** A client which receives callbacks from even"
},
{
"path": "terminal-emulator/src/main/java/com/termux/terminal/TerminalRow.java",
"chars": 14062,
"preview": "package com.termux.terminal;\n\nimport java.util.Arrays;\n\n/**\n * A row in a terminal, composed of a fixed number of cells."
},
{
"path": "terminal-emulator/src/main/java/com/termux/terminal/TerminalSession.java",
"chars": 14729,
"preview": "package com.termux.terminal;\n\nimport android.annotation.SuppressLint;\nimport android.os.Handler;\nimport android.os.Messa"
},
{
"path": "terminal-emulator/src/main/java/com/termux/terminal/TerminalSessionClient.java",
"chars": 1387,
"preview": "package com.termux.terminal;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\n\n/**\n * The inter"
},
{
"path": "terminal-emulator/src/main/java/com/termux/terminal/TextStyle.java",
"chars": 3623,
"preview": "package com.termux.terminal;\n\n/**\n * <p>\n * Encodes effects, foreground and background colors into a 64 bit long, which "
},
{
"path": "terminal-emulator/src/main/java/com/termux/terminal/WcWidth.java",
"chars": 39885,
"preview": "package com.termux.terminal;\n\n/**\n * Implementation of wcwidth(3) for Unicode 15.\n *\n * Implementation from https://gith"
},
{
"path": "terminal-emulator/src/main/jni/Android.mk",
"chars": 134,
"preview": "LOCAL_PATH:= $(call my-dir)\ninclude $(CLEAR_VARS)\nLOCAL_MODULE:= libtermux\nLOCAL_SRC_FILES:= termux.c\ninclude $(BUILD_SH"
},
{
"path": "terminal-emulator/src/main/jni/termux.c",
"chars": 7588,
"preview": "#include <dirent.h>\n#include <fcntl.h>\n#include <jni.h>\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#incl"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/ApcTest.java",
"chars": 1059,
"preview": "package com.termux.terminal;\n\npublic class ApcTest extends TerminalTestCase {\n\n public void testApcConsumed() {\n "
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/ByteQueueTest.java",
"chars": 1616,
"preview": "package com.termux.terminal;\n\nimport junit.framework.TestCase;\n\npublic class ByteQueueTest extends TestCase {\n\n\tprivate "
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/ControlSequenceIntroducerTest.java",
"chars": 6447,
"preview": "package com.termux.terminal;\n\nimport java.util.List;\n\n/** \"\\033[\" is the Control Sequence Introducer char sequence (CSI)"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/CursorAndScreenTest.java",
"chars": 13639,
"preview": "package com.termux.terminal;\n\nimport org.junit.Assert;\n\npublic class CursorAndScreenTest extends TerminalTestCase {\n\n\tpu"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/DecSetTest.java",
"chars": 3004,
"preview": "package com.termux.terminal;\n\n/**\n * <pre>\n * \"CSI ? Pm h\", DEC Private Mode Set (DECSET)\n * </pre>\n * <p/>\n * and\n * <p"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/DeviceControlStringTest.java",
"chars": 2128,
"preview": "package com.termux.terminal;\n\n/**\n * \"\\033P\" is a device control string.\n */\npublic class DeviceControlStringTest extend"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/HistoryTest.java",
"chars": 1116,
"preview": "package com.termux.terminal;\n\n\npublic class HistoryTest extends TerminalTestCase {\n\n\tpublic void testHistory() {\n\t\tfinal"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/KeyHandlerTest.java",
"chars": 13381,
"preview": "package com.termux.terminal;\n\nimport android.view.KeyEvent;\n\nimport junit.framework.TestCase;\n\npublic class KeyHandlerTe"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/OperatingSystemControlTest.java",
"chars": 9183,
"preview": "package com.termux.terminal;\n\nimport android.util.Base64;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport jav"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/RectangularAreasTest.java",
"chars": 7657,
"preview": "package com.termux.terminal;\n\npublic class RectangularAreasTest extends TerminalTestCase {\n\n\t/** http://www.vt100.net/do"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/ResizeTest.java",
"chars": 9290,
"preview": "package com.termux.terminal;\n\npublic class ResizeTest extends TerminalTestCase {\n\n\tpublic void testResizeWhenHasHistory("
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/ScreenBufferTest.java",
"chars": 2916,
"preview": "package com.termux.terminal;\n\npublic class ScreenBufferTest extends TerminalTestCase {\n\n\tpublic void testBasics() {\n\t\tTe"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/ScrollRegionTest.java",
"chars": 7813,
"preview": "package com.termux.terminal;\n\n/**\n * ${CSI}${top};${bottom}r\" - set Scrolling Region [top;bottom] (default = full size o"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/TerminalRowTest.java",
"chars": 16834,
"preview": "package com.termux.terminal;\n\nimport junit.framework.TestCase;\n\nimport java.util.Arrays;\nimport java.util.Random;\n\npubli"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/TerminalTest.java",
"chars": 14696,
"preview": "package com.termux.terminal;\n\nimport java.io.UnsupportedEncodingException;\n\npublic class TerminalTest extends TerminalTe"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/TerminalTestCase.java",
"chars": 11180,
"preview": "package com.termux.terminal;\n\nimport junit.framework.AssertionFailedError;\nimport junit.framework.TestCase;\n\nimport java"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/TextStyleTest.java",
"chars": 2539,
"preview": "package com.termux.terminal;\n\nimport junit.framework.TestCase;\n\npublic class TextStyleTest extends TestCase {\n\n\tprivate "
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/UnicodeInputTest.java",
"chars": 6364,
"preview": "package com.termux.terminal;\n\nimport java.io.UnsupportedEncodingException;\n\npublic class UnicodeInputTest extends Termin"
},
{
"path": "terminal-emulator/src/test/java/com/termux/terminal/WcWidthTest.java",
"chars": 2203,
"preview": "package com.termux.terminal;\n\nimport junit.framework.TestCase;\n\npublic class WcWidthTest extends TestCase {\n\n\tprivate st"
},
{
"path": "terminal-view/build.gradle",
"chars": 1578,
"preview": "apply plugin: 'com.android.library'\napply plugin: 'maven-publish'\n\nandroid {\n namespace \"com.termux.view\"\n compile"
},
{
"path": "terminal-view/proguard-rules.pro",
"chars": 933,
"preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /U"
},
{
"path": "terminal-view/src/main/AndroidManifest.xml",
"chars": 23,
"preview": "<manifest>\n</manifest>\n"
},
{
"path": "terminal-view/src/main/java/com/termux/view/GestureAndScaleRecognizer.java",
"chars": 3704,
"preview": "package com.termux.view;\n\nimport android.content.Context;\nimport android.view.GestureDetector;\nimport android.view.Motio"
},
{
"path": "terminal-view/src/main/java/com/termux/view/TerminalRenderer.java",
"chars": 12774,
"preview": "package com.termux.view;\n\nimport android.graphics.Canvas;\nimport android.graphics.Paint;\nimport android.graphics.PorterD"
},
{
"path": "terminal-view/src/main/java/com/termux/view/TerminalView.java",
"chars": 68034,
"preview": "package com.termux.view;\n\nimport android.annotation.SuppressLint;\nimport android.annotation.TargetApi;\nimport android.ap"
},
{
"path": "terminal-view/src/main/java/com/termux/view/TerminalViewClient.java",
"chars": 1998,
"preview": "package com.termux.view;\n\nimport android.view.KeyEvent;\nimport android.view.MotionEvent;\nimport android.view.ScaleGestur"
},
{
"path": "terminal-view/src/main/java/com/termux/view/support/PopupWindowCompatGingerbread.java",
"chars": 2870,
"preview": "/*\n * Copyright (C) 2015 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
},
{
"path": "terminal-view/src/main/java/com/termux/view/textselection/CursorController.java",
"chars": 1471,
"preview": "package com.termux.view.textselection;\n\nimport android.view.MotionEvent;\nimport android.view.ViewTreeObserver;\n\nimport c"
},
{
"path": "terminal-view/src/main/java/com/termux/view/textselection/TextSelectionCursorController.java",
"chars": 13903,
"preview": "package com.termux.view.textselection;\n\nimport android.content.ClipboardManager;\nimport android.content.Context;\nimport "
},
{
"path": "terminal-view/src/main/java/com/termux/view/textselection/TextSelectionHandleView.java",
"chars": 11639,
"preview": "package com.termux.view.textselection;\n\nimport android.annotation.SuppressLint;\nimport android.graphics.Canvas;\nimport a"
},
{
"path": "terminal-view/src/main/res/drawable/text_select_handle_left_material.xml",
"chars": 524,
"preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:width=\"48dp\"\n android:height=\"24dp\"\n "
},
{
"path": "terminal-view/src/main/res/drawable/text_select_handle_right_material.xml",
"chars": 498,
"preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n android:width=\"48dp\"\n android:height=\"24dp\"\n "
},
{
"path": "terminal-view/src/main/res/values/strings.xml",
"chars": 161,
"preview": "<resources>\n <string name=\"paste_text\">Paste</string>\n <string name=\"copy_text\">Copy</string>\n <string name=\"text_sel"
},
{
"path": "termux-shared/.gitignore",
"chars": 7,
"preview": "/build\n"
},
{
"path": "termux-shared/LICENSE.md",
"chars": 1329,
"preview": "The `termux-shared` library is released under [MIT](https://opensource.org/licenses/MIT) license.\n\n### Exceptions\n\n#### "
},
{
"path": "termux-shared/build.gradle",
"chars": 3123,
"preview": "apply plugin: 'com.android.library'\napply plugin: 'maven-publish'\n\nandroid {\n namespace = \"com.termux.shared\"\n\n co"
},
{
"path": "termux-shared/proguard-rules.pro",
"chars": 347,
"preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
},
{
"path": "termux-shared/src/androidTest/java/com/termux/shared/ExampleInstrumentedTest.java",
"chars": 754,
"preview": "package com.termux.shared;\n\nimport android.content.Context;\n\nimport androidx.test.platform.app.InstrumentationRegistry;\n"
},
{
"path": "termux-shared/src/main/AndroidManifest.xml",
"chars": 187,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <uses-p"
},
{
"path": "termux-shared/src/main/cpp/Android.mk",
"chars": 169,
"preview": "LOCAL_PATH:= $(call my-dir)\ninclude $(CLEAR_VARS)\nLOCAL_LDLIBS := -llog\nLOCAL_MODULE := local-socket\nLOCAL_SRC_FILES := "
},
{
"path": "termux-shared/src/main/cpp/Application.mk",
"chars": 22,
"preview": "APP_STL := c++_static\n"
},
{
"path": "termux-shared/src/main/cpp/local-socket.cpp",
"chars": 23983,
"preview": "#include <cstdio>\n#include <ctime>\n#include <cerrno>\n#include <jni.h>\n#include <sstream>\n#include <string>\n#include <uni"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/activities/ReportActivity.java",
"chars": 22016,
"preview": "package com.termux.shared.activities;\n\nimport androidx.annotation.NonNull;\nimport androidx.appcompat.app.ActionBar;\nimpo"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/activities/TextIOActivity.java",
"chars": 10492,
"preview": "package com.termux.shared.activities;\n\nimport android.annotation.SuppressLint;\nimport android.app.Activity;\nimport andro"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/activity/ActivityErrno.java",
"chars": 828,
"preview": "package com.termux.shared.activity;\n\nimport com.termux.shared.errors.Errno;\n\npublic class ActivityErrno extends Errno {\n"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/activity/ActivityUtils.java",
"chars": 6490,
"preview": "package com.termux.shared.activity;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/activity/media/AppCompatActivityUtils.java",
"chars": 4745,
"preview": "package com.termux.shared.activity.media;\n\nimport androidx.annotation.IdRes;\nimport androidx.annotation.NonNull;\nimport "
},
{
"path": "termux-shared/src/main/java/com/termux/shared/android/AndroidUtils.java",
"chars": 13125,
"preview": "package com.termux.shared.android;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport andro"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/android/FeatureFlagUtils.java",
"chars": 7846,
"preview": "package com.termux.shared.android;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\n\nimport andr"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/android/PackageUtils.java",
"chars": 37203,
"preview": "package com.termux.shared.android;\n\nimport android.app.ActivityManager;\nimport android.app.admin.DevicePolicyManager;\nim"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/android/PermissionUtils.java",
"chars": 28221,
"preview": "package com.termux.shared.android;\n\nimport android.Manifest;\nimport android.annotation.SuppressLint;\nimport android.app."
},
{
"path": "termux-shared/src/main/java/com/termux/shared/android/PhantomProcessUtils.java",
"chars": 6136,
"preview": "package com.termux.shared.android;\n\nimport android.Manifest;\nimport android.content.Context;\n\nimport androidx.annotation"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/android/ProcessUtils.java",
"chars": 2534,
"preview": "package com.termux.shared.android;\n\nimport android.app.ActivityManager;\nimport android.content.Context;\n\nimport androidx"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/android/SELinuxUtils.java",
"chars": 3882,
"preview": "package com.termux.shared.android;\n\nimport android.annotation.SuppressLint;\n\nimport androidx.annotation.NonNull;\nimport "
},
{
"path": "termux-shared/src/main/java/com/termux/shared/android/SettingsProviderUtils.java",
"chars": 4071,
"preview": "package com.termux.shared.android;\n\nimport android.content.Context;\nimport android.provider.Settings;\n\nimport androidx.a"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/android/UserUtils.java",
"chars": 6955,
"preview": "package com.termux.shared.android;\n\nimport android.content.Context;\nimport android.content.pm.PackageManager;\n\nimport an"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/android/resource/ResourceUtils.java",
"chars": 5931,
"preview": "package com.termux.shared.android.resource;\n\nimport android.content.Context;\n\nimport androidx.annotation.NonNull;\nimport"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/crash/CrashHandler.java",
"chars": 7324,
"preview": "package com.termux.shared.crash;\n\nimport android.content.Context;\n\nimport androidx.annotation.NonNull;\n\nimport com.termu"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/data/DataUtils.java",
"chars": 8670,
"preview": "package com.termux.shared.data;\n\nimport android.os.Bundle;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotati"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/data/IntentUtils.java",
"chars": 6526,
"preview": "package com.termux.shared.data;\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.os.Parcelable;\n"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/errors/Errno.java",
"chars": 3850,
"preview": "package com.termux.shared.errors;\n\nimport android.app.Activity;\n\nimport androidx.annotation.NonNull;\n\nimport com.termux."
},
{
"path": "termux-shared/src/main/java/com/termux/shared/errors/Error.java",
"chars": 9591,
"preview": "package com.termux.shared.errors;\n\nimport android.content.Context;\n\nimport androidx.annotation.NonNull;\n\nimport com.term"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/errors/FunctionErrno.java",
"chars": 1235,
"preview": "package com.termux.shared.errors;\n\n/** The {@link Class} that defines function error messages and codes. */\npublic class"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/file/FileUtils.java",
"chars": 104538,
"preview": "package com.termux.shared.file;\n\nimport android.os.Build;\nimport android.system.Os;\n\nimport androidx.annotation.NonNull;"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/file/FileUtilsErrno.java",
"chars": 8968,
"preview": "package com.termux.shared.file;\n\nimport com.termux.shared.errors.Errno;\n\nimport java.util.HashMap;\nimport java.util.Map;"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/file/filesystem/FileAttributes.java",
"chars": 12785,
"preview": "/*\n * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/file/filesystem/FileKey.java",
"chars": 2373,
"preview": "/*\n * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
},
{
"path": "termux-shared/src/main/java/com/termux/shared/file/filesystem/FilePermission.java",
"chars": 2299,
"preview": "\n/*\n * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT "
},
{
"path": "termux-shared/src/main/java/com/termux/shared/file/filesystem/FilePermissions.java",
"chars": 5792,
"preview": "/*\n * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.\n * DO NOT ALTER OR REMOVE COPYRIGHT N"
}
]
// ... and 118 more files (download for full content)
About this extraction
This page contains the full source code of the termux/termux-app GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 318 files (2.1 MB), approximately 578.8k tokens, and a symbol index with 2547 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.