From 959acb52739f4883400a4a0aac7d8837e35f014b Mon Sep 17 00:00:00 2001 From: Makoto Onuki Date: Fri, 26 Jan 2018 14:10:03 -0800 Subject: [PATCH] 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 --- core/java/android/app/job/JobInfo.java | 15 ++++++++ .../server/job/JobSchedulerService.java | 35 ++++++++++++------- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java index cba9dcc3c4cc8..a1ad825c3a291 100644 --- a/core/java/android/app/job/JobInfo.java +++ b/core/java/android/app/job/JobInfo.java @@ -255,6 +255,14 @@ public class JobInfo implements Parcelable { */ public static final int FLAG_IS_PREFETCH = 1 << 2; + /** + * This job needs to be exempted from the app standby throttling. Only the system (UID 1000) + * can set it. Jobs with a time constrant must not have it. + * + * @hide + */ + public static final int FLAG_EXEMPT_FROM_APP_STANDBY = 1 << 3; + /** * @hide */ @@ -355,6 +363,13 @@ public class JobInfo implements Parcelable { return flags; } + /** @hide */ + public boolean isExemptedFromAppStandby() { + return ((flags & FLAG_EXEMPT_FROM_APP_STANDBY) != 0) + && !hasEarlyConstraint() + && !hasLateConstraint(); + } + /** * Whether this job requires that the device be charging (or be a non-battery-powered * device connected to permanent power, such as Android TV devices). diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index 2066f2af46dd4..c087bff4e8a58 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 @@ public final class JobSchedulerService extends com.android.server.SystemService // 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 @@ public final class JobSchedulerService extends com.android.server.SystemService 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 @@ public final class JobSchedulerService extends com.android.server.SystemService } } - 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 @@ public final class JobSchedulerService extends com.android.server.SystemService 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 @@ public final class JobSchedulerService extends com.android.server.SystemService + " 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 {