diff options
5 files changed, 51 insertions, 33 deletions
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 2682dd75ca73..442c13009d8b 100644 --- a/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java +++ b/apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java @@ -36,9 +36,11 @@ public interface JobSchedulerInternal { /** * Cancel the jobs for a given uid (e.g. when app data is cleared) + * + * @param includeProxiedJobs Include jobs scheduled for this UID by other apps */ - void cancelJobsForUid(int uid, @JobParameters.StopReason int reason, int debugReasonCode, - String debugReason); + void cancelJobsForUid(int uid, boolean includeProxiedJobs, + @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 f5c0ed9f03f7..bdd1fc548af2 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -970,12 +970,12 @@ public class JobSchedulerService extends com.android.server.SystemService // Has this package scheduled any jobs, such that we will take action // if it were to be force-stopped? if (pkgUid != -1) { - List<JobStatus> jobsForUid; + ArraySet<JobStatus> jobsForUid; synchronized (mLock) { jobsForUid = mJobs.getJobsByUid(pkgUid); } for (int i = jobsForUid.size() - 1; i >= 0; i--) { - if (jobsForUid.get(i).getSourcePackageName().equals(pkgName)) { + if (jobsForUid.valueAt(i).getSourcePackageName().equals(pkgName)) { if (DEBUG) { Slog.d(TAG, "Restart query: package " + pkgName + " at uid " + pkgUid + " has jobs"); @@ -1292,10 +1292,11 @@ public class JobSchedulerService extends com.android.server.SystemService public List<JobInfo> getPendingJobs(int uid) { synchronized (mLock) { - List<JobStatus> jobs = mJobs.getJobsByUid(uid); + ArraySet<JobStatus> jobs = mJobs.getJobsByUid(uid); ArrayList<JobInfo> outList = new ArrayList<JobInfo>(jobs.size()); + // Write out for loop to avoid addAll() creating an Iterator. for (int i = jobs.size() - 1; i >= 0; i--) { - JobStatus job = jobs.get(i); + final JobStatus job = jobs.valueAt(i); outList.add(job.getJob()); } return outList; @@ -1304,9 +1305,9 @@ public class JobSchedulerService extends com.android.server.SystemService public JobInfo getPendingJob(int uid, int jobId) { synchronized (mLock) { - List<JobStatus> jobs = mJobs.getJobsByUid(uid); + ArraySet<JobStatus> jobs = mJobs.getJobsByUid(uid); for (int i = jobs.size() - 1; i >= 0; i--) { - JobStatus job = jobs.get(i); + JobStatus job = jobs.valueAt(i); if (job.getJobId() == jobId) { return job.getJob(); } @@ -1348,7 +1349,7 @@ public class JobSchedulerService extends com.android.server.SystemService Slog.wtfStack(TAG, "Can't cancel all jobs for system package"); return; } - final List<JobStatus> jobsForUid = new ArrayList<>(); + final ArraySet<JobStatus> jobsForUid = new ArraySet<>(); if (includeSchedulingApp) { mJobs.getJobsByUid(uid, jobsForUid); } @@ -1356,7 +1357,7 @@ public class JobSchedulerService extends com.android.server.SystemService mJobs.getJobsBySourceUid(uid, jobsForUid); } for (int i = jobsForUid.size() - 1; i >= 0; i--) { - final JobStatus job = jobsForUid.get(i); + final JobStatus job = jobsForUid.valueAt(i); final boolean shouldCancel = (includeSchedulingApp && job.getServiceComponent().getPackageName().equals(pkgName)) @@ -1368,14 +1369,16 @@ public class JobSchedulerService extends com.android.server.SystemService } /** - * Entry point from client to cancel all jobs originating from their uid. + * Entry point from client to cancel all jobs scheduled for or from their uid. * This will remove the job from the master list, and cancel the job if it was staged for * execution or being executed. * * @param uid Uid to check against for removal of a job. + * @param includeSourceApp Whether to include jobs scheduled for this UID by another UID. + * If false, only jobs scheduled by this UID will be cancelled. */ - public boolean cancelJobsForUid(int uid, @JobParameters.StopReason int reason, - int internalReasonCode, String debugReason) { + public boolean cancelJobsForUid(int uid, boolean includeSourceApp, + @JobParameters.StopReason int reason, int internalReasonCode, String debugReason) { if (uid == Process.SYSTEM_UID) { Slog.wtfStack(TAG, "Can't cancel all jobs for system uid"); return false; @@ -1383,9 +1386,15 @@ public class JobSchedulerService extends com.android.server.SystemService boolean jobsCanceled = false; synchronized (mLock) { - final List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid); + final ArraySet<JobStatus> jobsForUid = new ArraySet<>(); + // Get jobs scheduled by the app. + mJobs.getJobsByUid(uid, jobsForUid); + if (includeSourceApp) { + // Get jobs scheduled for the app by someone else. + mJobs.getJobsBySourceUid(uid, jobsForUid); + } for (int i = 0; i < jobsForUid.size(); i++) { - JobStatus toRemove = jobsForUid.get(i); + JobStatus toRemove = jobsForUid.valueAt(i); cancelJobImplLocked(toRemove, null, reason, internalReasonCode, debugReason); jobsCanceled = true; } @@ -2220,6 +2229,7 @@ public class JobSchedulerService extends com.android.server.SystemService updateUidState(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY); if (disabled) { cancelJobsForUid(uid, + /* includeSourceApp */ true, JobParameters.STOP_REASON_BACKGROUND_RESTRICTION, JobParameters.INTERNAL_STOP_REASON_CONSTRAINTS_NOT_SATISFIED, "uid gone"); @@ -2241,6 +2251,7 @@ public class JobSchedulerService extends com.android.server.SystemService final boolean disabled = message.arg2 != 0; if (disabled) { cancelJobsForUid(uid, + /* includeSourceApp */ true, JobParameters.STOP_REASON_BACKGROUND_RESTRICTION, JobParameters.INTERNAL_STOP_REASON_CONSTRAINTS_NOT_SATISFIED, "app uid idle"); @@ -2899,9 +2910,10 @@ public class JobSchedulerService extends com.android.server.SystemService } @Override - public void cancelJobsForUid(int uid, @JobParameters.StopReason int reason, - int internalReasonCode, String debugReason) { - JobSchedulerService.this.cancelJobsForUid(uid, reason, internalReasonCode, debugReason); + public void cancelJobsForUid(int uid, boolean includeProxiedJobs, + @JobParameters.StopReason int reason, int internalReasonCode, String debugReason) { + JobSchedulerService.this.cancelJobsForUid(uid, + includeProxiedJobs, reason, internalReasonCode, debugReason); } @Override @@ -3273,6 +3285,8 @@ public class JobSchedulerService extends com.android.server.SystemService final long ident = Binder.clearCallingIdentity(); try { JobSchedulerService.this.cancelJobsForUid(uid, + // Documentation says only jobs scheduled BY the app will be cancelled + /* includeSourceApp */ false, JobParameters.STOP_REASON_CANCELLED_BY_APP, JobParameters.INTERNAL_STOP_REASON_CANCELED, "cancelAll() called by app, callingUid=" + uid); @@ -3484,7 +3498,9 @@ public class JobSchedulerService extends com.android.server.SystemService if (!hasJobId) { pw.println("Canceling all jobs for " + pkgName + " in user " + userId); - if (!cancelJobsForUid(pkgUid, JobParameters.STOP_REASON_USER, + if (!cancelJobsForUid(pkgUid, + /* includeSourceApp */ false, + JobParameters.STOP_REASON_USER, JobParameters.INTERNAL_STOP_REASON_CANCELED, "cancel shell command for package")) { pw.println("No matching jobs found."); diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java index ff4d26dc807d..f731b8d1d0d7 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java @@ -291,11 +291,11 @@ public final class JobStore { * @return A list of all the jobs scheduled for the source app. Never null. */ @NonNull - public List<JobStatus> getJobsBySourceUid(int sourceUid) { + public ArraySet<JobStatus> getJobsBySourceUid(int sourceUid) { return mJobSet.getJobsBySourceUid(sourceUid); } - public void getJobsBySourceUid(int sourceUid, @NonNull List<JobStatus> insertInto) { + public void getJobsBySourceUid(int sourceUid, @NonNull Set<JobStatus> insertInto) { mJobSet.getJobsBySourceUid(sourceUid, insertInto); } @@ -304,11 +304,11 @@ public final class JobStore { * @return All JobStatus objects for a given uid from the master list. Never null. */ @NonNull - public List<JobStatus> getJobsByUid(int uid) { + public ArraySet<JobStatus> getJobsByUid(int uid) { return mJobSet.getJobsByUid(uid); } - public void getJobsByUid(int uid, @NonNull List<JobStatus> insertInto) { + public void getJobsByUid(int uid, @NonNull Set<JobStatus> insertInto) { mJobSet.getJobsByUid(uid, insertInto); } @@ -1232,13 +1232,13 @@ public final class JobStore { mJobsPerSourceUid = new SparseArray<>(); } - public List<JobStatus> getJobsByUid(int uid) { - ArrayList<JobStatus> matchingJobs = new ArrayList<JobStatus>(); + public ArraySet<JobStatus> getJobsByUid(int uid) { + ArraySet<JobStatus> matchingJobs = new ArraySet<>(); getJobsByUid(uid, matchingJobs); return matchingJobs; } - public void getJobsByUid(int uid, List<JobStatus> insertInto) { + public void getJobsByUid(int uid, Set<JobStatus> insertInto) { ArraySet<JobStatus> jobs = mJobs.get(uid); if (jobs != null) { insertInto.addAll(jobs); @@ -1246,13 +1246,13 @@ public final class JobStore { } @NonNull - public List<JobStatus> getJobsBySourceUid(int sourceUid) { - final ArrayList<JobStatus> result = new ArrayList<JobStatus>(); + public ArraySet<JobStatus> getJobsBySourceUid(int sourceUid) { + final ArraySet<JobStatus> result = new ArraySet<>(); getJobsBySourceUid(sourceUid, result); return result; } - public void getJobsBySourceUid(int sourceUid, List<JobStatus> insertInto) { + public void getJobsBySourceUid(int sourceUid, Set<JobStatus> insertInto) { final ArraySet<JobStatus> jobs = mJobsPerSourceUid.get(sourceUid); if (jobs != null) { insertInto.addAll(jobs); diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java index 9c167728cff9..bbd661acca01 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java @@ -50,7 +50,6 @@ import com.android.server.utils.AlarmQueue; import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import java.util.function.Predicate; /** @@ -397,10 +396,10 @@ public final class FlexibilityController extends StateController { return; } final long nowElapsed = sElapsedRealtimeClock.millis(); - List<JobStatus> jobsByUid = mService.getJobStore().getJobsByUid(uid); + ArraySet<JobStatus> jobsByUid = mService.getJobStore().getJobsBySourceUid(uid); boolean hasPrefetch = false; for (int i = 0; i < jobsByUid.size(); i++) { - JobStatus js = jobsByUid.get(i); + JobStatus js = jobsByUid.valueAt(i); if (js.hasFlexibilityConstraint()) { js.setFlexibilityConstraintSatisfied(nowElapsed, isFlexibilitySatisfiedLocked(js)); hasPrefetch |= js.getJob().isPrefetch(); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 593e21a54f15..1a4da7db54e9 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3937,7 +3937,8 @@ public class ActivityManagerService extends IActivityManager.Stub // Clear its scheduled jobs JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class); // Clearing data is a user-initiated action. - js.cancelJobsForUid(appInfo.uid, JobParameters.STOP_REASON_USER, + js.cancelJobsForUid(appInfo.uid, /* includeProxiedJobs */ true, + JobParameters.STOP_REASON_USER, JobParameters.INTERNAL_STOP_REASON_DATA_CLEARED, "clear data"); // Clear its pending alarms |