3232import com .termux .app .utils .TextDataUtils ;
3333import com .termux .models .ExecutionCommand ;
3434import com .termux .models .ExecutionCommand .ExecutionState ;
35+ import com .termux .app .terminal .TermuxTask ;
3536import com .termux .terminal .TerminalEmulator ;
3637import com .termux .terminal .TerminalSession ;
3738import com .termux .terminal .TerminalSessionClient ;
@@ -71,17 +72,17 @@ class LocalBinder extends Binder {
7172 private final Handler mHandler = new Handler ();
7273
7374 /**
74- * The termux sessions which this service manages.
75+ * The foreground termux sessions which this service manages.
7576 * Note that this list is observed by {@link TermuxActivity#mTermuxSessionListViewController},
7677 * so any changes must be made on the UI thread and followed by a call to
7778 * {@link ArrayAdapter#notifyDataSetChanged()} }.
7879 */
7980 final List <TermuxSession > mTermuxSessions = new ArrayList <>();
8081
8182 /**
82- * The background jobs which this service manages.
83+ * The background termux tasks which this service manages.
8384 */
84- final List <BackgroundJob > mBackgroundTasks = new ArrayList <>();
85+ final List <TermuxTask > mTermuxTasks = new ArrayList <>();
8586
8687 /** The full implementation of the {@link TerminalSessionClient} interface to be used by {@link TerminalSession}
8788 * that holds activity references for activity related functions.
@@ -204,15 +205,24 @@ private void requestStopService() {
204205 stopSelf ();
205206 }
206207
207-
208-
209208 /** Process action to stop service. */
210209 private void actionStopService () {
211210 mWantsToStop = true ;
212211 finishAllTermuxSessions ();
213212 requestStopService ();
214213 }
215214
215+ /** Finish all termux sessions by sending SIGKILL to their shells. */
216+ private synchronized void finishAllTermuxSessions () {
217+ // TODO: Should SIGKILL also be send to background processes maintained by mTermuxTasks?
218+ for (int i = 0 ; i < mTermuxSessions .size (); i ++)
219+ mTermuxSessions .get (i ).getTerminalSession ().finishIfRunning ();
220+ }
221+
222+
223+
224+
225+
216226 /** Process action to acquire Power and Wi-Fi WakeLocks. */
217227 @ SuppressLint ({"WakelockTimeout" , "BatteryLife" })
218228 private void actionAcquireWakeLock () {
@@ -306,36 +316,72 @@ private void actionServiceExecute(Intent intent) {
306316 executionCommand .pluginPendingIntent = intent .getParcelableExtra (TERMUX_SERVICE .EXTRA_PENDING_INTENT );
307317
308318 if (executionCommand .inBackground ) {
309- executeBackgroundCommand (executionCommand );
319+ executeTermuxTaskCommand (executionCommand );
310320 } else {
311321 executeTermuxSessionCommand (executionCommand );
312322 }
313323 }
314324
315- /** Execute a shell command in background with {@link BackgroundJob}. */
316- private void executeBackgroundCommand (ExecutionCommand executionCommand ) {
325+
326+
327+
328+
329+ /** Execute a shell command in background {@link TermuxTask}. */
330+ private void executeTermuxTaskCommand (ExecutionCommand executionCommand ) {
317331 if (executionCommand == null ) return ;
318-
319- Logger .logDebug (LOG_TAG , "Starting background command" );
332+
333+ Logger .logDebug (LOG_TAG , "Starting background termux task command" );
334+
335+ TermuxTask newTermuxTask = createTermuxTask (executionCommand );
336+ }
337+
338+ /** Create a {@link TermuxTask}. */
339+ @ Nullable
340+ public TermuxTask createTermuxTask (String executablePath , String [] arguments , String workingDirectory ) {
341+ return createTermuxTask (new ExecutionCommand (getNextExecutionId (), executablePath , arguments , workingDirectory , true , false ));
342+ }
343+
344+ /** Create a {@link TermuxTask}. */
345+ @ Nullable
346+ public synchronized TermuxTask createTermuxTask (ExecutionCommand executionCommand ) {
347+ if (executionCommand == null ) return null ;
348+
349+ Logger .logDebug (LOG_TAG , "Creating termux task" );
350+
351+ if (!executionCommand .inBackground ) {
352+ Logger .logDebug (LOG_TAG , "Ignoring a foreground execution command passed to createTermuxTask()" );
353+ return null ;
354+ }
320355
321356 if (Logger .getLogLevel () >= Logger .LOG_LEVEL_VERBOSE )
322357 Logger .logVerbose (LOG_TAG , executionCommand .toString ());
323358
324- BackgroundJob task = new BackgroundJob (executionCommand , this );
359+ TermuxTask newTermuxTask = TermuxTask .create (this , executionCommand );
360+ if (newTermuxTask == null ) {
361+ // Logger.logError(LOG_TAG, "Failed to execute new termux task command for:\n" + executionCommand.toString());
362+ return null ;
363+ };
364+
365+ mTermuxTasks .add (newTermuxTask );
325366
326- mBackgroundTasks .add (task );
327367 updateNotification ();
368+
369+ return newTermuxTask ;
328370 }
329371
330- /** Callback received when a {@link BackgroundJob } finishes. */
331- public void onBackgroundJobExited (final BackgroundJob task ) {
372+ /** Callback received when a {@link TermuxTask } finishes. */
373+ public synchronized void onTermuxTaskExited (final TermuxTask task ) {
332374 mHandler .post (() -> {
333- mBackgroundTasks .remove (task );
375+ mTermuxTasks .remove (task );
334376 updateNotification ();
335377 });
336378 }
337379
338- /** Execute a shell command in a foreground terminal session. */
380+
381+
382+
383+
384+ /** Execute a shell command in a foreground {@link TermuxSession}. */
339385 private void executeTermuxSessionCommand (ExecutionCommand executionCommand ) {
340386 if (executionCommand == null ) return ;
341387
@@ -357,15 +403,15 @@ private void executeTermuxSessionCommand(ExecutionCommand executionCommand) {
357403 }
358404
359405 /**
360- * Create a termux session .
406+ * Create a {@link TermuxSession} .
361407 * Currently called by {@link TermuxSessionClient#addNewSession(boolean, String)} to add a new termux session.
362408 */
363409 @ Nullable
364410 public TermuxSession createTermuxSession (String executablePath , String [] arguments , String workingDirectory , boolean isFailSafe , String sessionName ) {
365411 return createTermuxSession (new ExecutionCommand (getNextExecutionId (), executablePath , arguments , workingDirectory , false , isFailSafe ), sessionName );
366412 }
367413
368- /** Create a termux session . */
414+ /** Create a {@link TermuxSession} . */
369415 @ Nullable
370416 public synchronized TermuxSession createTermuxSession (ExecutionCommand executionCommand , String sessionName ) {
371417 if (executionCommand == null ) return null ;
@@ -428,11 +474,7 @@ public synchronized int removeTermuxSession(TerminalSession sessionToRemove) {
428474 return index ;
429475 }
430476
431- /** Finish all termux sessions by sending SIGKILL to their shells. */
432- private synchronized void finishAllTermuxSessions () {
433- for (int i = 0 ; i < mTermuxSessions .size (); i ++)
434- mTermuxSessions .get (i ).getTerminalSession ().finishIfRunning ();
435- }
477+
436478
437479
438480
@@ -473,6 +515,10 @@ private void startTermuxActivity() {
473515 startActivity (new Intent (this , TermuxActivity .class ).addFlags (Intent .FLAG_ACTIVITY_NEW_TASK ));
474516 }
475517
518+
519+
520+
521+
476522 /** If {@link TermuxActivity} has not bound to the {@link TermuxService} yet or is destroyed, then
477523 * interface functions requiring the activity should not be available to the terminal sessions,
478524 * so we just return the {@link #mTermuxSessionClientBase}. Once {@link TermuxActivity} bind
@@ -519,6 +565,8 @@ public synchronized void unsetTermuxSessionClient() {
519565
520566
521567
568+
569+
522570 private Notification buildNotification () {
523571 Intent notifyIntent = new Intent (this , TermuxActivity .class );
524572 // PendingIntent#getActivity(): "Note that the activity will be started outside of the context of an existing
@@ -527,7 +575,7 @@ private Notification buildNotification() {
527575 PendingIntent pendingIntent = PendingIntent .getActivity (this , 0 , notifyIntent , 0 );
528576
529577 int sessionCount = getTermuxSessionsSize ();
530- int taskCount = mBackgroundTasks .size ();
578+ int taskCount = mTermuxTasks .size ();
531579 String contentText = sessionCount + " session" + (sessionCount == 1 ? "" : "s" );
532580 if (taskCount > 0 ) {
533581 contentText += ", " + taskCount + " task" + (taskCount == 1 ? "" : "s" );
@@ -587,7 +635,7 @@ private void setupNotificationChannel() {
587635
588636 /** Update the shown foreground service notification after making any changes that affect it. */
589637 void updateNotification () {
590- if (mWakeLock == null && mTermuxSessions .isEmpty () && mBackgroundTasks .isEmpty ()) {
638+ if (mWakeLock == null && mTermuxSessions .isEmpty () && mTermuxTasks .isEmpty ()) {
591639 // Exit if we are updating after the user disabled all locks with no sessions or tasks running.
592640 requestStopService ();
593641 } else {
@@ -597,6 +645,8 @@ void updateNotification() {
597645
598646
599647
648+
649+
600650 private void setCurrentStoredTerminalSession (TerminalSession session ) {
601651 if (session == null ) return ;
602652 // Make the newly created session the current one to be displayed:
0 commit comments