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

Commit 61623568 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Add scheduled job high water mark metric." into udc-dev am: 1588d4ac

parents 6ff1a335 1588d4ac
Loading
Loading
Loading
Loading
+57 −3
Original line number Diff line number Diff line
@@ -49,8 +49,10 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.BitUtils;
import com.android.modules.expresslog.Histogram;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
import com.android.server.AppSchedulingModuleThread;
import com.android.server.IoThread;
import com.android.server.job.JobSchedulerInternal.JobStorePersistStats;
import com.android.server.job.controllers.JobStatus;
@@ -94,6 +96,7 @@ public final class JobStore {

    /** Threshold to adjust how often we want to write to the db. */
    private static final long JOB_PERSIST_DELAY = 2000L;
    private static final long SCHEDULED_JOB_HIGH_WATER_MARK_PERIOD_MS = 30 * 60_000L;
    @VisibleForTesting
    static final String JOB_FILE_SPLIT_PREFIX = "jobs_";
    private static final int ALL_UIDS = -1;
@@ -131,6 +134,30 @@ public final class JobStore {

    private JobStorePersistStats mPersistInfo = new JobStorePersistStats();

    /**
     * Separately updated value of the JobSet size to avoid recalculating it frequently for logging
     * purposes. Continue to use {@link JobSet#size()} for the up-to-date and accurate value.
     */
    private int mCurrentJobSetSize = 0;
    private int mScheduledJob30MinHighWaterMark = 0;
    private static final Histogram sScheduledJob30MinHighWaterMarkLogger = new Histogram(
            "job_scheduler.value_hist_scheduled_job_30_min_high_water_mark",
            new Histogram.ScaledRangeOptions(15, 1, 99, 1.5f));
    private final Runnable mScheduledJobHighWaterMarkLoggingRunnable = new Runnable() {
        @Override
        public void run() {
            AppSchedulingModuleThread.getHandler().removeCallbacks(this);
            synchronized (mLock) {
                sScheduledJob30MinHighWaterMarkLogger.logSample(mScheduledJob30MinHighWaterMark);
                mScheduledJob30MinHighWaterMark = mJobSet.size();
            }
            // The count doesn't need to be logged at exact times. Logging based on system uptime
            // should be fine.
            AppSchedulingModuleThread.getHandler()
                    .postDelayed(this, SCHEDULED_JOB_HIGH_WATER_MARK_PERIOD_MS);
        }
    };

    /** Used by the {@link JobSchedulerService} to instantiate the JobStore. */
    static JobStore get(JobSchedulerService jobManagerService) {
        synchronized (sSingletonLock) {
@@ -183,6 +210,9 @@ public final class JobStore {
        mXmlTimestamp = mJobsFile.exists()
                ? mJobsFile.getLastModifiedTime() : mJobFileDirectory.lastModified();
        mRtcGood = (sSystemClock.millis() > mXmlTimestamp);

        AppSchedulingModuleThread.getHandler().postDelayed(
                mScheduledJobHighWaterMarkLoggingRunnable, SCHEDULED_JOB_HIGH_WATER_MARK_PERIOD_MS);
    }

    private void init() {
@@ -252,7 +282,10 @@ public final class JobStore {
     * @param jobStatus Job to add.
     */
    public void add(JobStatus jobStatus) {
        mJobSet.add(jobStatus);
        if (mJobSet.add(jobStatus)) {
            mCurrentJobSetSize++;
            maybeUpdateHighWaterMark();
        }
        if (jobStatus.isPersisted()) {
            mPendingJobWriteUids.put(jobStatus.getUid(), true);
            maybeWriteStatusToDiskAsync();
@@ -267,7 +300,10 @@ public final class JobStore {
     */
    @VisibleForTesting
    public void addForTesting(JobStatus jobStatus) {
        mJobSet.add(jobStatus);
        if (mJobSet.add(jobStatus)) {
            mCurrentJobSetSize++;
            maybeUpdateHighWaterMark();
        }
        if (jobStatus.isPersisted()) {
            mPendingJobWriteUids.put(jobStatus.getUid(), true);
        }
@@ -303,6 +339,7 @@ public final class JobStore {
            }
            return false;
        }
        mCurrentJobSetSize--;
        if (removeFromPersisted && jobStatus.isPersisted()) {
            mPendingJobWriteUids.put(jobStatus.getUid(), true);
            maybeWriteStatusToDiskAsync();
@@ -315,7 +352,9 @@ public final class JobStore {
     */
    @VisibleForTesting
    public void removeForTesting(JobStatus jobStatus) {
        mJobSet.remove(jobStatus);
        if (mJobSet.remove(jobStatus)) {
            mCurrentJobSetSize--;
        }
        if (jobStatus.isPersisted()) {
            mPendingJobWriteUids.put(jobStatus.getUid(), true);
        }
@@ -327,6 +366,7 @@ public final class JobStore {
     */
    public void removeJobsOfUnlistedUsers(int[] keepUserIds) {
        mJobSet.removeJobsOfUnlistedUsers(keepUserIds);
        mCurrentJobSetSize = mJobSet.size();
    }

    /** Note a change in the specified JobStatus that necessitates writing job state to disk. */
@@ -342,6 +382,7 @@ public final class JobStore {
    public void clear() {
        mJobSet.clear();
        mPendingJobWriteUids.put(ALL_UIDS, true);
        mCurrentJobSetSize = 0;
        maybeWriteStatusToDiskAsync();
    }

@@ -352,6 +393,7 @@ public final class JobStore {
    public void clearForTesting() {
        mJobSet.clear();
        mPendingJobWriteUids.put(ALL_UIDS, true);
        mCurrentJobSetSize = 0;
    }

    void setUseSplitFiles(boolean useSplitFiles) {
@@ -442,6 +484,12 @@ public final class JobStore {
        mJobSet.forEachJobForSourceUid(sourceUid, functor);
    }

    private void maybeUpdateHighWaterMark() {
        if (mScheduledJob30MinHighWaterMark < mCurrentJobSetSize) {
            mScheduledJob30MinHighWaterMark = mCurrentJobSetSize;
        }
    }

    /** Version of the db schema. */
    private static final int JOBS_FILE_VERSION = 1;
    /**
@@ -1125,6 +1173,12 @@ public final class JobStore {
            if (needFileMigration) {
                migrateJobFilesAsync();
            }

            // Log the count immediately after loading from boot.
            mCurrentJobSetSize = numJobs;
            mScheduledJob30MinHighWaterMark = mCurrentJobSetSize;
            mScheduledJobHighWaterMarkLoggingRunnable.run();

            if (mCompletionLatch != null) {
                mCompletionLatch.countDown();
            }