Loading apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java +5 −1 Original line number Diff line number Diff line Loading @@ -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); } Loading apex/jobscheduler/framework/java/android/app/job/JobScheduler.java +12 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +23 −14 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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 { Loading Loading @@ -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 { Loading Loading @@ -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 { Loading Loading @@ -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); } Loading @@ -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); } Loading @@ -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); } Loading Loading @@ -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); Loading @@ -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); Loading Loading
apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java +5 −1 Original line number Diff line number Diff line Loading @@ -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); } Loading
apex/jobscheduler/framework/java/android/app/job/JobScheduler.java +12 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading
apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +23 −14 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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 { Loading Loading @@ -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 { Loading Loading @@ -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 { Loading Loading @@ -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); } Loading @@ -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); } Loading @@ -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); } Loading Loading @@ -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); Loading @@ -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); Loading