diff --git a/app/src/main/java/com/termux/app/BackgroundJob.java b/app/src/main/java/com/termux/app/BackgroundJob.java index 956c2c8d..1e8e63cd 100644 --- a/app/src/main/java/com/termux/app/BackgroundJob.java +++ b/app/src/main/java/com/termux/app/BackgroundJob.java @@ -19,11 +19,11 @@ import java.util.List; */ public final class BackgroundJob { - private static final String LOG_TAG = "termux-job"; + private static final String LOG_TAG = "termux-task"; final Process mProcess; - public BackgroundJob(String cwd, String fileToExecute, final String[] args) { + public BackgroundJob(String cwd, String fileToExecute, final String[] args, final TermuxService service) { String[] env = buildEnvironment(false, cwd); if (cwd == null) cwd = TermuxService.HOME_PATH; @@ -61,6 +61,7 @@ public final class BackgroundJob { try { int exitCode = mProcess.waitFor(); + service.onBackgroundJobExited(BackgroundJob.this); if (exitCode == 0) { Log.i(LOG_TAG, "[" + pid + "] exited normally"); } else { diff --git a/app/src/main/java/com/termux/app/TermuxService.java b/app/src/main/java/com/termux/app/TermuxService.java index 25e272c1..61a9ed69 100644 --- a/app/src/main/java/com/termux/app/TermuxService.java +++ b/app/src/main/java/com/termux/app/TermuxService.java @@ -11,6 +11,7 @@ import android.content.res.Resources; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.Binder; +import android.os.Handler; import android.os.IBinder; import android.os.PowerManager; import android.util.Log; @@ -48,12 +49,9 @@ public final class TermuxService extends Service implements SessionChangedCallba private static final int NOTIFICATION_ID = 1337; - /** Intent action to stop the service. */ private static final String ACTION_STOP_SERVICE = "com.termux.service_stop"; - /** Intent action to toggle the wake lock, {@link #mWakeLock}, which this service may hold. */ - private static final String ACTION_LOCK_WAKE = "com.termux.service_toggle_wake_lock"; - /** Intent action to toggle the wifi lock, {@link #mWifiLock}, which this service may hold. */ - private static final String ACTION_LOCK_WIFI = "com.termux.service_toggle_wifi_lock"; + private static final String ACTION_LOCK_WAKE = "com.termux.service_wake_lock"; + private static final String ACTION_UNLOCK_WAKE = "com.termux.service_wake_unlock"; /** Intent action to launch a new terminal session. Executed from TermuxWidgetProvider. */ public static final String ACTION_EXECUTE = "com.termux.service_execute"; @@ -68,6 +66,8 @@ public final class TermuxService extends Service implements SessionChangedCallba private final IBinder mBinder = new LocalBinder(); + private final Handler mHandler = new Handler(); + /** * The terminal sessions which this service manages. *

@@ -76,9 +76,12 @@ public final class TermuxService extends Service implements SessionChangedCallba */ final List mTerminalSessions = new ArrayList<>(); + final List mBackgroundTasks = new ArrayList<>(); + /** Note that the service may often outlive the activity, so need to clear this reference. */ SessionChangedCallback mSessionChangeCallback; + /** The wake lock and wifi lock are always acquired and released together. */ private PowerManager.WakeLock mWakeLock; private WifiManager.WifiLock mWifiLock; @@ -99,21 +102,25 @@ public final class TermuxService extends Service implements SessionChangedCallba PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, EmulatorDebug.LOG_TAG); mWakeLock.acquire(); - } else { - mWakeLock.release(); - mWakeLock = null; - } - updateNotification(); - } else if (ACTION_LOCK_WIFI.equals(action)) { - if (mWifiLock == null) { + WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE); mWifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, EmulatorDebug.LOG_TAG); mWifiLock.acquire(); - } else { + updateNotification(); + + updateNotification(); + } + } else if (ACTION_UNLOCK_WAKE.equals(action)) { + if (mWakeLock != null) { + mWakeLock.release(); + mWakeLock = null; + mWifiLock.release(); mWifiLock = null; + updateNotification(); + + updateNotification(); } - updateNotification(); } else if (ACTION_EXECUTE.equals(action)) { Uri executableUri = intent.getData(); String executablePath = (executableUri == null ? null : executableUri.getPath()); @@ -121,7 +128,8 @@ public final class TermuxService extends Service implements SessionChangedCallba String cwd = intent.getStringExtra(EXTRA_CURRENT_WORKING_DIRECTORY); if (intent.getBooleanExtra("com.termux.execute.background", false)) { - new BackgroundJob(cwd, executablePath, arguments); + mBackgroundTasks.add(new BackgroundJob(cwd, executablePath, arguments, this)); + updateNotification(); } else { TerminalSession newSession = createTermSession(executablePath, arguments, cwd, false); @@ -136,7 +144,7 @@ public final class TermuxService extends Service implements SessionChangedCallba // Make the newly created session the current one to be displayed: TermuxPreferences.storeCurrentSession(this, newSession); - // Launch the main Termux app, which will now show to current session: + // Launch the main Termux app, which will now show the current session: startActivity(new Intent(this, TermuxActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); } } else if (action != null) { @@ -160,8 +168,8 @@ public final class TermuxService extends Service implements SessionChangedCallba /** Update the shown foreground service notification after making any changes that affect it. */ private void updateNotification() { - if (mWakeLock == null && mWifiLock == null && getSessions().isEmpty()) { - // Exit if we are updating after the user disabled all locks with no sessions. + if (mWakeLock == null && mTerminalSessions.isEmpty() && mBackgroundTasks.isEmpty()) { + // Exit if we are updating after the user disabled all locks with no sessions or tasks running. stopSelf(); } else { ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, buildNotification()); @@ -176,18 +184,15 @@ public final class TermuxService extends Service implements SessionChangedCallba PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifyIntent, 0); int sessionCount = mTerminalSessions.size(); - String contentText = sessionCount + " terminal session" + (sessionCount == 1 ? "" : "s"); - - boolean wakeLockHeld = mWakeLock != null; - boolean wifiLockHeld = mWifiLock != null; - if (wakeLockHeld && wifiLockHeld) { - contentText += " (wake&wifi lock held)"; - } else if (wakeLockHeld) { - contentText += " (wake lock held)"; - } else if (wifiLockHeld) { - contentText += " (wifi lock held)"; + int taskCount = mBackgroundTasks.size(); + String contentText = sessionCount + " session" + (sessionCount == 1 ? "" : "s"); + if (taskCount > 0) { + contentText += ", " + taskCount + " task" + (taskCount == 1 ? "" : "s"); } + final boolean wakeLockHeld = mWakeLock != null; + if (wakeLockHeld) contentText += " (wake lock held)"; + Notification.Builder builder = new Notification.Builder(this); builder.setContentTitle(getText(R.string.application_name)); builder.setContentText(contentText); @@ -197,7 +202,7 @@ public final class TermuxService extends Service implements SessionChangedCallba // If holding a wake or wifi lock consider the notification of high priority since it's using power, // otherwise use a minimal priority since this is just a background service notification: - builder.setPriority((wakeLockHeld || wifiLockHeld) ? Notification.PRIORITY_HIGH : Notification.PRIORITY_MIN); + builder.setPriority((wakeLockHeld) ? Notification.PRIORITY_HIGH : Notification.PRIORITY_MIN); // No need to show a timestamp: builder.setShowWhen(false); @@ -209,13 +214,13 @@ public final class TermuxService extends Service implements SessionChangedCallba Intent exitIntent = new Intent(this, TermuxService.class).setAction(ACTION_STOP_SERVICE); builder.addAction(android.R.drawable.ic_delete, res.getString(R.string.notification_action_exit), PendingIntent.getService(this, 0, exitIntent, 0)); - Intent toggleWakeLockIntent = new Intent(this, TermuxService.class).setAction(ACTION_LOCK_WAKE); - builder.addAction(android.R.drawable.ic_lock_lock, res.getString(R.string.notification_action_wakelock), - PendingIntent.getService(this, 0, toggleWakeLockIntent, 0)); - - Intent toggleWifiLockIntent = new Intent(this, TermuxService.class).setAction(ACTION_LOCK_WIFI); - builder.addAction(android.R.drawable.ic_lock_lock, res.getString(R.string.notification_action_wifilock), - PendingIntent.getService(this, 0, toggleWifiLockIntent, 0)); + String newWakeAction = wakeLockHeld ? ACTION_UNLOCK_WAKE : ACTION_LOCK_WAKE; + Intent toggleWakeLockIntent = new Intent(this, TermuxService.class).setAction(newWakeAction); + String actionTitle = res.getString(wakeLockHeld ? + R.string.notification_action_wake_unlock : + R.string.notification_action_wake_lock); + int actionIcon = wakeLockHeld ? android.R.drawable.ic_lock_idle_lock : android.R.drawable.ic_lock_lock; + builder.addAction(actionIcon, actionTitle, PendingIntent.getService(this, 0, toggleWakeLockIntent, 0)); return builder.build(); } @@ -337,4 +342,13 @@ public final class TermuxService extends Service implements SessionChangedCallba if (mSessionChangeCallback != null) mSessionChangeCallback.onColorsChanged(session); } + public void onBackgroundJobExited(final BackgroundJob task) { + mHandler.post(new Runnable() { + @Override + public void run() { + mBackgroundTasks.remove(task); + updateNotification(); + } + }); + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 66496410..8caac3e6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -50,8 +50,8 @@ Install Exit - Wake - Wifi + Acquire wakelock + Release wakelock Save file in ~/downloads/ Edit