Allow system jobs to be exempted from app-standby
This flag will allow the sync manager to exempt certain kind of sync requests.
- This will only exempt jobs from app-standby.
- EBS still won't exempt them. Battery saver cuts background network anyway, so
background syncs will still not work, and it didn't used to work pre-P either.
- Manual force-app standby still doesn't allow them to run.
Bug: 72443754
Test: Build and boot. The behavior shouldn't change since none uses the flag yet.
Test: atest CtsJobSchedulerTestCases
Change-Id: I806b97bb4b7da773479e878e6eccb792b03eadc1
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 2066f2a..c087bff 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -1809,7 +1809,9 @@
// If the app is in a non-active standby bucket, make sure we've waited
// an appropriate amount of time since the last invocation. During device-
// wide parole, standby bucketing is ignored.
- if (!mInParole) {
+ //
+ // But if a job has FLAG_EXEMPT_FROM_APP_STANDBY, don't check it.
+ if (!mInParole && !job.getJob().isExemptedFromAppStandby()) {
final int bucket = job.getStandbyBucket();
if (mHeartbeat < mNextBucketHeartbeat[bucket]) {
// Only skip this job if it's still waiting for the end of its (initial) nominal
@@ -2295,6 +2297,22 @@
return canPersist;
}
+ private void validateJobFlags(JobInfo job, int callingUid) {
+ if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
+ }
+ if ((job.getFlags() & JobInfo.FLAG_EXEMPT_FROM_APP_STANDBY) != 0) {
+ if (callingUid != Process.SYSTEM_UID) {
+ throw new SecurityException("Job has invalid flags");
+ }
+ if (job.hasLateConstraint() || job.hasEarlyConstraint()) {
+ Slog.wtf(TAG, "Jobs with time-constraints mustn't have"
+ +" FLAG_EXEMPT_FROM_APP_STANDBY. Job=" + job);
+ }
+ }
+ }
+
// IJobScheduler implementation
@Override
public int schedule(JobInfo job) throws RemoteException {
@@ -2313,10 +2331,7 @@
}
}
- if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
- getContext().enforceCallingOrSelfPermission(
- android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
- }
+ validateJobFlags(job, uid);
long ident = Binder.clearCallingIdentity();
try {
@@ -2344,10 +2359,7 @@
throw new NullPointerException("work is null");
}
- if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
- getContext().enforceCallingOrSelfPermission(
- android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
- }
+ validateJobFlags(job, uid);
long ident = Binder.clearCallingIdentity();
try {
@@ -2378,10 +2390,7 @@
+ " not permitted to schedule jobs for other apps");
}
- if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
- getContext().enforceCallingOrSelfPermission(
- android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
- }
+ validateJobFlags(job, callerUid);
long ident = Binder.clearCallingIdentity();
try {