Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 293c2796 authored by Kweku Adams's avatar Kweku Adams Committed by Android (Google) Code Review
Browse files

Merge "Better handle uninstall cases." into sc-dev

parents 98e99b9f 36bd8292
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -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. */
+2 −1
Original line number Diff line number Diff line
@@ -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.
+62 −48
Original line number Diff line number Diff line
@@ -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,26 +785,23 @@ 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)) {
            } 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);
                }
                    // 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) {
                    // 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, "app uninstalled");
                            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);
                synchronized (mLock) {
@@ -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<JobStatus> 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;
@@ -1163,7 +1164,7 @@ public class JobSchedulerService extends com.android.server.SystemService
            final List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
            for (int i = 0; i < jobsForUid.size(); i++) {
                JobStatus toRemove = jobsForUid.get(i);
                cancelJobImplLocked(toRemove, null, reason, debugReason);
                cancelJobImplLocked(toRemove, null, reason, debugReasonCode, debugReason);
                jobsCanceled = true;
            }
        }
@@ -1185,6 +1186,7 @@ public class JobSchedulerService extends com.android.server.SystemService
            toCancel = mJobs.getJobByUidAndJobId(uid, jobId);
            if (toCancel != null) {
                cancelJobImplLocked(toCancel, null, reason,
                        JobParameters.REASON_CANCELED,
                        "cancel() called by app, callingUid=" + callingUid
                                + " uid=" + uid + " jobId=" + jobId);
            }
@@ -1199,7 +1201,7 @@ public class JobSchedulerService extends com.android.server.SystemService
     * currently scheduled jobs.
     */
    private void cancelJobImplLocked(JobStatus cancelled, JobStatus incomingJob,
            @JobParameters.StopReason int reason, String debugReason) {
            @JobParameters.StopReason int reason, int debugReasonCode, String debugReason) {
        if (DEBUG) Slog.d(TAG, "CANCEL: " + cancelled.toShortString());
        cancelled.unprepareLocked();
        stopTrackingJobLocked(cancelled, incomingJob, true /* writeBack */);
@@ -1208,8 +1210,7 @@ public class JobSchedulerService extends com.android.server.SystemService
            mJobPackageTracker.noteNonpending(cancelled);
        }
        // Cancel if running.
        stopJobOnServiceContextLocked(cancelled, reason, JobParameters.REASON_CANCELED,
                debugReason);
        stopJobOnServiceContextLocked(cancelled, reason, debugReasonCode, debugReason);
        // If this is a replacement, bring in the new version of the job
        if (incomingJob != null) {
            if (DEBUG) Slog.i(TAG, "Tracking replacement job " + incomingJob.toShortString());
@@ -1459,7 +1460,7 @@ public class JobSchedulerService extends com.android.server.SystemService
                    Slog.v(TAG, "  replacing " + oldJob + " with " + newJob);
                }
                cancelJobImplLocked(oldJob, newJob, JobParameters.STOP_REASON_SYSTEM_PROCESSING,
                        "deferred rtc calculation");
                        JobParameters.REASON_CANCELED, "deferred rtc calculation");
            }
        }
    };
@@ -1482,7 +1483,7 @@ public class JobSchedulerService extends com.android.server.SystemService

            // Register br for package removals and user removals.
            final IntentFilter filter = new IntentFilter();
            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
            filter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
            filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
            filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
            filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
@@ -1786,15 +1787,26 @@ public class JobSchedulerService extends com.android.server.SystemService
     * @param needsReschedule Whether the implementing class should reschedule this job.
     */
    @Override
    public void onJobCompletedLocked(JobStatus jobStatus, int stopReason, boolean needsReschedule) {
    public void onJobCompletedLocked(JobStatus jobStatus, int debugStopReason,
            boolean needsReschedule) {
        if (DEBUG) {
            Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule);
            Slog.d(TAG, "Completed " + jobStatus + ", reason=" + debugStopReason
                    + ", reschedule=" + needsReschedule);
        }

        mLastCompletedJobs[mLastCompletedJobIndex] = jobStatus;
        mLastCompletedJobTimeElapsed[mLastCompletedJobIndex] = sElapsedRealtimeClock.millis();
        mLastCompletedJobIndex = (mLastCompletedJobIndex + 1) % NUM_COMPLETED_JOB_HISTORY;

        if (debugStopReason == JobParameters.DEBUG_REASON_UNINSTALL
                || debugStopReason == JobParameters.DEBUG_REASON_DATA_CLEARED) {
            // The job should have already been cleared from the rest of the JS tracking. No need
            // to go through all that flow again.
            jobStatus.unprepareLocked();
            reportActiveLocked();
            return;
        }

        // Intentionally not checking expedited job quota here. An app can't find out if it's run
        // out of quota when it asks JS to reschedule an expedited job. Instead, the rescheduled
        // EJ will just be demoted to a regular job if the app has no EJ quota left.
@@ -1805,8 +1817,8 @@ public class JobSchedulerService extends com.android.server.SystemService
        final JobStatus rescheduledJob = needsReschedule
                ? getRescheduleJobForFailureLocked(jobStatus) : null;
        if (rescheduledJob != null
                && (stopReason == JobParameters.REASON_TIMEOUT
                || stopReason == JobParameters.REASON_PREEMPT)) {
                && (debugStopReason == JobParameters.REASON_TIMEOUT
                || debugStopReason == JobParameters.REASON_PREEMPT)) {
            rescheduledJob.disallowRunInBatterySaverAndDoze();
        }

@@ -1911,6 +1923,7 @@ public class JobSchedulerService extends com.android.server.SystemService
                        break;
                    case MSG_STOP_JOB:
                        cancelJobImplLocked((JobStatus) message.obj, null, message.arg1,
                                JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED,
                                "app no longer allowed to run");
                        break;

@@ -1927,7 +1940,7 @@ public class JobSchedulerService extends com.android.server.SystemService
                        if (disabled) {
                            cancelJobsForUid(uid,
                                    JobParameters.STOP_REASON_BACKGROUND_RESTRICTION,
                                    "uid gone");
                                    JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED, "uid gone");
                        }
                        synchronized (mLock) {
                            mDeviceIdleJobsController.setUidActiveLocked(uid, false);
@@ -1947,7 +1960,7 @@ public class JobSchedulerService extends com.android.server.SystemService
                        if (disabled) {
                            cancelJobsForUid(uid,
                                    JobParameters.STOP_REASON_BACKGROUND_RESTRICTION,
                                    "app uid idle");
                                    JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED, "app uid idle");
                        }
                        synchronized (mLock) {
                            mDeviceIdleJobsController.setUidActiveLocked(uid, false);
@@ -2409,8 +2422,8 @@ public class JobSchedulerService extends com.android.server.SystemService

        @Override
        public void cancelJobsForUid(int uid, @JobParameters.StopReason int reason,
                String debugReason) {
            JobSchedulerService.this.cancelJobsForUid(uid, reason, debugReason);
                int debugReasonCode, String debugReason) {
            JobSchedulerService.this.cancelJobsForUid(uid, reason, debugReasonCode, debugReason);
        }

        @Override
@@ -2749,6 +2762,7 @@ public class JobSchedulerService extends com.android.server.SystemService
            try {
                JobSchedulerService.this.cancelJobsForUid(uid,
                        JobParameters.STOP_REASON_CANCELLED_BY_APP,
                        JobParameters.REASON_CANCELED,
                        "cancelAll() called by app, callingUid=" + uid);
            } finally {
                Binder.restoreCallingIdentity(ident);
@@ -2969,7 +2983,7 @@ 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,
                    "cancel shell command for package")) {
                    JobParameters.REASON_CANCELED, "cancel shell command for package")) {
                pw.println("No matching jobs found.");
            }
        } else {
+4 −1
Original line number Diff line number Diff line
@@ -244,7 +244,10 @@ public final class ConnectivityController extends RestrictingController implemen
                    getUidStats(jobStatus.getSourceUid(), jobStatus.getSourcePackageName(), true);
            uidStats.numReadyWithConnectivity--;
            if (jobStatus.madeActive != 0) {
                uidStats.numRunning--;
                // numRunning would be 0 if the UidStats object didn't exist before this method
                // was called. getUidStats() handles logging, so just make sure we don't save a
                // negative value.
                uidStats.numRunning = Math.max(0, uidStats.numRunning - 1);
            }
            maybeRevokeStandbyExceptionLocked(jobStatus);
            postAdjustCallbacks();
+1 −0
Original line number Diff line number Diff line
@@ -735,6 +735,7 @@ public final class QuotaController extends StateController {
        mTempAllowlistCache.delete(uid);
        mTempAllowlistGraceCache.delete(uid);
        mTopAppCache.delete(uid);
        mTopAppTrackers.delete(uid);
        mTopAppGraceCache.delete(uid);
    }

Loading