summaryrefslogtreecommitdiff
path: root/src/com
diff options
context:
space:
mode:
author Austin Tankiang <austinct@google.com> 2025-03-06 13:25:12 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-03-06 13:25:12 -0800
commitb6d83baa452320fa5c2d35afb8bd31785041574e (patch)
tree98fbaa038938bcd35f1d235efa9bd3f9a0654098 /src/com
parent800e5f08ccdde397b2ae935e3b176c6b88a46ed6 (diff)
parent9d5b960f0229d9a0e10bcca4851073bce2ead0eb (diff)
Merge "Broadcast the progress of Jobs" into main
Diffstat (limited to 'src/com')
-rw-r--r--src/com/android/documentsui/services/FileOperationService.java76
-rw-r--r--src/com/android/documentsui/util/FlagUtils.kt5
2 files changed, 79 insertions, 2 deletions
diff --git a/src/com/android/documentsui/services/FileOperationService.java b/src/com/android/documentsui/services/FileOperationService.java
index c7be5f4fc..dcb2c1db4 100644
--- a/src/com/android/documentsui/services/FileOperationService.java
+++ b/src/com/android/documentsui/services/FileOperationService.java
@@ -17,6 +17,7 @@
package com.android.documentsui.services;
import static com.android.documentsui.base.SharedMinimal.DEBUG;
+import static com.android.documentsui.util.FlagUtils.isVisualSignalsFlagEnabled;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -126,9 +127,15 @@ public class FileOperationService extends Service implements Job.Listener {
// Use a features to determine if notification channel is enabled.
@VisibleForTesting Features features;
+ // Used so tests can force the state of visual signals.
+ @VisibleForTesting Boolean mVisualSignalsEnabled = isVisualSignalsFlagEnabled();
+
@GuardedBy("mJobs")
private final Map<String, JobRecord> mJobs = new LinkedHashMap<>();
+ // Used to send periodic broadcasts for job progress.
+ private GlobalJobMonitor mJobMonitor;
+
// The job whose notification is used to keep the service in foreground mode.
@GuardedBy("mJobs")
private Job mForegroundJob;
@@ -162,6 +169,10 @@ public class FileOperationService extends Service implements Job.Listener {
notificationManager = getSystemService(NotificationManager.class);
}
+ if (mVisualSignalsEnabled && mJobMonitor == null) {
+ mJobMonitor = new GlobalJobMonitor();
+ }
+
UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
features = new Features.RuntimeFeatures(getResources(), userManager);
setUpNotificationChannel();
@@ -188,6 +199,10 @@ public class FileOperationService extends Service implements Job.Listener {
Log.d(TAG, "Shutting down executor.");
}
+ if (mJobMonitor != null) {
+ mJobMonitor.stop();
+ }
+
List<Runnable> unfinishedCopies = executor.shutdownNow();
List<Runnable> unfinishedDeletions = deletionExecutor.shutdownNow();
List<Runnable> unfinished =
@@ -330,6 +345,10 @@ public class FileOperationService extends Service implements Job.Listener {
assert(record != null);
record.job.cleanup();
+ if (mVisualSignalsEnabled && mJobs.isEmpty()) {
+ mJobMonitor.stop();
+ }
+
// Delay the shutdown until we've cleaned up all notifications. shutdown() is now posted in
// onFinished(Job job) to main thread.
}
@@ -389,8 +408,12 @@ public class FileOperationService extends Service implements Job.Listener {
}
// Set up related monitor
- JobMonitor monitor = new JobMonitor(job);
- monitor.start();
+ if (mVisualSignalsEnabled) {
+ mJobMonitor.start();
+ } else {
+ JobMonitor monitor = new JobMonitor(job);
+ monitor.start();
+ }
}
@Override
@@ -399,6 +422,9 @@ public class FileOperationService extends Service implements Job.Listener {
if (DEBUG) {
Log.d(TAG, "onFinished: " + job.id);
}
+ if (mVisualSignalsEnabled) {
+ mJobMonitor.sendProgress();
+ }
synchronized (mJobs) {
// Delete the job from mJobs first to avoid this job being selected as the foreground
@@ -545,6 +571,52 @@ public class FileOperationService extends Service implements Job.Listener {
}
}
+ /**
+ * A class used to periodically poll the state of every running job.
+ *
+ * We need to be sending the progress of every job, so rather than having a single monitor per
+ * job, have one for the whole service.
+ */
+ private final class GlobalJobMonitor implements Runnable {
+ private static final long PROGRESS_INTERVAL_MILLIS = 500L;
+ private boolean mRunning = false;
+
+ private void start() {
+ if (!mRunning) {
+ handler.post(this);
+ }
+ mRunning = true;
+ }
+
+ private void stop() {
+ mRunning = false;
+ handler.removeCallbacks(this);
+ }
+
+ private void sendProgress() {
+ var progress = new ArrayList<JobProgress>();
+ synchronized (mJobs) {
+ for (JobRecord rec : mJobs.values()) {
+ progress.add(rec.job.getJobProgress());
+ }
+ }
+ Intent intent = new Intent();
+ intent.setPackage(getPackageName());
+ intent.setAction("com.android.documentsui.PROGRESS");
+ intent.putExtra("id", 0);
+ intent.putParcelableArrayListExtra("progress", progress);
+ sendBroadcast(intent);
+ }
+
+ @Override
+ public void run() {
+ sendProgress();
+ if (mRunning) {
+ handler.postDelayed(this, PROGRESS_INTERVAL_MILLIS);
+ }
+ }
+ }
+
@Override
public IBinder onBind(Intent intent) {
return null; // Boilerplate. See super#onBind
diff --git a/src/com/android/documentsui/util/FlagUtils.kt b/src/com/android/documentsui/util/FlagUtils.kt
index 606f071f2..eee51be89 100644
--- a/src/com/android/documentsui/util/FlagUtils.kt
+++ b/src/com/android/documentsui/util/FlagUtils.kt
@@ -45,6 +45,11 @@ class FlagUtils {
}
@JvmStatic
+ fun isVisualSignalsFlagEnabled(): Boolean {
+ return Flags.visualSignalsRo() && isUseMaterial3FlagEnabled()
+ }
+
+ @JvmStatic
fun isHideRootsOnDesktopFlagEnabled(): Boolean {
return Flags.hideRootsOnDesktopRo()
}