diff --git a/app/src/main/java/com/termux/app/RunCommandService.java b/app/src/main/java/com/termux/app/RunCommandService.java index c5c79f939d..2d1d3fe22c 100644 --- a/app/src/main/java/com/termux/app/RunCommandService.java +++ b/app/src/main/java/com/termux/app/RunCommandService.java @@ -101,6 +101,7 @@ public int onStartCommand(Intent intent, int flags, int startId) { executionCommand.stdin = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_STDIN, null); executionCommand.workingDirectory = IntentUtils.getStringExtraIfSet(intent, RUN_COMMAND_SERVICE.EXTRA_WORKDIR, null); executionCommand.inBackground = intent.getBooleanExtra(RUN_COMMAND_SERVICE.EXTRA_BACKGROUND, false); + 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.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); @@ -197,6 +198,7 @@ public int onStartCommand(Intent intent, int flags, int startId) { 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_BACKGROUND, executionCommand.inBackground); + 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_COMMAND_LABEL, executionCommand.commandLabel); execIntent.putExtra(TERMUX_SERVICE.EXTRA_COMMAND_DESCRIPTION, executionCommand.commandDescription); diff --git a/app/src/main/java/com/termux/app/TermuxService.java b/app/src/main/java/com/termux/app/TermuxService.java index fe0b9a5b61..06a25754df 100644 --- a/app/src/main/java/com/termux/app/TermuxService.java +++ b/app/src/main/java/com/termux/app/TermuxService.java @@ -364,6 +364,7 @@ private void actionServiceExecute(Intent intent) { executionCommand.arguments = IntentUtils.getStringArrayExtraIfSet(intent, TERMUX_SERVICE.EXTRA_ARGUMENTS, null); if (executionCommand.inBackground) 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); diff --git a/termux-shared/src/main/java/com/termux/shared/data/DataUtils.java b/termux-shared/src/main/java/com/termux/shared/data/DataUtils.java index 60bb9fca96..9196910360 100644 --- a/termux-shared/src/main/java/com/termux/shared/data/DataUtils.java +++ b/termux-shared/src/main/java/com/termux/shared/data/DataUtils.java @@ -4,10 +4,6 @@ import androidx.annotation.Nullable; -import java.util.LinkedHashSet; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - public class DataUtils { public static final int TRANSACTION_SIZE_LIMIT_IN_BYTES = 100 * 1024; // 100KB @@ -97,6 +93,17 @@ public static int getIntFromString(String value, int def) { } } + /** + * Get the {@code String} from an {@link Integer}. + * + * @param value The {@link Integer} value. + * @param def The default {@link String} value. + * @return Returns {@code value} if it is not {@code null}, otherwise returns {@code def}. + */ + public static String getStringFromInteger(Integer value, String def) { + return (value == null) ? def : String.valueOf((int) value); + } + /** * Get the {@code hex string} from a {@link byte[]}. * diff --git a/termux-shared/src/main/java/com/termux/shared/data/IntentUtils.java b/termux-shared/src/main/java/com/termux/shared/data/IntentUtils.java index 885eb4232f..0c692fc352 100644 --- a/termux-shared/src/main/java/com/termux/shared/data/IntentUtils.java +++ b/termux-shared/src/main/java/com/termux/shared/data/IntentUtils.java @@ -49,6 +49,29 @@ public static String getStringExtraIfSet(@NonNull Intent intent, String key, Str return value; } + /** + * Get an {@link Integer} from an {@link Intent} stored as a {@link String} extra if its not + * {@code null} or empty. + * + * @param intent The {@link Intent} to get the extra from. + * @param key The {@link String} key name. + * @param def The default value if extra is not set. + * @return Returns the {@link Integer} extra if set, otherwise {@code null}. + */ + public static Integer getIntegerExtraIfSet(@NonNull Intent intent, String key, Integer def) { + try { + String value = intent.getStringExtra(key); + if (value == null || value.isEmpty()) { + return def; + } + + return Integer.parseInt(value); + } + catch (Exception e) { + return def; + } + } + /** diff --git a/termux-shared/src/main/java/com/termux/shared/logger/Logger.java b/termux-shared/src/main/java/com/termux/shared/logger/Logger.java index 2202a7bcde..10e777f848 100644 --- a/termux-shared/src/main/java/com/termux/shared/logger/Logger.java +++ b/termux-shared/src/main/java/com/termux/shared/logger/Logger.java @@ -50,16 +50,16 @@ public class Logger { - public static void logMessage(int logLevel, String tag, String message) { - if (logLevel == Log.ERROR && CURRENT_LOG_LEVEL >= LOG_LEVEL_NORMAL) + public static void logMessage(int logPriority, String tag, String message) { + if (logPriority == Log.ERROR && CURRENT_LOG_LEVEL >= LOG_LEVEL_NORMAL) Log.e(getFullTag(tag), message); - else if (logLevel == Log.WARN && CURRENT_LOG_LEVEL >= LOG_LEVEL_NORMAL) + else if (logPriority == Log.WARN && CURRENT_LOG_LEVEL >= LOG_LEVEL_NORMAL) Log.w(getFullTag(tag), message); - else if (logLevel == Log.INFO && CURRENT_LOG_LEVEL >= LOG_LEVEL_NORMAL) + else if (logPriority == Log.INFO && CURRENT_LOG_LEVEL >= LOG_LEVEL_NORMAL) Log.i(getFullTag(tag), message); - else if (logLevel == Log.DEBUG && CURRENT_LOG_LEVEL >= LOG_LEVEL_DEBUG) + else if (logPriority == Log.DEBUG && CURRENT_LOG_LEVEL >= LOG_LEVEL_DEBUG) Log.d(getFullTag(tag), message); - else if (logLevel == Log.VERBOSE && CURRENT_LOG_LEVEL >= LOG_LEVEL_VERBOSE) + else if (logPriority == Log.VERBOSE && CURRENT_LOG_LEVEL >= LOG_LEVEL_VERBOSE) Log.v(getFullTag(tag), message); } @@ -187,6 +187,10 @@ public static void logVerboseExtended(String message) { logExtendedMessage(Log.VERBOSE, DEFAULT_LOG_TAG, message); } + public static void logVerboseForce(String tag, String message) { + Log.v(tag, message); + } + public static void logErrorAndShowToast(Context context, String tag, String message) { diff --git a/termux-shared/src/main/java/com/termux/shared/models/ExecutionCommand.java b/termux-shared/src/main/java/com/termux/shared/models/ExecutionCommand.java index 77f7716078..d3611a5364 100644 --- a/termux-shared/src/main/java/com/termux/shared/models/ExecutionCommand.java +++ b/termux-shared/src/main/java/com/termux/shared/models/ExecutionCommand.java @@ -83,6 +83,12 @@ public int getValue() { /** If the {@link ExecutionCommand} is meant to start a failsafe terminal session. */ public boolean isFailsafe; + /** + * The {@link ExecutionCommand} custom log level for background {@link com.termux.shared.shell.TermuxTask} + * commands. By default, @link com.termux.shared.shell.StreamGobbler} only logs if {@link Logger} + * `CURRENT_LOG_LEVEL` is >= {@link Logger#LOG_LEVEL_VERBOSE}. + */ + public Integer backgroundCustomLogLevel; /** The session action of foreground commands. */ public String sessionAction; @@ -264,6 +270,9 @@ public static String getExecutionInputLogString(final ExecutionCommand execution logString.append("\n").append(executionCommand.getInBackgroundLogString()); logString.append("\n").append(executionCommand.getIsFailsafeLogString()); + if (executionCommand.inBackground && (!ignoreNull || executionCommand.backgroundCustomLogLevel != null)) + logString.append("\n").append(executionCommand.getBackgroundCustomLogLevelLogString()); + if (!ignoreNull || executionCommand.sessionAction != null) logString.append("\n").append(executionCommand.getSessionActionLogString()); @@ -346,6 +355,10 @@ public static String getExecutionCommandMarkdownString(final ExecutionCommand ex markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Working Directory", executionCommand.workingDirectory, "-")); markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("inBackground", executionCommand.inBackground, "-")); markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("isFailsafe", executionCommand.isFailsafe, "-")); + + if (executionCommand.inBackground && executionCommand.backgroundCustomLogLevel != null) + markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Background Custom Log Level", executionCommand.backgroundCustomLogLevel, "-")); + markdownString.append("\n").append(MarkdownUtils.getSingleLineMarkdownStringEntry("Session Action", executionCommand.sessionAction, "-")); @@ -418,6 +431,10 @@ public String getIsFailsafeLogString() { return "isFailsafe: `" + isFailsafe + "`"; } + public String getBackgroundCustomLogLevelLogString() { + return "Background Custom Log Level: `" + backgroundCustomLogLevel + "`"; + } + public String getSessionActionLogString() { return Logger.getSingleLineLogStringEntry("Session Action", sessionAction, "-"); } diff --git a/termux-shared/src/main/java/com/termux/shared/shell/StreamGobbler.java b/termux-shared/src/main/java/com/termux/shared/shell/StreamGobbler.java index d14ce7ab27..a8e1ca9136 100644 --- a/termux-shared/src/main/java/com/termux/shared/shell/StreamGobbler.java +++ b/termux-shared/src/main/java/com/termux/shared/shell/StreamGobbler.java @@ -87,6 +87,8 @@ public interface OnStreamClosedListener { private final OnLineListener lineListener; @Nullable private final OnStreamClosedListener streamClosedListener; + @Nullable + private final Integer mLlogLevel; private volatile boolean active = true; private volatile boolean calledOnClose = false; @@ -102,9 +104,13 @@ public interface OnStreamClosedListener { * @param shell Name of the shell * @param inputStream InputStream to read from * @param outputList {@literal List} to write to, or null + * @param logLevel The custom log level to use for logging by command output. If set to + * {@code null}, then {@link Logger#LOG_LEVEL_VERBOSE} will be used. */ @AnyThread - public StreamGobbler(@NonNull String shell, @NonNull InputStream inputStream, @Nullable List outputList) { + public StreamGobbler(@NonNull String shell, @NonNull InputStream inputStream, + @Nullable List outputList, + @Nullable Integer logLevel) { super("Gobbler#" + incThreadCounter()); this.shell = shell; this.inputStream = inputStream; @@ -114,6 +120,8 @@ public StreamGobbler(@NonNull String shell, @NonNull InputStream inputStream, @N listWriter = outputList; stringWriter = null; lineListener = null; + + mLlogLevel = logLevel; } /** @@ -128,9 +136,13 @@ public StreamGobbler(@NonNull String shell, @NonNull InputStream inputStream, @N * @param shell Name of the shell * @param inputStream InputStream to read from * @param outputString {@literal List} to write to, or null + * @param logLevel The custom log level to use for logging by command output. If set to + * {@code null}, then {@link Logger#LOG_LEVEL_VERBOSE} will be used. */ @AnyThread - public StreamGobbler(@NonNull String shell, @NonNull InputStream inputStream, @Nullable StringBuilder outputString) { + public StreamGobbler(@NonNull String shell, @NonNull InputStream inputStream, + @Nullable StringBuilder outputString, + @Nullable Integer logLevel) { super("Gobbler#" + incThreadCounter()); this.shell = shell; this.inputStream = inputStream; @@ -140,6 +152,8 @@ public StreamGobbler(@NonNull String shell, @NonNull InputStream inputStream, @N listWriter = null; stringWriter = outputString; lineListener = null; + + mLlogLevel = logLevel; } /** @@ -153,9 +167,14 @@ public StreamGobbler(@NonNull String shell, @NonNull InputStream inputStream, @N * @param inputStream InputStream to read from * @param onLineListener OnLineListener callback * @param onStreamClosedListener OnStreamClosedListener callback + * @param logLevel The custom log level to use for logging by command output. If set to + * {@code null}, then {@link Logger#LOG_LEVEL_VERBOSE} will be used. */ @AnyThread - public StreamGobbler(@NonNull String shell, @NonNull InputStream inputStream, @Nullable OnLineListener onLineListener, @Nullable OnStreamClosedListener onStreamClosedListener) { + public StreamGobbler(@NonNull String shell, @NonNull InputStream inputStream, + @Nullable OnLineListener onLineListener, + @Nullable OnStreamClosedListener onStreamClosedListener, + @Nullable Integer logLevel) { super("Gobbler#" + incThreadCounter()); this.shell = shell; this.inputStream = inputStream; @@ -165,21 +184,30 @@ public StreamGobbler(@NonNull String shell, @NonNull InputStream inputStream, @N listWriter = null; stringWriter = null; lineListener = onLineListener; + + mLlogLevel = logLevel; } @Override public void run() { - // keep reading the InputStream until it ends (or an error occurs) - // optionally pausing when a command is executed that consumes the InputStream itself + String defaultLogTag = Logger.DEFAULT_LOG_TAG; int currentLogLevel = Logger.getLogLevel(); - int logLevelVerbose = Logger.LOG_LEVEL_VERBOSE; + int customLogLevel; + if (mLlogLevel != null && mLlogLevel >= Logger.LOG_LEVEL_OFF) { + customLogLevel = mLlogLevel; + Logger.logVerbose(LOG_TAG, "Using custom log level: " + customLogLevel + ", current log level: " + currentLogLevel); + } else { + customLogLevel = Logger.LOG_LEVEL_VERBOSE; + } + + // keep reading the InputStream until it ends (or an error occurs) + // optionally pausing when a command is executed that consumes the InputStream itself try { String line; while ((line = reader.readLine()) != null) { - - if (currentLogLevel >= logLevelVerbose) - Logger.logVerbose(LOG_TAG, String.format(Locale.ENGLISH, "[%s] %s", shell, line)); // This will get truncated by LOGGER_ENTRY_MAX_LEN, likely 4KB + if (customLogLevel >= currentLogLevel) + Logger.logVerboseForce(defaultLogTag + "Command", String.format(Locale.ENGLISH, "[%s] %s", shell, line)); // This will get truncated by LOGGER_ENTRY_MAX_LEN, likely 4KB if (stringWriter != null) stringWriter.append(line).append("\n"); if (listWriter != null) listWriter.add(line); diff --git a/termux-shared/src/main/java/com/termux/shared/shell/TermuxTask.java b/termux-shared/src/main/java/com/termux/shared/shell/TermuxTask.java index 4b2801eaeb..4d0658e558 100644 --- a/termux-shared/src/main/java/com/termux/shared/shell/TermuxTask.java +++ b/termux-shared/src/main/java/com/termux/shared/shell/TermuxTask.java @@ -139,8 +139,8 @@ private void executeInner(@NonNull final Context context) throws IllegalThreadSt // setup stdin, and stdout and stderr gobblers DataOutputStream STDIN = new DataOutputStream(mProcess.getOutputStream()); - StreamGobbler STDOUT = new StreamGobbler(pid + "-stdout", mProcess.getInputStream(), mExecutionCommand.resultData.stdout); - StreamGobbler STDERR = new StreamGobbler(pid + "-stderr", mProcess.getErrorStream(), mExecutionCommand.resultData.stderr); + StreamGobbler STDOUT = new StreamGobbler(pid + "-stdout", mProcess.getInputStream(), mExecutionCommand.resultData.stdout, mExecutionCommand.backgroundCustomLogLevel); + StreamGobbler STDERR = new StreamGobbler(pid + "-stderr", mProcess.getErrorStream(), mExecutionCommand.resultData.stderr, mExecutionCommand.backgroundCustomLogLevel); // start gobbling STDOUT.start(); diff --git a/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java b/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java index fe531a86a3..a71337a408 100644 --- a/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java +++ b/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java @@ -12,7 +12,7 @@ import java.util.List; /* - * Version: v0.24.0 + * Version: v0.25.0 * * Changelog * @@ -172,6 +172,12 @@ * `FORMAT_FAILED_ERR__ERRMSG__STDOUT__STDERR__EXIT_CODE`, * `RESULT_FILE_ERR_PREFIX`, `RESULT_FILE_ERRMSG_PREFIX` `RESULT_FILE_STDOUT_PREFIX`, * `RESULT_FILE_STDERR_PREFIX`, `RESULT_FILE_EXIT_CODE_PREFIX`. + * + * - 0.25.0 (2021-08-19) + * - Added following to `TERMUX_APP.TERMUX_SERVICE`: + * `EXTRA_BACKGROUND_CUSTOM_LOG_LEVEL`. + * - Added following to `TERMUX_APP.RUN_COMMAND_SERVICE`: + * `EXTRA_BACKGROUND_CUSTOM_LOG_LEVEL`. */ /** @@ -816,6 +822,8 @@ public static final class TERMUX_SERVICE { public static final String EXTRA_WORKDIR = TERMUX_PACKAGE_NAME + ".execute.cwd"; // Default: "com.termux.execute.cwd" /** Intent {@code boolean} extra for command background mode for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */ public static final String EXTRA_BACKGROUND = TERMUX_PACKAGE_NAME + ".execute.background"; // Default: "com.termux.execute.background" + /** Intent {@code String} extra for custom log level for background commands defined by {@link com.termux.shared.logger.Logger} for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */ + public static final String EXTRA_BACKGROUND_CUSTOM_LOG_LEVEL = TERMUX_PACKAGE_NAME + ".execute.background_custom_log_level"; // Default: "com.termux.execute.background_custom_log_level" /** Intent {@code String} extra for session action for foreground commands for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */ public static final String EXTRA_SESSION_ACTION = TERMUX_PACKAGE_NAME + ".execute.session_action"; // Default: "com.termux.execute.session_action" /** Intent {@code String} extra for label of the command for the TERMUX_SERVICE.ACTION_SERVICE_EXECUTE intent */ @@ -939,6 +947,8 @@ public static final class RUN_COMMAND_SERVICE { public static final String EXTRA_WORKDIR = TERMUX_PACKAGE_NAME + ".RUN_COMMAND_WORKDIR"; // Default: "com.termux.RUN_COMMAND_WORKDIR" /** Intent {@code boolean} extra for whether to run command in background or foreground terminal session for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */ public static final String EXTRA_BACKGROUND = TERMUX_PACKAGE_NAME + ".RUN_COMMAND_BACKGROUND"; // Default: "com.termux.RUN_COMMAND_BACKGROUND" + /** Intent {@code String} extra for custom log level for background commands defined by {@link com.termux.shared.logger.Logger} for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */ + public static final String EXTRA_BACKGROUND_CUSTOM_LOG_LEVEL = TERMUX_PACKAGE_NAME + ".RUN_COMMAND_BACKGROUND_CUSTOM_LOG_LEVEL"; // Default: "com.termux.RUN_COMMAND_BACKGROUND_CUSTOM_LOG_LEVEL" /** Intent {@code String} extra for session action of foreground commands for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */ public static final String EXTRA_SESSION_ACTION = TERMUX_PACKAGE_NAME + ".RUN_COMMAND_SESSION_ACTION"; // Default: "com.termux.RUN_COMMAND_SESSION_ACTION" /** Intent {@code String} extra for label of the command for the RUN_COMMAND_SERVICE.ACTION_RUN_COMMAND intent */ diff --git a/termux-shared/src/main/java/com/termux/shared/termux/TermuxUtils.java b/termux-shared/src/main/java/com/termux/shared/termux/TermuxUtils.java index ba623bc279..4981b206b4 100644 --- a/termux-shared/src/main/java/com/termux/shared/termux/TermuxUtils.java +++ b/termux-shared/src/main/java/com/termux/shared/termux/TermuxUtils.java @@ -341,6 +341,7 @@ public static String geAPTInfoMarkdownString(@NonNull final Context context) { aptInfoScript = aptInfoScript.replaceAll(Pattern.quote("@TERMUX_PREFIX@"), TermuxConstants.TERMUX_PREFIX_DIR_PATH); ExecutionCommand executionCommand = new ExecutionCommand(1, TermuxConstants.TERMUX_BIN_PREFIX_DIR_PATH + "/bash", null, aptInfoScript, null, true, false); + executionCommand.backgroundCustomLogLevel = Logger.LOG_LEVEL_OFF; TermuxTask termuxTask = TermuxTask.execute(context, executionCommand, null, new TermuxShellEnvironmentClient(), true); if (termuxTask == null || !executionCommand.isSuccessful() || executionCommand.resultData.exitCode != 0) { Logger.logError(LOG_TAG, executionCommand.toString());