Remove demotion flags when a JobWorkItem is enqueued.

Remove the demotion flags from a user-initiated job if the app
successfully enqueues a new JobWorkItem. If an app successfully enqueues
a JobWorkItem to a UI job, then the app is in a state to successfully
schedule a UI job. Presumably, the user has asked for this additional
bit of work, so it makes sense to remove the demotion flags. For now,
we only do this for UI jobs since they have strict scheduling
requirements. It's harder to assume other jobs were scheduled due to
user interaction/request.

This mimics the behavior when a UI job is rescheduled (without adding a
JobWorkItem). Internal flags aren't copied over when a job is
rescheduled.

Bug: 281838527
Test: atest FrameworksMockingServicesTests:JobStatusTest
Change-Id: I591afc7c0ac23fa0bda646fd12053be58ff5d4ee
This commit is contained in:
Kweku Adams
2023-05-10 15:29:38 +00:00
parent 22490466ca
commit 4e443ad09c
3 changed files with 63 additions and 0 deletions

View File

@@ -1500,6 +1500,16 @@ public class JobSchedulerService extends com.android.server.SystemService
}
toCancel.enqueueWorkLocked(work);
if (toCancel.getJob().isUserInitiated()) {
// The app is in a state to successfully schedule a UI job. Presumably, the
// user has asked for this additional bit of work, so remove any demotion
// flags. Only do this for UI jobs since they have strict scheduling
// requirements; it's harder to assume other jobs were scheduled due to
// user interaction/request.
toCancel.removeInternalFlags(
JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER
| JobStatus.INTERNAL_FLAG_DEMOTED_BY_SYSTEM_UIJ);
}
mJobs.touchJob(toCancel);
sEnqueuedJwiHighWaterMarkLogger.logSampleWithUid(uId, toCancel.getWorkCount());

View File

@@ -1177,6 +1177,10 @@ public final class JobStatus {
mInternalFlags |= flags;
}
public void removeInternalFlags(int flags) {
mInternalFlags = mInternalFlags & ~flags;
}
int getPreferredConstraintFlags() {
return mPreferredConstraints;
}

View File

@@ -581,6 +581,49 @@ public class JobStatusTest {
assertEquals(JobInfo.PRIORITY_HIGH, job.getEffectivePriority());
}
@Test
public void testModifyingInternalFlags() {
final JobInfo jobInfo =
new JobInfo.Builder(101, new ComponentName("foo", "bar"))
.setExpedited(true)
.build();
JobStatus job = createJobStatus(jobInfo);
assertEquals(0, job.getInternalFlags());
// Add single flag
job.addInternalFlags(JobStatus.INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION);
assertEquals(JobStatus.INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION, job.getInternalFlags());
// Add multiple flags
job.addInternalFlags(JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER
| JobStatus.INTERNAL_FLAG_DEMOTED_BY_SYSTEM_UIJ);
assertEquals(JobStatus.INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION
| JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER
| JobStatus.INTERNAL_FLAG_DEMOTED_BY_SYSTEM_UIJ,
job.getInternalFlags());
// Add flag that's already set
job.addInternalFlags(JobStatus.INTERNAL_FLAG_DEMOTED_BY_SYSTEM_UIJ);
assertEquals(JobStatus.INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION
| JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER
| JobStatus.INTERNAL_FLAG_DEMOTED_BY_SYSTEM_UIJ,
job.getInternalFlags());
// Remove multiple
job.removeInternalFlags(JobStatus.INTERNAL_FLAG_HAS_FOREGROUND_EXEMPTION
| JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER);
assertEquals(JobStatus.INTERNAL_FLAG_DEMOTED_BY_SYSTEM_UIJ, job.getInternalFlags());
// Remove one that isn't set
job.removeInternalFlags(JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER);
assertEquals(JobStatus.INTERNAL_FLAG_DEMOTED_BY_SYSTEM_UIJ, job.getInternalFlags());
// Remove final flag.
job.removeInternalFlags(JobStatus.INTERNAL_FLAG_DEMOTED_BY_SYSTEM_UIJ);
assertEquals(0, job.getInternalFlags());
}
@Test
public void testShouldTreatAsUserInitiated() {
JobInfo jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar"))
@@ -619,6 +662,9 @@ public class JobStatusTest {
rescheduledJob = new JobStatus(job, NO_EARLIEST_RUNTIME, NO_LATEST_RUNTIME,
0, 0, 0, 0, 0);
assertFalse(rescheduledJob.shouldTreatAsUserInitiatedJob());
rescheduledJob.removeInternalFlags(JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER);
assertTrue(rescheduledJob.shouldTreatAsUserInitiatedJob());
}
@Test
@@ -641,6 +687,9 @@ public class JobStatusTest {
rescheduledJob = new JobStatus(job, NO_EARLIEST_RUNTIME, NO_LATEST_RUNTIME,
0, 0, 0, 0, 0);
assertFalse(rescheduledJob.shouldTreatAsUserInitiatedJob());
rescheduledJob.removeInternalFlags(JobStatus.INTERNAL_FLAG_DEMOTED_BY_SYSTEM_UIJ);
assertTrue(rescheduledJob.shouldTreatAsUserInitiatedJob());
}
/**