Flag to mark foreground jobs, fix data saver.

When a job will eventually run in the foreground, the internal
scheduling needs to ignore any background network restrictions when
satisfying constraints.  This also means the job should ignore the
current device doze state, since the requesting app could get the
same behavior by starting their own foreground service.

Always dispatch network policy changes to ConnectivityService first
to ensure that it has up-to-date information.  Fix bugs around data
saver that were causing networks to not be marked as BLOCKED for
background apps; before this fix apps would have been spinning in
internal connectivity loops, thinking that the network was actually
connected when the kernel was actually blocking their traffic.

Offer new ConnectivityService method overloads to ignore the blocked
state for a specific UID.

Print unsatisfied job constraints to aid debugging.

Bug: 26571724
Change-Id: Iaaa17933e6dc1bf6d3dff26d0bfc12222e51e241
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 590d075..19bede9 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -297,6 +297,10 @@
         return job.getPriority();
     }
 
+    public int getFlags() {
+        return job.getFlags();
+    }
+
     public boolean hasConnectivityConstraint() {
         return (requiredConstraints&CONSTRAINT_CONNECTIVITY) != 0;
     }
@@ -416,12 +420,12 @@
         // satisfied).
         // AppNotIdle implicit constraint must be satisfied
         // DeviceNotDozing implicit constraint must be satisfied
-        return (isConstraintsSatisfied()
-                || (!job.isPeriodic()
-                && hasDeadlineConstraint() && (satisfiedConstraints&CONSTRAINT_DEADLINE) != 0)
-                )
-                && (satisfiedConstraints & CONSTRAINT_APP_NOT_IDLE) != 0
-                && (satisfiedConstraints & CONSTRAINT_DEVICE_NOT_DOZING) != 0;
+        final boolean deadlineSatisfied = (!job.isPeriodic() && hasDeadlineConstraint()
+                && (satisfiedConstraints & CONSTRAINT_DEADLINE) != 0);
+        final boolean notIdle = (satisfiedConstraints & CONSTRAINT_APP_NOT_IDLE) != 0;
+        final boolean notDozing = (satisfiedConstraints & CONSTRAINT_DEVICE_NOT_DOZING) != 0
+                || (job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
+        return (isConstraintsSatisfied() || deadlineSatisfied) && notIdle && notDozing;
     }
 
     static final int CONSTRAINTS_OF_INTEREST =
@@ -561,6 +565,10 @@
             if (job.getPriority() != 0) {
                 pw.print(prefix); pw.print("  Priority: "); pw.println(job.getPriority());
             }
+            if (job.getFlags() != 0) {
+                pw.print(prefix); pw.print("  Flags: ");
+                pw.println(Integer.toHexString(job.getFlags()));
+            }
             pw.print(prefix); pw.print("  Requires: charging=");
             pw.print(job.isRequireCharging()); pw.print(" deviceIdle=");
             pw.println(job.isRequireDeviceIdle());
@@ -613,6 +621,9 @@
             pw.print(prefix); pw.print("Satisfied constraints:");
             dumpConstraints(pw, satisfiedConstraints);
             pw.println();
+            pw.print(prefix); pw.print("Unsatisfied constraints:");
+            dumpConstraints(pw, (requiredConstraints & ~satisfiedConstraints));
+            pw.println();
         }
         if (changedAuthorities != null) {
             pw.print(prefix); pw.println("Changed authorities:");