Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 022f67e2 authored by Kweku Adams's avatar Kweku Adams Committed by Android (Google) Code Review
Browse files

Merge "Remove jobs from the pending queue on user stop."

parents 17bd64d1 59c3b84f
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -1584,6 +1584,12 @@ public class JobSchedulerService extends com.android.server.SystemService
        return reason;
    }

    @VisibleForTesting
    @JobScheduler.PendingJobReason
    int getPendingJobReason(JobStatus job) {
        return getPendingJobReason(job.getUid(), job.getNamespace(), job.getJobId());
    }

    @JobScheduler.PendingJobReason
    @GuardedBy("mLock")
    private int getPendingJobReasonLocked(int uid, String namespace, int jobId) {
@@ -1694,7 +1700,8 @@ public class JobSchedulerService extends com.android.server.SystemService
        }
    }

    private void stopUserVisibleJobsInternal(@NonNull String packageName, int userId) {
    @VisibleForTesting
    void stopUserVisibleJobsInternal(@NonNull String packageName, int userId) {
        final int packageUid = mLocalPM.getPackageUid(packageName, 0, userId);
        if (packageUid < 0) {
            Slog.wtf(TAG, "Asked to stop jobs of an unknown package");
@@ -1716,6 +1723,21 @@ public class JobSchedulerService extends com.android.server.SystemService
                // to stop only that work, B's jobs would be demoted as well.
                // TODO(255768978): make it possible to demote only the relevant subset of jobs
                job.addInternalFlags(JobStatus.INTERNAL_FLAG_DEMOTED_BY_USER);

                // The app process will be killed soon. There's no point keeping its jobs in
                // the pending queue to try and start them.
                if (mPendingJobQueue.remove(job)) {
                    synchronized (mPendingJobReasonCache) {
                        SparseIntArray jobIdToReason = mPendingJobReasonCache.get(
                                job.getUid(), job.getNamespace());
                        if (jobIdToReason == null) {
                            jobIdToReason = new SparseIntArray();
                            mPendingJobReasonCache.add(job.getUid(), job.getNamespace(),
                                    jobIdToReason);
                        }
                        jobIdToReason.put(job.getJobId(), JobScheduler.PENDING_JOB_REASON_USER);
                    }
                }
            }
        }
    }
+65 −4
Original line number Diff line number Diff line
@@ -30,7 +30,9 @@ import static com.android.server.job.JobSchedulerService.RARE_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -95,6 +97,8 @@ public class JobSchedulerServiceTest {
    private ActivityManagerInternal mActivityMangerInternal;
    @Mock
    private Context mContext;
    @Mock
    private PackageManagerInternal mPackageManagerInternal;

    private class TestJobSchedulerService extends JobSchedulerService {
        TestJobSchedulerService(Context context) {
@@ -121,6 +125,8 @@ public class JobSchedulerServiceTest {
                .when(() -> LocalServices.getService(AppStandbyInternal.class));
        doReturn(mock(BatteryManagerInternal.class))
                .when(() -> LocalServices.getService(BatteryManagerInternal.class));
        doReturn(mPackageManagerInternal)
                .when(() -> LocalServices.getService(PackageManagerInternal.class));
        doReturn(mock(UsageStatsManagerInternal.class))
                .when(() -> LocalServices.getService(UsageStatsManagerInternal.class));
        when(mContext.getString(anyInt())).thenReturn("some_test_string");
@@ -138,9 +144,6 @@ public class JobSchedulerServiceTest {
        // Used in JobConcurrencyManager.
        doReturn(mock(UserManagerInternal.class))
                .when(() -> LocalServices.getService(UserManagerInternal.class));
        // Used in JobStatus.
        doReturn(mock(PackageManagerInternal.class))
                .when(() -> LocalServices.getService(PackageManagerInternal.class));
        // Called via IdleController constructor.
        when(mContext.getPackageManager()).thenReturn(mock(PackageManager.class));
        when(mContext.getResources()).thenReturn(mock(Resources.class));
@@ -197,8 +200,13 @@ public class JobSchedulerServiceTest {

    private JobStatus createJobStatus(String testTag, JobInfo.Builder jobInfoBuilder,
            int callingUid) {
        return createJobStatus(testTag, jobInfoBuilder, callingUid, "com.android.test");
    }

    private JobStatus createJobStatus(String testTag, JobInfo.Builder jobInfoBuilder,
            int callingUid, String sourcePkg) {
        return JobStatus.createFromJobInfo(
                jobInfoBuilder.build(), callingUid, "com.android.test", 0, "JSSTest", testTag);
                jobInfoBuilder.build(), callingUid, sourcePkg, 0, "JSSTest", testTag);
    }

    private void grantRunLongJobsPermission(boolean grant) {
@@ -1238,4 +1246,57 @@ public class JobSchedulerServiceTest {
                            0, "JSSTest", ""));
        }
    }

    /** Tests that jobs are removed from the pending list if the user stops the app. */
    @Test
    public void testUserStopRemovesPending() {
        spyOn(mService);

        JobStatus job1a = createJobStatus("testUserStopRemovesPending",
                createJobInfo(1), 1, "pkg1");
        JobStatus job1b = createJobStatus("testUserStopRemovesPending",
                createJobInfo(2), 1, "pkg1");
        JobStatus job2a = createJobStatus("testUserStopRemovesPending",
                createJobInfo(1), 2, "pkg2");
        JobStatus job2b = createJobStatus("testUserStopRemovesPending",
                createJobInfo(2), 2, "pkg2");
        doReturn(1).when(mPackageManagerInternal).getPackageUid("pkg1", 0, 0);
        doReturn(11).when(mPackageManagerInternal).getPackageUid("pkg1", 0, 1);
        doReturn(2).when(mPackageManagerInternal).getPackageUid("pkg2", 0, 0);

        mService.getPendingJobQueue().clear();
        mService.getPendingJobQueue().add(job1a);
        mService.getPendingJobQueue().add(job1b);
        mService.getPendingJobQueue().add(job2a);
        mService.getPendingJobQueue().add(job2b);
        mService.getJobStore().add(job1a);
        mService.getJobStore().add(job1b);
        mService.getJobStore().add(job2a);
        mService.getJobStore().add(job2b);

        mService.stopUserVisibleJobsInternal("pkg1", 1);
        assertEquals(4, mService.getPendingJobQueue().size());
        assertTrue(mService.getPendingJobQueue().contains(job1a));
        assertTrue(mService.getPendingJobQueue().contains(job1b));
        assertTrue(mService.getPendingJobQueue().contains(job2a));
        assertTrue(mService.getPendingJobQueue().contains(job2b));

        mService.stopUserVisibleJobsInternal("pkg1", 0);
        assertEquals(2, mService.getPendingJobQueue().size());
        assertFalse(mService.getPendingJobQueue().contains(job1a));
        assertEquals(JobScheduler.PENDING_JOB_REASON_USER, mService.getPendingJobReason(job1a));
        assertFalse(mService.getPendingJobQueue().contains(job1b));
        assertEquals(JobScheduler.PENDING_JOB_REASON_USER, mService.getPendingJobReason(job1b));
        assertTrue(mService.getPendingJobQueue().contains(job2a));
        assertTrue(mService.getPendingJobQueue().contains(job2b));

        mService.stopUserVisibleJobsInternal("pkg2", 0);
        assertEquals(0, mService.getPendingJobQueue().size());
        assertFalse(mService.getPendingJobQueue().contains(job1a));
        assertFalse(mService.getPendingJobQueue().contains(job1b));
        assertFalse(mService.getPendingJobQueue().contains(job2a));
        assertEquals(JobScheduler.PENDING_JOB_REASON_USER, mService.getPendingJobReason(job2a));
        assertFalse(mService.getPendingJobQueue().contains(job2b));
        assertEquals(JobScheduler.PENDING_JOB_REASON_USER, mService.getPendingJobReason(job2b));
    }
}