Keep track of background tasks

Also merge wake lock and wifi lock into one, and make it exposed to
termux-wake-lock and termux-wake-unlock commands.
This commit is contained in:
Fredrik Fornwall
2016-12-04 04:37:13 +01:00
parent 9fe0e49473
commit 9c19540759
3 changed files with 55 additions and 40 deletions

View File

@@ -19,11 +19,11 @@ import java.util.List;
*/ */
public final class BackgroundJob { public final class BackgroundJob {
private static final String LOG_TAG = "termux-job"; private static final String LOG_TAG = "termux-task";
final Process mProcess; 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); String[] env = buildEnvironment(false, cwd);
if (cwd == null) cwd = TermuxService.HOME_PATH; if (cwd == null) cwd = TermuxService.HOME_PATH;
@@ -61,6 +61,7 @@ public final class BackgroundJob {
try { try {
int exitCode = mProcess.waitFor(); int exitCode = mProcess.waitFor();
service.onBackgroundJobExited(BackgroundJob.this);
if (exitCode == 0) { if (exitCode == 0) {
Log.i(LOG_TAG, "[" + pid + "] exited normally"); Log.i(LOG_TAG, "[" + pid + "] exited normally");
} else { } else {

View File

@@ -11,6 +11,7 @@ import android.content.res.Resources;
import android.net.Uri; import android.net.Uri;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.Binder; import android.os.Binder;
import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
import android.os.PowerManager; import android.os.PowerManager;
import android.util.Log; import android.util.Log;
@@ -48,12 +49,9 @@ public final class TermuxService extends Service implements SessionChangedCallba
private static final int NOTIFICATION_ID = 1337; private static final int NOTIFICATION_ID = 1337;
/** Intent action to stop the service. */
private static final String ACTION_STOP_SERVICE = "com.termux.service_stop"; 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_wake_lock";
private static final String ACTION_LOCK_WAKE = "com.termux.service_toggle_wake_lock"; private static final String ACTION_UNLOCK_WAKE = "com.termux.service_wake_unlock";
/** 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";
/** Intent action to launch a new terminal session. Executed from TermuxWidgetProvider. */ /** Intent action to launch a new terminal session. Executed from TermuxWidgetProvider. */
public static final String ACTION_EXECUTE = "com.termux.service_execute"; 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 IBinder mBinder = new LocalBinder();
private final Handler mHandler = new Handler();
/** /**
* The terminal sessions which this service manages. * The terminal sessions which this service manages.
* <p/> * <p/>
@@ -76,9 +76,12 @@ public final class TermuxService extends Service implements SessionChangedCallba
*/ */
final List<TerminalSession> mTerminalSessions = new ArrayList<>(); final List<TerminalSession> mTerminalSessions = new ArrayList<>();
final List<BackgroundJob> mBackgroundTasks = new ArrayList<>();
/** Note that the service may often outlive the activity, so need to clear this reference. */ /** Note that the service may often outlive the activity, so need to clear this reference. */
SessionChangedCallback mSessionChangeCallback; SessionChangedCallback mSessionChangeCallback;
/** The wake lock and wifi lock are always acquired and released together. */
private PowerManager.WakeLock mWakeLock; private PowerManager.WakeLock mWakeLock;
private WifiManager.WifiLock mWifiLock; private WifiManager.WifiLock mWifiLock;
@@ -99,21 +102,25 @@ public final class TermuxService extends Service implements SessionChangedCallba
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, EmulatorDebug.LOG_TAG); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, EmulatorDebug.LOG_TAG);
mWakeLock.acquire(); 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); WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
mWifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, EmulatorDebug.LOG_TAG); mWifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, EmulatorDebug.LOG_TAG);
mWifiLock.acquire(); mWifiLock.acquire();
} else { updateNotification();
updateNotification();
}
} else if (ACTION_UNLOCK_WAKE.equals(action)) {
if (mWakeLock != null) {
mWakeLock.release();
mWakeLock = null;
mWifiLock.release(); mWifiLock.release();
mWifiLock = null; mWifiLock = null;
updateNotification();
updateNotification();
} }
updateNotification();
} else if (ACTION_EXECUTE.equals(action)) { } else if (ACTION_EXECUTE.equals(action)) {
Uri executableUri = intent.getData(); Uri executableUri = intent.getData();
String executablePath = (executableUri == null ? null : executableUri.getPath()); 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); String cwd = intent.getStringExtra(EXTRA_CURRENT_WORKING_DIRECTORY);
if (intent.getBooleanExtra("com.termux.execute.background", false)) { if (intent.getBooleanExtra("com.termux.execute.background", false)) {
new BackgroundJob(cwd, executablePath, arguments); mBackgroundTasks.add(new BackgroundJob(cwd, executablePath, arguments, this));
updateNotification();
} else { } else {
TerminalSession newSession = createTermSession(executablePath, arguments, cwd, false); 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: // Make the newly created session the current one to be displayed:
TermuxPreferences.storeCurrentSession(this, newSession); 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)); startActivity(new Intent(this, TermuxActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
} }
} else if (action != null) { } 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. */ /** Update the shown foreground service notification after making any changes that affect it. */
private void updateNotification() { private void updateNotification() {
if (mWakeLock == null && mWifiLock == null && getSessions().isEmpty()) { if (mWakeLock == null && mTerminalSessions.isEmpty() && mBackgroundTasks.isEmpty()) {
// Exit if we are updating after the user disabled all locks with no sessions. // Exit if we are updating after the user disabled all locks with no sessions or tasks running.
stopSelf(); stopSelf();
} else { } else {
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, buildNotification()); ((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); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifyIntent, 0);
int sessionCount = mTerminalSessions.size(); int sessionCount = mTerminalSessions.size();
String contentText = sessionCount + " terminal session" + (sessionCount == 1 ? "" : "s"); int taskCount = mBackgroundTasks.size();
String contentText = sessionCount + " session" + (sessionCount == 1 ? "" : "s");
boolean wakeLockHeld = mWakeLock != null; if (taskCount > 0) {
boolean wifiLockHeld = mWifiLock != null; contentText += ", " + taskCount + " task" + (taskCount == 1 ? "" : "s");
if (wakeLockHeld && wifiLockHeld) {
contentText += " (wake&wifi lock held)";
} else if (wakeLockHeld) {
contentText += " (wake lock held)";
} else if (wifiLockHeld) {
contentText += " (wifi lock held)";
} }
final boolean wakeLockHeld = mWakeLock != null;
if (wakeLockHeld) contentText += " (wake lock held)";
Notification.Builder builder = new Notification.Builder(this); Notification.Builder builder = new Notification.Builder(this);
builder.setContentTitle(getText(R.string.application_name)); builder.setContentTitle(getText(R.string.application_name));
builder.setContentText(contentText); 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, // 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: // 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: // No need to show a timestamp:
builder.setShowWhen(false); 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); 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)); 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); String newWakeAction = wakeLockHeld ? ACTION_UNLOCK_WAKE : ACTION_LOCK_WAKE;
builder.addAction(android.R.drawable.ic_lock_lock, res.getString(R.string.notification_action_wakelock), Intent toggleWakeLockIntent = new Intent(this, TermuxService.class).setAction(newWakeAction);
PendingIntent.getService(this, 0, toggleWakeLockIntent, 0)); String actionTitle = res.getString(wakeLockHeld ?
R.string.notification_action_wake_unlock :
Intent toggleWifiLockIntent = new Intent(this, TermuxService.class).setAction(ACTION_LOCK_WIFI); R.string.notification_action_wake_lock);
builder.addAction(android.R.drawable.ic_lock_lock, res.getString(R.string.notification_action_wifilock), int actionIcon = wakeLockHeld ? android.R.drawable.ic_lock_idle_lock : android.R.drawable.ic_lock_lock;
PendingIntent.getService(this, 0, toggleWifiLockIntent, 0)); builder.addAction(actionIcon, actionTitle, PendingIntent.getService(this, 0, toggleWakeLockIntent, 0));
return builder.build(); return builder.build();
} }
@@ -337,4 +342,13 @@ public final class TermuxService extends Service implements SessionChangedCallba
if (mSessionChangeCallback != null) mSessionChangeCallback.onColorsChanged(session); if (mSessionChangeCallback != null) mSessionChangeCallback.onColorsChanged(session);
} }
public void onBackgroundJobExited(final BackgroundJob task) {
mHandler.post(new Runnable() {
@Override
public void run() {
mBackgroundTasks.remove(task);
updateNotification();
}
});
}
} }

View File

@@ -50,8 +50,8 @@
<string name="styling_install">Install</string> <string name="styling_install">Install</string>
<string name="notification_action_exit">Exit</string> <string name="notification_action_exit">Exit</string>
<string name="notification_action_wakelock">Wake</string> <string name="notification_action_wake_lock">Acquire wakelock</string>
<string name="notification_action_wifilock">Wifi</string> <string name="notification_action_wake_unlock">Release wakelock</string>
<string name="file_received_title">Save file in ~/downloads/</string> <string name="file_received_title">Save file in ~/downloads/</string>
<string name="file_received_edit_button">Edit</string> <string name="file_received_edit_button">Edit</string>