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