Mechanical refactoring to improve job dumping.

First, JobStatusFunctor was really Consumer<JobStatus> before we
had the java.util.function APIs, so switch everyone over.  Replace
most usages with lambdas; no additional runtime cost, since existing
code was already creating classes.

Move dump() to accept Predicate<JobStatus> for their filtering
behavior, enabling more future advanced filtering using any
attributes of JobStatus.  Also move dump() to IndentingPrintWriter
to avoid passing around tedious prefix information.  Makes it much
easier to print sane-looking output.

Add IndentingPrintWriter support for initial prefix values.

Test: manual dumpsys output looks sane
Bug: 73019091
Change-Id: I4c2398443b42dfb48135ab900d4331ff6d2bb5c4
diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java
index 021eccd..4b48824 100644
--- a/services/core/java/com/android/server/job/controllers/AppIdleController.java
+++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java
@@ -23,12 +23,13 @@
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerService;
-import com.android.server.job.JobStore;
 import com.android.server.job.StateControllerProto;
 
-import java.io.PrintWriter;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
 
 /**
  * Controls when apps are considered idle and if jobs pertaining to those apps should
@@ -49,10 +50,11 @@
     private boolean mInitializedParoleOn;
     boolean mAppIdleParoleOn;
 
-    final class GlobalUpdateFunc implements JobStore.JobStatusFunctor {
+    final class GlobalUpdateFunc implements Consumer<JobStatus> {
         boolean mChanged;
 
-        @Override public void process(JobStatus jobStatus) {
+        @Override
+        public void accept(JobStatus jobStatus) {
             String packageName = jobStatus.getSourcePackageName();
             final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
                     jobStatus.getSourceUid(), jobStatus.getSourceUserId());
@@ -63,9 +65,9 @@
                 mChanged = true;
             }
         }
-    };
+    }
 
-    final static class PackageUpdateFunc implements JobStore.JobStatusFunctor {
+    final static class PackageUpdateFunc implements Consumer<JobStatus> {
         final int mUserId;
         final String mPackage;
         final boolean mIdle;
@@ -77,7 +79,8 @@
             mIdle = idle;
         }
 
-        @Override public void process(JobStatus jobStatus) {
+        @Override
+        public void accept(JobStatus jobStatus) {
             if (jobStatus.getSourcePackageName().equals(mPackage)
                     && jobStatus.getSourceUserId() == mUserId) {
                 if (jobStatus.setAppNotIdleConstraintSatisfied(!mIdle)) {
@@ -89,7 +92,7 @@
                 }
             }
         }
-    };
+    }
 
     public static AppIdleController get(JobSchedulerService service) {
         synchronized (sCreationLock) {
@@ -131,56 +134,46 @@
     }
 
     @Override
-    public void dumpControllerStateLocked(final PrintWriter pw, final int filterUid) {
-        pw.print("AppIdle: parole on = ");
-        pw.println(mAppIdleParoleOn);
-        mJobSchedulerService.getJobStore().forEachJob(new JobStore.JobStatusFunctor() {
-            @Override public void process(JobStatus jobStatus) {
-                // Skip printing details if the caller requested a filter
-                if (!jobStatus.shouldDump(filterUid)) {
-                    return;
-                }
-                pw.print("  #");
-                jobStatus.printUniqueId(pw);
-                pw.print(" from ");
-                UserHandle.formatUid(pw, jobStatus.getSourceUid());
-                pw.print(": ");
-                pw.print(jobStatus.getSourcePackageName());
-                if ((jobStatus.satisfiedConstraints&JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0) {
-                    pw.println(" RUNNABLE");
-                } else {
-                    pw.println(" WAITING");
-                }
+    public void dumpControllerStateLocked(final IndentingPrintWriter pw,
+            final Predicate<JobStatus> predicate) {
+        pw.println("Parole on: " + mAppIdleParoleOn);
+        pw.println();
+
+        mJobSchedulerService.getJobStore().forEachJob(predicate, (jobStatus) -> {
+            pw.print("#");
+            jobStatus.printUniqueId(pw);
+            pw.print(" from ");
+            UserHandle.formatUid(pw, jobStatus.getSourceUid());
+            pw.print(": ");
+            pw.print(jobStatus.getSourcePackageName());
+            if ((jobStatus.satisfiedConstraints&JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0) {
+                pw.println(" RUNNABLE");
+            } else {
+                pw.println(" WAITING");
             }
         });
     }
 
     @Override
-    public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, int filterUid) {
+    public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
+            Predicate<JobStatus> predicate) {
         final long token = proto.start(fieldId);
         final long mToken = proto.start(StateControllerProto.APP_IDLE);
 
         proto.write(StateControllerProto.AppIdleController.IS_PAROLE_ON, mAppIdleParoleOn);
 
-        mJobSchedulerService.getJobStore().forEachJob(new JobStore.JobStatusFunctor() {
-            @Override public void process(JobStatus js) {
-                // Skip printing details if the caller requested a filter
-                if (!js.shouldDump(filterUid)) {
-                    return;
-                }
-
-                final long jsToken =
-                        proto.start(StateControllerProto.AppIdleController.TRACKED_JOBS);
-                js.writeToShortProto(proto, StateControllerProto.AppIdleController.TrackedJob.INFO);
-                proto.write(StateControllerProto.AppIdleController.TrackedJob.SOURCE_UID,
-                        js.getSourceUid());
-                proto.write(StateControllerProto.AppIdleController.TrackedJob.SOURCE_PACKAGE_NAME,
-                        js.getSourcePackageName());
-                proto.write(
-                        StateControllerProto.AppIdleController.TrackedJob.ARE_CONSTRAINTS_SATISFIED,
-                        (js.satisfiedConstraints & JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0);
-                proto.end(jsToken);
-            }
+        mJobSchedulerService.getJobStore().forEachJob(predicate, (js) -> {
+            final long jsToken =
+                    proto.start(StateControllerProto.AppIdleController.TRACKED_JOBS);
+            js.writeToShortProto(proto, StateControllerProto.AppIdleController.TrackedJob.INFO);
+            proto.write(StateControllerProto.AppIdleController.TrackedJob.SOURCE_UID,
+                    js.getSourceUid());
+            proto.write(StateControllerProto.AppIdleController.TrackedJob.SOURCE_PACKAGE_NAME,
+                    js.getSourcePackageName());
+            proto.write(
+                    StateControllerProto.AppIdleController.TrackedJob.ARE_CONSTRAINTS_SATISFIED,
+                    (js.satisfiedConstraints & JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0);
+            proto.end(jsToken);
         });
 
         proto.end(mToken);