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
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user