From 68be0cb20499b423e39b6b93ccf8706c72a4e9da Mon Sep 17 00:00:00 2001 From: M66B Date: Fri, 18 Jun 2021 08:37:11 +0200 Subject: [PATCH] Added task monitoring --- app/src/main/java/eu/faircode/email/Log.java | 31 +++++++++-- .../java/eu/faircode/email/SimpleTask.java | 51 ++++++++++++++++++- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/Log.java b/app/src/main/java/eu/faircode/email/Log.java index fc196a7ff4..7de150e7d9 100644 --- a/app/src/main/java/eu/faircode/email/Log.java +++ b/app/src/main/java/eu/faircode/email/Log.java @@ -1542,11 +1542,12 @@ public class Log { attachNetworkInfo(context, draft.id, 3); attachLog(context, draft.id, 4); attachOperations(context, draft.id, 5); - attachLogcat(context, draft.id, 6); + attachTasks(context, draft.id, 6); + attachLogcat(context, draft.id, 7); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) - attachNotificationInfo(context, draft.id, 7); + attachNotificationInfo(context, draft.id, 8); //if (MessageClassifier.isEnabled(context)) - // attachClassifierData(context, draft.id, 8); + // attachClassifierData(context, draft.id, 9); EntityOperation.queue(context, draft, EntityOperation.ADD); @@ -2062,6 +2063,30 @@ public class Log { db.attachment().setDownloaded(attachment.id, size); } + private static void attachTasks(Context context, long id, int sequence) throws IOException { + DB db = DB.getInstance(context); + + EntityAttachment attachment = new EntityAttachment(); + attachment.message = id; + attachment.sequence = sequence; + attachment.name = "tasks.txt"; + attachment.type = "text/plain"; + attachment.disposition = Part.ATTACHMENT; + attachment.size = null; + attachment.progress = 0; + attachment.id = db.attachment().insertAttachment(attachment); + + long size = 0; + File file = attachment.getFile(context); + try (OutputStream os = new BufferedOutputStream(new FileOutputStream(file))) { + for (SimpleTask task : SimpleTask.getList()) { + size += write(os, String.format("%s\r\n", task.toString())); + } + } + + db.attachment().setDownloaded(attachment.id, size); + } + private static void attachLogcat(Context context, long id, int sequence) throws IOException { DB db = DB.getInstance(context); diff --git a/app/src/main/java/eu/faircode/email/SimpleTask.java b/app/src/main/java/eu/faircode/email/SimpleTask.java index f049c892b0..0f78238e91 100644 --- a/app/src/main/java/eu/faircode/email/SimpleTask.java +++ b/app/src/main/java/eu/faircode/email/SimpleTask.java @@ -53,6 +53,10 @@ public abstract class SimpleTask implements LifecycleObserver { private boolean count = true; private String name; + private long created; + private long started; + private boolean reported; + private boolean interrupted; private Future future; private ExecutorService localExecutor; @@ -60,8 +64,16 @@ public abstract class SimpleTask implements LifecycleObserver { private static ExecutorService globalExecutor = null; private static final List tasks = new ArrayList<>(); + private static final int MAX_WAKELOCK = 30 * 60 * 1000; // milliseconds + private static final int REPORT_AFTER = 5 * 60 * 1000; // milliseconds + private static final int CANCEL_AFTER = MAX_WAKELOCK; // milliseconds + static final String ACTION_TASK_COUNT = BuildConfig.APPLICATION_ID + ".ACTION_TASK_COUNT"; + public SimpleTask() { + created = new Date().getTime(); + } + public SimpleTask setLog(boolean log) { this.log = log; if (!log) @@ -121,6 +133,7 @@ public abstract class SimpleTask implements LifecycleObserver { private void run(final Context context, final LifecycleOwner owner, final Bundle args, final String name) { this.name = name; + this.started = new Date().getTime(); if (owner instanceof TwoStateOwner) Log.e(new Throwable("SimpleTask/TwoStateOwner")); @@ -152,7 +165,7 @@ public abstract class SimpleTask implements LifecycleObserver { public void run() { // Run in background thread try { - wl.acquire(); + wl.acquire(MAX_WAKELOCK); if (log) Log.i("Executing task=" + name); @@ -264,6 +277,26 @@ public abstract class SimpleTask implements LifecycleObserver { } private void updateTaskCount(Context context) { + long now = new Date().getTime(); + synchronized (tasks) { + for (SimpleTask task : tasks) { + long pending = now - task.created; + long elapsed = now - task.started; + if (elapsed > CANCEL_AFTER && !task.interrupted && task.started > 0) { + task.interrupted = true; + if (task.future != null && !task.future.isDone()) + task.future.cancel(true); + } else if (pending > REPORT_AFTER && !task.reported) { + task.reported = true; + Log.e("Long running task " + task.name + + " pending=" + (pending / 1000) + + " elapsed=" + (elapsed / 1000) + + " done=" + (task.future == null ? null : task.future.isDone()) + + " cancelled=" + (task.future == null ? null : task.future.isCancelled())); + } + } + } + int executing = getCount(); Log.i("Remaining tasks=" + executing + "/" + tasks.size()); LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context); @@ -283,6 +316,16 @@ public abstract class SimpleTask implements LifecycleObserver { protected void onPostExecute(Bundle args) { } + @Override + public String toString() { + long now = new Date().getTime(); + long pending = now - created; + long elapsed = now - started; + return name + + " pending=" + (pending / 1000) + "s" + + " elapsed=" + (elapsed / 1000) + "s"; + } + static int getCount() { int executing = 0; synchronized (tasks) { @@ -292,4 +335,10 @@ public abstract class SimpleTask implements LifecycleObserver { } return executing; } + + static List getList() { + synchronized (tasks) { + return new ArrayList<>(tasks); + } + } }