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

Commit 70d74835 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Clearing QuotaController data on app/user removal."

parents ca72a202 a9f8e1f7
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -861,6 +861,11 @@ public class JobSchedulerService extends com.android.server.SystemService
                        Slog.d(TAG, "Removing jobs for uid: " + uidRemoved);
                    }
                    cancelJobsForPackageAndUid(pkgName, uidRemoved, "app uninstalled");
                    synchronized (mLock) {
                        for (int c = 0; c < mControllers.size(); ++c) {
                            mControllers.get(c).onAppRemovedLocked(pkgName, pkgUid);
                        }
                    }
                }
            } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
@@ -868,6 +873,11 @@ public class JobSchedulerService extends com.android.server.SystemService
                    Slog.d(TAG, "Removing jobs for user: " + userId);
                }
                cancelJobsForUser(userId);
                synchronized (mLock) {
                    for (int c = 0; c < mControllers.size(); ++c) {
                        mControllers.get(c).onUserRemovedLocked(userId);
                    }
                }
            } else if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
                // Has this package scheduled any jobs, such that we will take action
                // if it were to be force-stopped?
+6 −0
Original line number Diff line number Diff line
@@ -296,6 +296,12 @@ public final class ConnectivityController extends StateController implements
        mRequestedWhitelistJobs.remove(uid);
    }

    @GuardedBy("mLock")
    @Override
    public void onAppRemovedLocked(String pkgName, int uid) {
        mTrackedJobs.delete(uid);
    }

    /**
     * Test to see if running the given job on the given network is insane.
     * <p>
+54 −0
Original line number Diff line number Diff line
@@ -98,6 +98,19 @@ public final class QuotaController extends StateController {
            data.put(packageName, obj);
        }

        /** Removes all the data for the user, if there was any. */
        public void delete(int userId) {
            mData.delete(userId);
        }

        /** Removes the data for the user and package, if there was any. */
        public void delete(int userId, @NonNull String packageName) {
            ArrayMap<String, T> data = mData.get(userId);
            if (data != null) {
                data.remove(packageName);
            }
        }

        @Nullable
        public T get(int userId, @NonNull String packageName) {
            ArrayMap<String, T> data = mData.get(userId);
@@ -371,6 +384,38 @@ public final class QuotaController extends StateController {
        }
    }

    @Override
    public void onAppRemovedLocked(String packageName, int uid) {
        if (packageName == null) {
            Slog.wtf(TAG, "Told app removed but given null package name.");
            return;
        }
        final int userId = UserHandle.getUserId(uid);
        mTrackedJobs.delete(userId, packageName);
        Timer timer = mPkgTimers.get(userId, packageName);
        if (timer != null) {
            if (timer.isActive()) {
                Slog.wtf(TAG, "onAppRemovedLocked called before Timer turned off.");
                timer.dropEverything();
            }
            mPkgTimers.delete(userId, packageName);
        }
        mTimingSessions.delete(userId, packageName);
        QcAlarmListener alarmListener = mInQuotaAlarmListeners.get(userId, packageName);
        if (alarmListener != null) {
            mAlarmManager.cancel(alarmListener);
            mInQuotaAlarmListeners.delete(userId, packageName);
        }
    }

    @Override
    public void onUserRemovedLocked(int userId) {
        mTrackedJobs.delete(userId);
        mPkgTimers.delete(userId);
        mTimingSessions.delete(userId);
        mInQuotaAlarmListeners.delete(userId);
    }

    /**
     * Returns an appropriate standby bucket for the job, taking into account any standby
     * exemptions.
@@ -882,6 +927,15 @@ public final class QuotaController extends StateController {
            }
        }

        /**
         * Stops tracking all jobs and cancels any pending alarms. This should only be called if
         * the Timer is not going to be used anymore.
         */
        void dropEverything() {
            mRunningBgJobs.clear();
            cancelCutoff();
        }

        private void emitSessionLocked(long nowElapsed) {
            if (mBgJobCount <= 0) {
                // Nothing to emit.
+22 −14
Original line number Diff line number Diff line
@@ -83,21 +83,12 @@ public abstract class StateController {
    public void onConstantsUpdatedLocked() {
    }

    protected boolean wouldBeReadyWithConstraintLocked(JobStatus jobStatus, int constraint) {
        // This is very cheap to check (just a few conditions on data in JobStatus).
        final boolean jobWouldBeReady = jobStatus.wouldBeReadyWithConstraint(constraint);
        if (DEBUG) {
            Slog.v(TAG, "wouldBeReadyWithConstraintLocked: " + jobStatus.toShortString()
                    + " readyWithConstraint=" + jobWouldBeReady);
        }
        if (!jobWouldBeReady) {
            // If the job wouldn't be ready, nothing to do here.
            return false;
    /** Called when a package is uninstalled from the device (not for an update). */
    public void onAppRemovedLocked(String packageName, int uid) {
    }

        // This is potentially more expensive since JSS may have to query component
        // presence.
        return mService.areComponentsInPlaceLocked(jobStatus);
    /** Called when a user is removed from the device. */
    public void onUserRemovedLocked(int userId) {
    }

    /**
@@ -114,6 +105,23 @@ public abstract class StateController {
    public void reevaluateStateLocked(int uid) {
    }

    protected boolean wouldBeReadyWithConstraintLocked(JobStatus jobStatus, int constraint) {
        // This is very cheap to check (just a few conditions on data in JobStatus).
        final boolean jobWouldBeReady = jobStatus.wouldBeReadyWithConstraint(constraint);
        if (DEBUG) {
            Slog.v(TAG, "wouldBeReadyWithConstraintLocked: " + jobStatus.toShortString()
                    + " readyWithConstraint=" + jobWouldBeReady);
        }
        if (!jobWouldBeReady) {
            // If the job wouldn't be ready, nothing to do here.
            return false;
        }

        // This is potentially more expensive since JSS may have to query component
        // presence.
        return mService.areComponentsInPlaceLocked(jobStatus);
    }

    public abstract void dumpControllerStateLocked(IndentingPrintWriter pw,
            Predicate<JobStatus> predicate);
    public abstract void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
+54 −0
Original line number Diff line number Diff line
@@ -269,6 +269,60 @@ public class QuotaControllerTest {
        assertEquals(expected, mQuotaController.getTimingSessions(0, "com.android.test"));
    }

    @Test
    public void testOnAppRemovedLocked() {
        final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
        mQuotaController.saveTimingSession(0, "com.android.test.remove",
                createTimingSession(now - (6 * HOUR_IN_MILLIS), 10 * MINUTE_IN_MILLIS, 5));
        mQuotaController.saveTimingSession(0, "com.android.test.remove",
                createTimingSession(
                        now - (2 * HOUR_IN_MILLIS + MINUTE_IN_MILLIS), 6 * MINUTE_IN_MILLIS, 5));
        mQuotaController.saveTimingSession(0, "com.android.test.remove",
                createTimingSession(now - (HOUR_IN_MILLIS), MINUTE_IN_MILLIS, 1));
        // Test that another app isn't affected.
        TimingSession one = createTimingSession(
                now - 10 * MINUTE_IN_MILLIS, 9 * MINUTE_IN_MILLIS, 3);
        TimingSession two = createTimingSession(
                now - (70 * MINUTE_IN_MILLIS), 9 * MINUTE_IN_MILLIS, 1);
        List<TimingSession> expected = new ArrayList<>();
        // Added in correct (chronological) order.
        expected.add(two);
        expected.add(one);
        mQuotaController.saveTimingSession(0, "com.android.test.stay", two);
        mQuotaController.saveTimingSession(0, "com.android.test.stay", one);

        mQuotaController.onAppRemovedLocked("com.android.test.remove", 10001);
        assertNull(mQuotaController.getTimingSessions(0, "com.android.test.remove"));
        assertEquals(expected, mQuotaController.getTimingSessions(0, "com.android.test.stay"));
    }

    @Test
    public void testOnUserRemovedLocked() {
        final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
        mQuotaController.saveTimingSession(0, "com.android.test",
                createTimingSession(now - (6 * HOUR_IN_MILLIS), 10 * MINUTE_IN_MILLIS, 5));
        mQuotaController.saveTimingSession(0, "com.android.test",
                createTimingSession(
                        now - (2 * HOUR_IN_MILLIS + MINUTE_IN_MILLIS), 6 * MINUTE_IN_MILLIS, 5));
        mQuotaController.saveTimingSession(0, "com.android.test",
                createTimingSession(now - (HOUR_IN_MILLIS), MINUTE_IN_MILLIS, 1));
        // Test that another user isn't affected.
        TimingSession one = createTimingSession(
                now - 10 * MINUTE_IN_MILLIS, 9 * MINUTE_IN_MILLIS, 3);
        TimingSession two = createTimingSession(
                now - (70 * MINUTE_IN_MILLIS), 9 * MINUTE_IN_MILLIS, 1);
        List<TimingSession> expected = new ArrayList<>();
        // Added in correct (chronological) order.
        expected.add(two);
        expected.add(one);
        mQuotaController.saveTimingSession(10, "com.android.test", two);
        mQuotaController.saveTimingSession(10, "com.android.test", one);

        mQuotaController.onUserRemovedLocked(0);
        assertNull(mQuotaController.getTimingSessions(0, "com.android.test"));
        assertEquals(expected, mQuotaController.getTimingSessions(10, "com.android.test"));
    }

    @Test
    public void testGetTrailingExecutionTimeLocked_NoTimer() {
        final long now = JobSchedulerService.sElapsedRealtimeClock.millis();