summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kweku Adams <kwekua@google.com> 2023-03-30 17:16:19 +0000
committer Kweku Adams <kwekua@google.com> 2023-03-30 17:59:51 +0000
commita6843af7302e36fb0b8b2b72207af0a9b23bdb02 (patch)
tree74907f8cee1ce5f7004511005dbeb846e9cca4f0
parent8b84c481cc637478bc0a1e096e42a9b7997cc00a (diff)
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
-rw-r--r--apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java6
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobScheduler.java12
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java37
3 files changed, 40 insertions, 15 deletions
diff --git a/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java b/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
index 776d913e56cb..3cfddc6d8e2b 100644
--- a/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
+++ b/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
@@ -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);
}
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
index b8847add0734..d59d430e0b78 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
@@ -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
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 3fe83a64b5ec..bad4060ca775 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -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);