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