Don't allow empty namespaces.
An empty namespace (""), or a string made up of only whitespace,
isn't very descriptive and may cause issues with debugging in the
future. This blocks clients from using such namespaces in the first
place.
Bug: 276313158
Test: atest CtsJobSchedulerTestCases:JobSchedulingTest
Change-Id: I2b8da58fc1836b8547270b2c6f39fe44fd34f936
This commit is contained in:
@@ -65,8 +65,12 @@ public class JobSchedulerImpl extends JobScheduler {
|
||||
@NonNull
|
||||
@Override
|
||||
public JobScheduler forNamespace(@NonNull String namespace) {
|
||||
namespace = sanitizeNamespace(namespace);
|
||||
if (namespace == null) {
|
||||
throw new IllegalArgumentException("namespace cannot be null");
|
||||
throw new NullPointerException("namespace cannot be null");
|
||||
}
|
||||
if (namespace.isEmpty()) {
|
||||
throw new IllegalArgumentException("namespace cannot be empty");
|
||||
}
|
||||
return new JobSchedulerImpl(this, namespace);
|
||||
}
|
||||
|
||||
@@ -270,6 +270,9 @@ public abstract class JobScheduler {
|
||||
* otherwise. Attempting to update a job scheduled in another namespace will not be possible
|
||||
* but will instead create or update the job inside the current namespace. A JobScheduler
|
||||
* instance dedicated to a namespace must be used to schedule or update jobs in that namespace.
|
||||
*
|
||||
* <p class="note">Since leading and trailing whitespace can lead to hard-to-debug issues,
|
||||
* they will be {@link String#trim() trimmed}. An empty String (after trimming) is not allowed.
|
||||
* @see #getNamespace()
|
||||
*/
|
||||
@NonNull
|
||||
@@ -287,6 +290,15 @@ public abstract class JobScheduler {
|
||||
throw new RuntimeException("Not implemented. Must override in a subclass.");
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Nullable
|
||||
public static String sanitizeNamespace(@Nullable String namespace) {
|
||||
if (namespace == null) {
|
||||
return null;
|
||||
}
|
||||
return namespace.trim().intern();
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule a job to be executed. Will replace any currently scheduled job with the same
|
||||
* ID with the new information in the {@link JobInfo}. If a job with the given ID is currently
|
||||
|
||||
@@ -4024,6 +4024,18 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
return JobScheduler.RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
/** Returns a sanitized namespace if valid, or throws an exception if not. */
|
||||
private String validateNamespace(@Nullable String namespace) {
|
||||
namespace = JobScheduler.sanitizeNamespace(namespace);
|
||||
if (namespace != null) {
|
||||
if (namespace.isEmpty()) {
|
||||
throw new IllegalArgumentException("namespace cannot be empty");
|
||||
}
|
||||
namespace = namespace.intern();
|
||||
}
|
||||
return namespace;
|
||||
}
|
||||
|
||||
private int validateRunUserInitiatedJobsPermission(int uid, String packageName) {
|
||||
final int state = getRunUserInitiatedJobsPermissionState(uid, packageName);
|
||||
if (state == PermissionChecker.PERMISSION_HARD_DENIED) {
|
||||
@@ -4071,9 +4083,7 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
return result;
|
||||
}
|
||||
|
||||
if (namespace != null) {
|
||||
namespace = namespace.intern();
|
||||
}
|
||||
namespace = validateNamespace(namespace);
|
||||
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -4104,9 +4114,7 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
return result;
|
||||
}
|
||||
|
||||
if (namespace != null) {
|
||||
namespace = namespace.intern();
|
||||
}
|
||||
namespace = validateNamespace(namespace);
|
||||
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -4145,9 +4153,7 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
return result;
|
||||
}
|
||||
|
||||
if (namespace != null) {
|
||||
namespace = namespace.intern();
|
||||
}
|
||||
namespace = validateNamespace(namespace);
|
||||
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -4184,7 +4190,8 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return new ParceledListSlice<>(
|
||||
JobSchedulerService.this.getPendingJobsInNamespace(uid, namespace));
|
||||
JobSchedulerService.this.getPendingJobsInNamespace(uid,
|
||||
validateNamespace(namespace)));
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
@@ -4196,7 +4203,8 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return JobSchedulerService.this.getPendingJob(uid, namespace, jobId);
|
||||
return JobSchedulerService.this.getPendingJob(
|
||||
uid, validateNamespace(namespace), jobId);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
@@ -4208,7 +4216,8 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return JobSchedulerService.this.getPendingJobReason(uid, namespace, jobId);
|
||||
return JobSchedulerService.this.getPendingJobReason(
|
||||
uid, validateNamespace(namespace), jobId);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
@@ -4238,7 +4247,7 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
JobSchedulerService.this.cancelJobsForUid(uid,
|
||||
// Documentation says only jobs scheduled BY the app will be cancelled
|
||||
/* includeSourceApp */ false,
|
||||
/* namespaceOnly */ true, namespace,
|
||||
/* namespaceOnly */ true, validateNamespace(namespace),
|
||||
JobParameters.STOP_REASON_CANCELLED_BY_APP,
|
||||
JobParameters.INTERNAL_STOP_REASON_CANCELED,
|
||||
"cancelAllInNamespace() called by app, callingUid=" + uid);
|
||||
@@ -4253,7 +4262,7 @@ public class JobSchedulerService extends com.android.server.SystemService
|
||||
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
JobSchedulerService.this.cancelJob(uid, namespace, jobId, uid,
|
||||
JobSchedulerService.this.cancelJob(uid, validateNamespace(namespace), jobId, uid,
|
||||
JobParameters.STOP_REASON_CANCELLED_BY_APP);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
|
||||
Reference in New Issue
Block a user