• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package android.app.job;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.IntDef;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.RequiresPermission;
24 import android.annotation.SystemApi;
25 import android.annotation.SystemService;
26 import android.annotation.UserIdInt;
27 import android.app.ActivityManager;
28 import android.app.usage.UsageStatsManager;
29 import android.compat.annotation.ChangeId;
30 import android.compat.annotation.EnabledAfter;
31 import android.content.ClipData;
32 import android.content.Context;
33 import android.content.pm.PackageManager;
34 import android.net.NetworkRequest;
35 import android.os.Build;
36 import android.os.Bundle;
37 import android.os.PersistableBundle;
38 
39 import java.lang.annotation.Retention;
40 import java.lang.annotation.RetentionPolicy;
41 import java.util.List;
42 import java.util.Map;
43 
44 /**
45  * This is an API for scheduling various types of jobs against the framework that will be executed
46  * in your application's own process.
47  * <p>
48  * See {@link android.app.job.JobInfo} for more description of the types of jobs that can be run
49  * and how to construct them. You will construct these JobInfo objects and pass them to the
50  * JobScheduler with {@link #schedule(JobInfo)}. When the criteria declared are met, the
51  * system will execute this job on your application's {@link android.app.job.JobService}.
52  * You identify the service component that implements the logic for your job when you
53  * construct the JobInfo using
54  * {@link android.app.job.JobInfo.Builder#Builder(int,android.content.ComponentName)}.
55  * </p>
56  * <p>
57  * The framework will be intelligent about when it executes jobs, and attempt to batch
58  * and defer them as much as possible. Typically, if you don't specify a deadline on a job, it
59  * can be run at any moment depending on the current state of the JobScheduler's internal queue.
60  * </p>
61  * <p>
62  * Starting in Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
63  * JobScheduler may try to optimize job execution by shifting execution to times with more available
64  * system resources in order to lower user impact. Factors in system health include sufficient
65  * battery, idle, charging, and access to an un-metered network. Jobs will initially be treated as
66  * if they have all these requirements, but as their deadlines approach, restrictions will become
67  * less strict. Requested requirements will not be affected by this change.
68  * </p>
69  *
70  * {@see android.app.job.JobInfo.Builder#setRequiresBatteryNotLow(boolean)}
71  * {@see android.app.job.JobInfo.Builder#setRequiresDeviceIdle(boolean)}
72  * {@see android.app.job.JobInfo.Builder#setRequiresCharging(boolean)}
73  * {@see android.app.job.JobInfo.Builder#setRequiredNetworkType(int)}
74  *
75  * <p>
76  * While a job is running, the system holds a wakelock on behalf of your app.  For this reason,
77  * you do not need to take any action to guarantee that the device stays awake for the
78  * duration of the job.
79  * </p>
80  * <p>You do not
81  * instantiate this class directly; instead, retrieve it through
82  * {@link android.content.Context#getSystemService
83  * Context.getSystemService(Context.JOB_SCHEDULER_SERVICE)}.
84  *
85  * <p> Prior to Android version {@link android.os.Build.VERSION_CODES#S}, jobs could only have
86  * a maximum of 100 jobs scheduled at a time. Starting with Android version
87  * {@link android.os.Build.VERSION_CODES#S}, that limit has been increased to 150.
88  * Expedited jobs also count towards the limit.
89  *
90  * <p> In Android version {@link android.os.Build.VERSION_CODES#LOLLIPOP}, jobs had a maximum
91  * execution time of one minute. Starting with Android version
92  * {@link android.os.Build.VERSION_CODES#M} and ending with Android version
93  * {@link android.os.Build.VERSION_CODES#R}, jobs had a maximum execution time of 10 minutes.
94  * Starting from Android version {@link android.os.Build.VERSION_CODES#S}, jobs will still be
95  * stopped after 10 minutes if the system is busy or needs the resources, but if not, jobs
96  * may continue running longer than 10 minutes.
97  *
98  * <p class="caution"><strong>Note:</strong> Beginning with API 30
99  * ({@link android.os.Build.VERSION_CODES#R}), JobScheduler will throttle runaway applications.
100  * Calling {@link #schedule(JobInfo)} and other such methods with very high frequency can have a
101  * high cost and so, to make sure the system doesn't get overwhelmed, JobScheduler will begin
102  * to throttle apps, regardless of target SDK version.
103  */
104 @SystemService(Context.JOB_SCHEDULER_SERVICE)
105 public abstract class JobScheduler {
106     /**
107      * Whether to throw an exception when an app doesn't properly implement all the necessary
108      * data transfer APIs.
109      *
110      * @hide
111      */
112     @ChangeId
113     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
114     public static final long THROW_ON_INVALID_DATA_TRANSFER_IMPLEMENTATION = 255371817L;
115 
116     /** @hide */
117     @IntDef(prefix = { "RESULT_" }, value = {
118             RESULT_FAILURE,
119             RESULT_SUCCESS,
120     })
121     @Retention(RetentionPolicy.SOURCE)
122     public @interface Result {}
123 
124     /**
125      * Returned from {@link #schedule(JobInfo)} if a job wasn't scheduled successfully. Scheduling
126      * can fail for a variety of reasons, including, but not limited to:
127      * <ul>
128      * <li>an invalid parameter was supplied (eg. the run-time for your job is too short, or the
129      * system can't resolve the requisite {@link JobService} in your package)</li>
130      * <li>the app has too many jobs scheduled</li>
131      * <li>the app has tried to schedule too many jobs in a short amount of time</li>
132      * </ul>
133      * Attempting to schedule the job again immediately after receiving this result will not
134      * guarantee a successful schedule.
135      */
136     public static final int RESULT_FAILURE = 0;
137     /**
138      * Returned from {@link #schedule(JobInfo)} if this job has been successfully scheduled.
139      */
140     public static final int RESULT_SUCCESS = 1;
141 
142     /** The job doesn't exist. */
143     public static final int PENDING_JOB_REASON_INVALID_JOB_ID = -2;
144     /** The job is currently running and is therefore not pending. */
145     public static final int PENDING_JOB_REASON_EXECUTING = -1;
146     /**
147      * There is no known reason why the job is pending.
148      * If additional reasons are added on newer Android versions, the system may return this reason
149      * to apps whose target SDK is not high enough to expect that reason.
150      */
151     public static final int PENDING_JOB_REASON_UNDEFINED = 0;
152     /**
153      * The app is in a state that prevents the job from running
154      * (eg. the {@link JobService} component is disabled).
155      */
156     public static final int PENDING_JOB_REASON_APP = 1;
157     /**
158      * The current standby bucket prevents the job from running.
159      *
160      * @see UsageStatsManager#STANDBY_BUCKET_RESTRICTED
161      */
162     public static final int PENDING_JOB_REASON_APP_STANDBY = 2;
163     /**
164      * The app is restricted from running in the background.
165      *
166      * @see ActivityManager#isBackgroundRestricted()
167      * @see PackageManager#isInstantApp()
168      */
169     public static final int PENDING_JOB_REASON_BACKGROUND_RESTRICTION = 3;
170     /**
171      * The requested battery-not-low constraint is not satisfied.
172      *
173      * @see JobInfo.Builder#setRequiresBatteryNotLow(boolean)
174      */
175     public static final int PENDING_JOB_REASON_CONSTRAINT_BATTERY_NOT_LOW = 4;
176     /**
177      * The requested charging constraint is not satisfied.
178      *
179      * @see JobInfo.Builder#setRequiresCharging(boolean)
180      */
181     public static final int PENDING_JOB_REASON_CONSTRAINT_CHARGING = 5;
182     /**
183      * The requested connectivity constraint is not satisfied.
184      *
185      * @see JobInfo.Builder#setRequiredNetwork(NetworkRequest)
186      * @see JobInfo.Builder#setRequiredNetworkType(int)
187      */
188     public static final int PENDING_JOB_REASON_CONSTRAINT_CONNECTIVITY = 6;
189     /**
190      * The requested content trigger constraint is not satisfied.
191      *
192      * @see JobInfo.Builder#addTriggerContentUri(JobInfo.TriggerContentUri)
193      */
194     public static final int PENDING_JOB_REASON_CONSTRAINT_CONTENT_TRIGGER = 7;
195     /**
196      * The requested idle constraint is not satisfied.
197      *
198      * @see JobInfo.Builder#setRequiresDeviceIdle(boolean)
199      */
200     public static final int PENDING_JOB_REASON_CONSTRAINT_DEVICE_IDLE = 8;
201     /**
202      * The minimum latency has not transpired.
203      *
204      * @see JobInfo.Builder#setMinimumLatency(long)
205      */
206     public static final int PENDING_JOB_REASON_CONSTRAINT_MINIMUM_LATENCY = 9;
207     /**
208      * The system's estimate of when the app will be launched is far away enough to warrant delaying
209      * this job.
210      *
211      * @see JobInfo#isPrefetch()
212      * @see JobInfo.Builder#setPrefetch(boolean)
213      */
214     public static final int PENDING_JOB_REASON_CONSTRAINT_PREFETCH = 10;
215     /**
216      * The requested storage-not-low constraint is not satisfied.
217      *
218      * @see JobInfo.Builder#setRequiresStorageNotLow(boolean)
219      */
220     public static final int PENDING_JOB_REASON_CONSTRAINT_STORAGE_NOT_LOW = 11;
221     /**
222      * The job is being deferred due to the device state (eg. Doze, battery saver, memory usage,
223      * thermal status, etc.).
224      */
225     public static final int PENDING_JOB_REASON_DEVICE_STATE = 12;
226     /**
227      * JobScheduler thinks it can defer this job to a more optimal running time.
228      */
229     public static final int PENDING_JOB_REASON_JOB_SCHEDULER_OPTIMIZATION = 13;
230     /**
231      * The app has consumed all of its current quota.
232      *
233      * @see UsageStatsManager#getAppStandbyBucket()
234      * @see JobParameters#STOP_REASON_QUOTA
235      */
236     public static final int PENDING_JOB_REASON_QUOTA = 14;
237     /**
238      * JobScheduler is respecting one of the user's actions (eg. force stop or adb shell commands)
239      * to defer this job.
240      */
241     public static final int PENDING_JOB_REASON_USER = 15;
242     /**
243      * The override deadline has not transpired.
244      *
245      * @see JobInfo.Builder#setOverrideDeadline(long)
246      */
247     @FlaggedApi(Flags.FLAG_GET_PENDING_JOB_REASONS_API)
248     public static final int PENDING_JOB_REASON_CONSTRAINT_DEADLINE = 16;
249 
250     /** @hide */
251     @IntDef(prefix = {"PENDING_JOB_REASON_"}, value = {
252             PENDING_JOB_REASON_UNDEFINED,
253             PENDING_JOB_REASON_APP,
254             PENDING_JOB_REASON_APP_STANDBY,
255             PENDING_JOB_REASON_BACKGROUND_RESTRICTION,
256             PENDING_JOB_REASON_CONSTRAINT_BATTERY_NOT_LOW,
257             PENDING_JOB_REASON_CONSTRAINT_CHARGING,
258             PENDING_JOB_REASON_CONSTRAINT_CONNECTIVITY,
259             PENDING_JOB_REASON_CONSTRAINT_CONTENT_TRIGGER,
260             PENDING_JOB_REASON_CONSTRAINT_DEVICE_IDLE,
261             PENDING_JOB_REASON_CONSTRAINT_MINIMUM_LATENCY,
262             PENDING_JOB_REASON_CONSTRAINT_PREFETCH,
263             PENDING_JOB_REASON_CONSTRAINT_STORAGE_NOT_LOW,
264             PENDING_JOB_REASON_DEVICE_STATE,
265             PENDING_JOB_REASON_EXECUTING,
266             PENDING_JOB_REASON_INVALID_JOB_ID,
267             PENDING_JOB_REASON_JOB_SCHEDULER_OPTIMIZATION,
268             PENDING_JOB_REASON_QUOTA,
269             PENDING_JOB_REASON_USER,
270             PENDING_JOB_REASON_CONSTRAINT_DEADLINE,
271     })
272     @Retention(RetentionPolicy.SOURCE)
273     public @interface PendingJobReason {
274     }
275 
276     /**
277      * Get a JobScheduler instance that is dedicated to a specific namespace. Any API calls using
278      * this instance will interact with jobs in that namespace, unless the API documentation says
279      * otherwise. Attempting to update a job scheduled in another namespace will not be possible
280      * but will instead create or update the job inside the current namespace. A JobScheduler
281      * instance dedicated to a namespace must be used to schedule or update jobs in that namespace.
282      *
283      * <p class="note">Since leading and trailing whitespace can lead to hard-to-debug issues,
284      * they will be {@link String#trim() trimmed}. An empty String (after trimming) is not allowed.
285      * @see #getNamespace()
286      */
287     @NonNull
forNamespace(@onNull String namespace)288     public JobScheduler forNamespace(@NonNull String namespace) {
289         throw new RuntimeException("Not implemented. Must override in a subclass.");
290     }
291 
292     /**
293      * Get the namespace this JobScheduler instance is operating in. A {@code null} value means
294      * that the app has not specified a namespace for this instance, and it is therefore using the
295      * default namespace.
296      */
297     @Nullable
getNamespace()298     public String getNamespace() {
299         throw new RuntimeException("Not implemented. Must override in a subclass.");
300     }
301 
302     /** @hide */
303     @Nullable
sanitizeNamespace(@ullable String namespace)304     public static String sanitizeNamespace(@Nullable String namespace) {
305         if (namespace == null) {
306             return null;
307         }
308         return namespace.trim().intern();
309     }
310 
311     /**
312      * Schedule a job to be executed.  Will replace any currently scheduled job with the same
313      * ID with the new information in the {@link JobInfo}.  If a job with the given ID is currently
314      * running, it will be stopped.
315      *
316      * <p class="caution"><strong>Note:</strong> Scheduling a job can have a high cost, even if it's
317      * rescheduling the same job and the job didn't execute, especially on platform versions before
318      * version {@link android.os.Build.VERSION_CODES#Q}. As such, the system may throttle calls to
319      * this API if calls are made too frequently in a short amount of time.
320      *
321      * <p>Note: The JobService component needs to be enabled in order to successfully schedule a
322      * job.
323      *
324      * @param job The job you wish scheduled. See
325      * {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs
326      * you can schedule.
327      * @return the result of the schedule request.
328      * @throws IllegalArgumentException if the specified {@link JobService} doesn't exist or is
329      * disabled.
330      */
schedule(@onNull JobInfo job)331     public abstract @Result int schedule(@NonNull JobInfo job);
332 
333     /**
334      * Similar to {@link #schedule}, but allows you to enqueue work for a new <em>or existing</em>
335      * job.  If a job with the same ID is already scheduled, it will be replaced with the
336      * new {@link JobInfo}, but any previously enqueued work will remain and be dispatched the
337      * next time it runs.  If a job with the same ID is already running, the new work will be
338      * enqueued for it without stopping the job.
339      *
340      * <p>The work you enqueue is later retrieved through
341      * {@link JobParameters#dequeueWork() JobParameters.dequeueWork}.  Be sure to see there
342      * about how to process work; the act of enqueueing work changes how you should handle the
343      * overall lifecycle of an executing job.</p>
344      *
345      * <p>It is strongly encouraged that you use the same {@link JobInfo} for all work you
346      * enqueue.  This will allow the system to optimally schedule work along with any pending
347      * and/or currently running work.  If the JobInfo changes from the last time the job was
348      * enqueued, the system will need to update the associated JobInfo, which can cause a disruption
349      * in execution.  In particular, this can result in any currently running job that is processing
350      * previous work to be stopped and restarted with the new JobInfo.</p>
351      *
352      * <p>It is recommended that you avoid using
353      * {@link JobInfo.Builder#setExtras(PersistableBundle)} or
354      * {@link JobInfo.Builder#setTransientExtras(Bundle)} with a JobInfo you are using to
355      * enqueue work.  The system will try to compare these extras with the previous JobInfo,
356      * but there are situations where it may get this wrong and count the JobInfo as changing.
357      * (That said, you should be relatively safe with a simple set of consistent data in these
358      * fields.)  You should never use {@link JobInfo.Builder#setClipData(ClipData, int)} with
359      * work you are enqueuing, since currently this will always be treated as a different JobInfo,
360      * even if the ClipData contents are exactly the same.</p>
361      *
362      * <p class="caution"><strong>Note:</strong> Scheduling a job can have a high cost, even if it's
363      * rescheduling the same job and the job didn't execute, especially on platform versions before
364      * version {@link android.os.Build.VERSION_CODES#Q}. As such, the system may throttle calls to
365      * this API if calls are made too frequently in a short amount of time.
366      *
367      * <p class="caution"><strong>Note:</strong> Prior to Android version
368      * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, JobWorkItems could not be persisted.
369      * Apps were not allowed to enqueue JobWorkItems with persisted jobs and the system would throw
370      * an {@link IllegalArgumentException} if they attempted to do so. Starting with
371      * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
372      * JobWorkItems can be persisted alongside the hosting job.
373      * However, Intents cannot be persisted. Set a {@link PersistableBundle} using
374      * {@link JobWorkItem.Builder#setExtras(PersistableBundle)} for any information that needs
375      * to be persisted.
376      *
377      * <p>Note: The JobService component needs to be enabled in order to successfully schedule a
378      * job.
379      *
380      * @param job The job you wish to enqueue work for. See
381      * {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs
382      * you can schedule.
383      * @param work New work to enqueue.  This will be available later when the job starts running.
384      * @return the result of the enqueue request.
385      * @throws IllegalArgumentException if the specified {@link JobService} doesn't exist or is
386      * disabled.
387      */
enqueue(@onNull JobInfo job, @NonNull JobWorkItem work)388     public abstract @Result int enqueue(@NonNull JobInfo job, @NonNull JobWorkItem work);
389 
390     /**
391      *
392      * @param job The job to be scheduled.
393      * @param packageName The package on behalf of which the job is to be scheduled. This will be
394      *                    used to track battery usage and appIdleState.
395      * @param userId    User on behalf of whom this job is to be scheduled.
396      * @param tag Debugging tag for dumps associated with this job (instead of the service class)
397      * @hide
398      */
399     @SuppressWarnings("HiddenAbstractMethod")
400     @SystemApi
401     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
scheduleAsPackage(@onNull JobInfo job, @NonNull String packageName, int userId, String tag)402     public abstract @Result int scheduleAsPackage(@NonNull JobInfo job, @NonNull String packageName,
403             int userId, String tag);
404 
405     /**
406      * Cancel the specified job.  If the job is currently executing, it is stopped
407      * immediately and the return value from its {@link JobService#onStopJob(JobParameters)}
408      * method is ignored.
409      *
410      * @param jobId unique identifier for the job to be canceled, as supplied to
411      *     {@link JobInfo.Builder#Builder(int, android.content.ComponentName)
412      *     JobInfo.Builder(int, android.content.ComponentName)}.
413      */
cancel(int jobId)414     public abstract void cancel(int jobId);
415 
416     /**
417      * Cancel all jobs that have been scheduled in the current namespace by the
418      * calling application.
419      *
420      * <p>
421      * Starting with Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, this
422      * will only cancel within the current namespace. If a namespace hasn't been explicitly set
423      * with {@link #forNamespace(String)}, then this will cancel jobs in the default namespace.
424      * To cancel all jobs scheduled by the application,
425      * use {@link #cancelInAllNamespaces()} instead.
426      */
cancelAll()427     public abstract void cancelAll();
428 
429     /**
430      * Cancel <em>all</em> jobs that have been scheduled by the calling application, regardless of
431      * namespace.
432      */
cancelInAllNamespaces()433     public void cancelInAllNamespaces() {
434         throw new RuntimeException("Not implemented. Must override in a subclass.");
435     }
436 
437     /**
438      * Retrieve all jobs that have been scheduled by the calling application.
439      *
440      * @return a list of all of the app's scheduled jobs.  This includes jobs that are
441      *     currently started as well as those that are still waiting to run.
442      */
getAllPendingJobs()443     public abstract @NonNull List<JobInfo> getAllPendingJobs();
444 
445     /**
446      * Retrieve all jobs that have been scheduled by the calling application within the current
447      * namespace.
448      *
449      * @return a list of all of the app's scheduled jobs scheduled with the current namespace.
450      * If a namespace hasn't been explicitly set with {@link #forNamespace(String)},
451      * then this will return jobs in the default namespace.
452      * This includes jobs that are currently started as well as those that are still waiting to run.
453      */
454     @NonNull
getPendingJobsInAllNamespaces()455     public Map<String, List<JobInfo>> getPendingJobsInAllNamespaces() {
456         throw new RuntimeException("Not implemented. Must override in a subclass.");
457     }
458 
459     /**
460      * Look up the description of a scheduled job.
461      *
462      * @return The {@link JobInfo} description of the given scheduled job, or {@code null}
463      *     if the supplied job ID does not correspond to any job.
464      */
getPendingJob(int jobId)465     public abstract @Nullable JobInfo getPendingJob(int jobId);
466 
467     /**
468      * Returns a reason why the job is pending and not currently executing. If there are multiple
469      * reasons why a job may be pending, this will only return one of them.
470      *
471      * @apiNote
472      * To know all the potential reasons why the job may be pending,
473      * use {@link #getPendingJobReasons(int)} instead.
474      */
475     @PendingJobReason
getPendingJobReason(int jobId)476     public int getPendingJobReason(int jobId) {
477         return PENDING_JOB_REASON_UNDEFINED;
478     }
479 
480     /**
481      * Returns potential reasons why the job with the given {@code jobId} may be pending
482      * and not currently executing.
483      *
484      * The returned array will include {@link PendingJobReason reasons} composed of both
485      * explicitly set constraints on the job and implicit constraints imposed by the system.
486      * The results can be used to debug why a given job may not be currently executing.
487      */
488     @FlaggedApi(Flags.FLAG_GET_PENDING_JOB_REASONS_API)
489     @NonNull
490     @PendingJobReason
getPendingJobReasons(int jobId)491     public int[] getPendingJobReasons(int jobId) {
492         return new int[] { PENDING_JOB_REASON_UNDEFINED };
493     }
494 
495     /**
496      * For the given {@code jobId}, returns a limited historical view of why the job may have
497      * been pending execution. The returned list is composed of {@link PendingJobReasonsInfo}
498      * objects, each of which include a timestamp since epoch along with an array of
499      * unsatisfied constraints represented by {@link PendingJobReason PendingJobReason constants}.
500      * <p>
501      * These constants could either be explicitly set constraints on the job or implicit
502      * constraints imposed by the system due to various reasons.
503      * The results can be used to debug why a given job may have been pending execution.
504      * <p>
505      * If the only {@link PendingJobReason} for the timestamp is
506      * {@link PendingJobReason#PENDING_JOB_REASON_UNDEFINED}, it could mean that
507      * the job was ready to be executed at that point in time.
508      * <p>
509      * Note: there is no set interval for the timestamps in the returned list since
510      * constraint changes occur based on device status and various other factors.
511      * <p>
512      * Note: the pending job reasons history is not persisted across device reboots.
513      * <p>
514      * @throws IllegalArgumentException if the {@code jobId} is invalid.
515      * @see #getPendingJobReasons(int)
516      */
517     @FlaggedApi(Flags.FLAG_GET_PENDING_JOB_REASONS_HISTORY_API)
518     @NonNull
getPendingJobReasonsHistory(int jobId)519     public List<PendingJobReasonsInfo> getPendingJobReasonsHistory(int jobId) {
520         throw new UnsupportedOperationException("Not implemented by " + getClass());
521     }
522 
523     /**
524      * Returns {@code true} if the calling app currently holds the
525      * {@link android.Manifest.permission#RUN_USER_INITIATED_JOBS} permission, allowing it to run
526      * user-initiated jobs.
527      */
canRunUserInitiatedJobs()528     public boolean canRunUserInitiatedJobs() {
529         return false;
530     }
531 
532     /**
533      * Returns {@code true} if the app currently holds the
534      * {@link android.Manifest.permission#RUN_USER_INITIATED_JOBS} permission, allowing it to run
535      * user-initiated jobs.
536      * @hide
537      * TODO(255371817): consider exposing this to apps who could call
538      * {@link #scheduleAsPackage(JobInfo, String, int, String)}
539      */
hasRunUserInitiatedJobsPermission(@onNull String packageName, @UserIdInt int userId)540     public boolean hasRunUserInitiatedJobsPermission(@NonNull String packageName,
541             @UserIdInt int userId) {
542         return false;
543     }
544 
545     /**
546      * <b>For internal system callers only!</b>
547      * Returns a list of all currently-executing jobs.
548      * @hide
549      */
550     @Nullable
getStartedJobs()551     public List<JobInfo> getStartedJobs() {
552         return null;
553     }
554 
555     /**
556      * <b>For internal system callers only!</b>
557      * Returns a snapshot of the state of all jobs known to the system.
558      *
559      * <p class="note">This is a slow operation, so it should be called sparingly.
560      * @hide
561      */
562     @Nullable
getAllJobSnapshots()563     public List<JobSnapshot> getAllJobSnapshots() {
564         return null;
565     }
566 
567     /**
568      * @hide
569      */
570     @RequiresPermission(allOf = {
571             android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
572             android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
registerUserVisibleJobObserver(@onNull IUserVisibleJobObserver observer)573     public void registerUserVisibleJobObserver(@NonNull IUserVisibleJobObserver observer) {
574     }
575 
576     /**
577      * @hide
578      */
579     @RequiresPermission(allOf = {
580             android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
581             android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
unregisterUserVisibleJobObserver( @onNull IUserVisibleJobObserver observer)582     public void unregisterUserVisibleJobObserver(
583             @NonNull IUserVisibleJobObserver observer) {
584 
585     }
586 
587     /**
588      * @hide
589      */
590     @RequiresPermission(allOf = {
591             android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
592             android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
notePendingUserRequestedAppStop(@onNull String packageName, int userId, @Nullable String debugReason)593     public void notePendingUserRequestedAppStop(@NonNull String packageName, int userId,
594             @Nullable String debugReason) {
595     }
596 }
597