diff --git a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java index 60f64757f65ab..e1bfde15fa0a9 100644 --- a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java +++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java @@ -64,6 +64,16 @@ public class JobParameters implements Parcelable { */ public static final int REASON_RESTRICTED_BUCKET = JobProtoEnums.STOP_REASON_RESTRICTED_BUCKET; // 6. + /** + * The app was uninstalled. + * @hide + */ + public static final int DEBUG_REASON_UNINSTALL = 7; + /** + * The app's data was cleared. + * @hide + */ + public static final int DEBUG_REASON_DATA_CLEARED = 8; /** * All the stop reason codes. This should be regarded as an immutable array at runtime. @@ -187,8 +197,8 @@ public class JobParameters implements Parcelable { */ public static final int STOP_REASON_APP_STANDBY = 12; /** - * The user stopped the job. This can happen either through force-stop, or via adb shell - * commands. + * The user stopped the job. This can happen either through force-stop, adb shell commands, + * or uninstalling. */ public static final int STOP_REASON_USER = 13; /** The system is doing some processing that requires stopping this job. */ diff --git a/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java b/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java index 6ae91a0917a41..6d2bd47f60bd8 100644 --- a/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java +++ b/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java @@ -37,7 +37,8 @@ public interface JobSchedulerInternal { /** * Cancel the jobs for a given uid (e.g. when app data is cleared) */ - void cancelJobsForUid(int uid, @JobParameters.StopReason int reason, String debugReason); + void cancelJobsForUid(int uid, @JobParameters.StopReason int reason, int debugReasonCode, + String debugReason); /** * These are for activity manager to communicate to use what is currently performing backups. 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 41b342cc258cb..8b9eca6f31dc5 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -747,12 +747,14 @@ public class JobSchedulerService extends com.android.server.SystemService + " in user " + userId); } synchronized (mLock) { - // By the time we get here, the process should have - // already been stopped, so the app wouldn't get the - // stop reason, so just put USER instead of UNINSTALL - // or DISABLED. + // There's no guarantee that the process has been + // stopped by the time we get here, but since this is + // a user-initiated action, it should be fine to just + // put USER instead of UNINSTALL or DISABLED. cancelJobsForPackageAndUidLocked(pkgName, pkgUid, - JobParameters.STOP_REASON_USER, "app disabled"); + JobParameters.STOP_REASON_USER, + JobParameters.DEBUG_REASON_UNINSTALL, + "app disabled"); } } } catch (RemoteException|IllegalArgumentException e) { @@ -783,25 +785,22 @@ public class JobSchedulerService extends com.android.server.SystemService } else { Slog.w(TAG, "PACKAGE_CHANGED for " + pkgName + " / uid " + pkgUid); } - } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) { - // If this is an outright uninstall rather than the first half of an - // app update sequence, cancel the jobs associated with the app. - if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { - int uidRemoved = intent.getIntExtra(Intent.EXTRA_UID, -1); - if (DEBUG) { - Slog.d(TAG, "Removing jobs for uid: " + uidRemoved); - } - // By the time we get here, the process should have already - // been stopped, so the app wouldn't get the stop reason, - // so just put USER instead of UNINSTALL or DISABLED. - synchronized (mLock) { - cancelJobsForPackageAndUidLocked(pkgName, uidRemoved, - JobParameters.STOP_REASON_USER, "app uninstalled"); - for (int c = 0; c < mControllers.size(); ++c) { - mControllers.get(c).onAppRemovedLocked(pkgName, pkgUid); - } - mDebuggableApps.remove(pkgName); + } else if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action)) { + int uidRemoved = intent.getIntExtra(Intent.EXTRA_UID, -1); + if (DEBUG) { + Slog.d(TAG, "Removing jobs for uid: " + uidRemoved); + } + synchronized (mLock) { + // There's no guarantee that the process has been stopped by the time we + // get here, but since this is generally a user-initiated action, it should + // be fine to just put USER instead of UNINSTALL or DISABLED. + cancelJobsForPackageAndUidLocked(pkgName, uidRemoved, + JobParameters.STOP_REASON_USER, + JobParameters.DEBUG_REASON_UNINSTALL, "app uninstalled"); + for (int c = 0; c < mControllers.size(); ++c) { + mControllers.get(c).onAppRemovedLocked(pkgName, pkgUid); } + mDebuggableApps.remove(pkgName); } } else if (Intent.ACTION_USER_ADDED.equals(action)) { final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); @@ -849,7 +848,8 @@ public class JobSchedulerService extends com.android.server.SystemService } synchronized (mLock) { cancelJobsForPackageAndUidLocked(pkgName, pkgUid, - JobParameters.STOP_REASON_USER, "app force stopped"); + JobParameters.STOP_REASON_USER, JobParameters.REASON_CANCELED, + "app force stopped"); } } } @@ -1038,7 +1038,7 @@ public class JobSchedulerService extends com.android.server.SystemService if (toCancel != null) { // Implicitly replaces the existing job record with the new instance cancelJobImplLocked(toCancel, jobStatus, JobParameters.STOP_REASON_CANCELLED_BY_APP, - "job rescheduled by app"); + JobParameters.REASON_CANCELED, "job rescheduled by app"); } else { startTrackingJobLocked(jobStatus, null); } @@ -1115,10 +1115,11 @@ public class JobSchedulerService extends com.android.server.SystemService final List jobsForUser = mJobs.getJobsByUser(userHandle); for (int i = 0; i < jobsForUser.size(); i++) { JobStatus toRemove = jobsForUser.get(i); - // By the time we get here, the process should have already been stopped, so the - // app wouldn't get the stop reason, so just put USER instead of UNINSTALL. + // There's no guarantee that the process has been stopped by the time we get here, + // but since this is a user-initiated action, it should be fine to just put USER + // instead of UNINSTALL or DISABLED. cancelJobImplLocked(toRemove, null, JobParameters.STOP_REASON_USER, - "user removed"); + JobParameters.DEBUG_REASON_UNINSTALL, "user removed"); } } @@ -1130,7 +1131,7 @@ public class JobSchedulerService extends com.android.server.SystemService } private void cancelJobsForPackageAndUidLocked(String pkgName, int uid, - @JobParameters.StopReason int reason, String debugReason) { + @JobParameters.StopReason int reason, int debugReasonCode, String debugReason) { if ("android".equals(pkgName)) { Slog.wtfStack(TAG, "Can't cancel all jobs for system package"); return; @@ -1139,7 +1140,7 @@ public class JobSchedulerService extends com.android.server.SystemService for (int i = jobsForUid.size() - 1; i >= 0; i--) { final JobStatus job = jobsForUid.get(i); if (job.getSourcePackageName().equals(pkgName)) { - cancelJobImplLocked(job, null, reason, debugReason); + cancelJobImplLocked(job, null, reason, debugReasonCode, debugReason); } } } @@ -1152,7 +1153,7 @@ public class JobSchedulerService extends com.android.server.SystemService * @param uid Uid to check against for removal of a job. */ public boolean cancelJobsForUid(int uid, @JobParameters.StopReason int reason, - String debugReason) { + int debugReasonCode, String debugReason) { if (uid == Process.SYSTEM_UID) { Slog.wtfStack(TAG, "Can't cancel all jobs for system uid"); return false; @@ -1161,9 +1162,9 @@ public class JobSchedulerService extends com.android.server.SystemService boolean jobsCanceled = false; synchronized (mLock) { final List jobsForUid = mJobs.getJobsByUid(uid); - for (int i=0; i