From 057b8da1a1cce50c7ace76745772ee96bad16c66 Mon Sep 17 00:00:00 2001 From: Suprabh Shukla Date: Wed, 19 Feb 2020 17:15:14 -0800 Subject: [PATCH] Narrowing the set of Media URI exemptions for jobs Only jobs watching for changes to EXTERNAL_CONTENT_URI for Images and Vidoes will get exemption for jobs. MediaScanner will scan and insert an entry under each of these URIs for respective file types. Test: atest com.android.server.job.controllers.JobStatusTest Bug: 148887841 Change-Id: I6f9a07d2c0f06c002929056891187f22a6e87e21 --- .../server/job/controllers/JobStatus.java | 22 +++++++--- .../server/job/controllers/JobStatusTest.java | 40 +++++++++++++------ 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java index cf7f3804b34df..c780ce8f943b2 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java @@ -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, diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java index d7a3cfd8aeca3..1bf9c2a0822eb 100644 --- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java @@ -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