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

Commit cf85ce24 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Narrowing the set of Media URI exemptions for jobs"

parents 62612562 057b8da1
Loading
Loading
Loading
Loading
+16 −6
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import android.util.Slog;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;

import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.LocalServices;
import com.android.server.job.GrantedUriPermissions;
@@ -96,6 +97,15 @@ public final class JobStatus {
                    | CONSTRAINT_CONNECTIVITY
                    | CONSTRAINT_IDLE;

    /**
     * Standard media URIs that contain the media files that might be important to the user.
     * @see #mHasMediaBackupExemption
     */
    private static final Uri[] MEDIA_URIS_FOR_STANDBY_EXEMPTION = {
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
    };

    /**
     * The constraints that we want to log to statsd.
     *
@@ -441,13 +451,13 @@ public final class JobStatus {
        if (latestRunTimeElapsedMillis != NO_LATEST_RUNTIME) {
            requiredConstraints |= CONSTRAINT_DEADLINE;
        }
        boolean mediaOnly = false;
        boolean exemptedMediaUrisOnly = false;
        if (job.getTriggerContentUris() != null) {
            requiredConstraints |= CONSTRAINT_CONTENT_TRIGGER;
            mediaOnly = true;
            exemptedMediaUrisOnly = true;
            for (JobInfo.TriggerContentUri uri : job.getTriggerContentUris()) {
                if (!MediaStore.AUTHORITY.equals(uri.getUri().getAuthority())) {
                    mediaOnly = false;
                if (!ArrayUtils.contains(MEDIA_URIS_FOR_STANDBY_EXEMPTION, uri.getUri())) {
                    exemptedMediaUrisOnly = false;
                    break;
                }
            }
@@ -475,8 +485,8 @@ public final class JobStatus {
            job.getRequiredNetwork().networkCapabilities.setSingleUid(this.sourceUid);
        }
        final JobSchedulerInternal jsi = LocalServices.getService(JobSchedulerInternal.class);
        mHasMediaBackupExemption = !job.hasLateConstraint() && mediaOnly && requiresNetwork
                && this.sourcePackageName.equals(jsi.getMediaBackupPackage());
        mHasMediaBackupExemption = !job.hasLateConstraint() && exemptedMediaUrisOnly
                && requiresNetwork && this.sourcePackageName.equals(jsi.getMediaBackupPackage());
    }

    /** Copy constructor: used specifically when cloning JobStatus objects for persistence,
+28 −12
Original line number Diff line number Diff line
@@ -73,7 +73,9 @@ public class JobStatusTest {
    private static final double DELTA = 0.00001;
    private static final String TEST_PACKAGE = "job.test.package";
    private static final ComponentName TEST_JOB_COMPONENT = new ComponentName(TEST_PACKAGE, "test");
    private static final Uri TEST_MEDIA_URI = Uri.parse("content://media/path/to/media");

    private static final Uri IMAGES_MEDIA_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    private static final Uri VIDEO_MEDIA_URI = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;

    @Mock
    private JobSchedulerInternal mJobSchedulerInternal;
@@ -127,7 +129,7 @@ public class JobStatusTest {
    @Test
    public void testMediaBackupExemption_lateConstraint() {
        final JobInfo triggerContentJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
                .addTriggerContentUri(new JobInfo.TriggerContentUri(TEST_MEDIA_URI, 0))
                .addTriggerContentUri(new JobInfo.TriggerContentUri(IMAGES_MEDIA_URI, 0))
                .setOverrideDeadline(12)
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                .build();
@@ -138,7 +140,7 @@ public class JobStatusTest {
    @Test
    public void testMediaBackupExemption_noConnectivityConstraint() {
        final JobInfo triggerContentJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
                .addTriggerContentUri(new JobInfo.TriggerContentUri(TEST_MEDIA_URI, 0))
                .addTriggerContentUri(new JobInfo.TriggerContentUri(IMAGES_MEDIA_URI, 0))
                .build();
        when(mJobSchedulerInternal.getMediaBackupPackage()).thenReturn(TEST_PACKAGE);
        assertEffectiveBucketForMediaExemption(createJobStatus(triggerContentJob), false);
@@ -156,7 +158,7 @@ public class JobStatusTest {
    @Test
    public void testMediaBackupExemption_wrongSourcePackage() {
        final JobInfo networkContentJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
                .addTriggerContentUri(new JobInfo.TriggerContentUri(TEST_MEDIA_URI, 0))
                .addTriggerContentUri(new JobInfo.TriggerContentUri(IMAGES_MEDIA_URI, 0))
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                .build();
        when(mJobSchedulerInternal.getMediaBackupPackage()).thenReturn("not.test.package");
@@ -164,11 +166,12 @@ public class JobStatusTest {
    }

    @Test
    public void testMediaBackupExemption_nonMediaUri() {
        final Uri nonMediaUri = Uri.parse("content://not-media/any/path");
    public void testMediaBackupExemption_nonEligibleUri() {
        final Uri nonEligibleUri = MediaStore.AUTHORITY_URI.buildUpon()
                .appendPath("any_path").build();
        final JobInfo networkContentJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
                .addTriggerContentUri(new JobInfo.TriggerContentUri(TEST_MEDIA_URI, 0))
                .addTriggerContentUri(new JobInfo.TriggerContentUri(nonMediaUri, 0))
                .addTriggerContentUri(new JobInfo.TriggerContentUri(IMAGES_MEDIA_URI, 0))
                .addTriggerContentUri(new JobInfo.TriggerContentUri(nonEligibleUri, 0))
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                .build();
        when(mJobSchedulerInternal.getMediaBackupPackage()).thenReturn(TEST_PACKAGE);
@@ -177,12 +180,25 @@ public class JobStatusTest {

    @Test
    public void testMediaBackupExemptionGranted() {
        final JobInfo networkContentJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
                .addTriggerContentUri(new JobInfo.TriggerContentUri(TEST_MEDIA_URI, 0))
        when(mJobSchedulerInternal.getMediaBackupPackage()).thenReturn(TEST_PACKAGE);
        final JobInfo imageUriJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
                .addTriggerContentUri(new JobInfo.TriggerContentUri(IMAGES_MEDIA_URI, 0))
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                .build();
        when(mJobSchedulerInternal.getMediaBackupPackage()).thenReturn(TEST_PACKAGE);
        assertEffectiveBucketForMediaExemption(createJobStatus(networkContentJob), true);
        assertEffectiveBucketForMediaExemption(createJobStatus(imageUriJob), true);

        final JobInfo videoUriJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
                .addTriggerContentUri(new JobInfo.TriggerContentUri(VIDEO_MEDIA_URI, 0))
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                .build();
        assertEffectiveBucketForMediaExemption(createJobStatus(videoUriJob), true);

        final JobInfo bothUriJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
                .addTriggerContentUri(new JobInfo.TriggerContentUri(IMAGES_MEDIA_URI, 0))
                .addTriggerContentUri(new JobInfo.TriggerContentUri(VIDEO_MEDIA_URI, 0))
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                .build();
        assertEffectiveBucketForMediaExemption(createJobStatus(bothUriJob), true);
    }

    @Test