Loading apex/jobscheduler/service/java/com/android/server/job/JobStore.java +57 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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() { Loading Loading @@ -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(); Loading @@ -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); } Loading Loading @@ -303,6 +339,7 @@ public final class JobStore { } return false; } mCurrentJobSetSize--; if (removeFromPersisted && jobStatus.isPersisted()) { mPendingJobWriteUids.put(jobStatus.getUid(), true); maybeWriteStatusToDiskAsync(); Loading @@ -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); } Loading @@ -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. */ Loading @@ -342,6 +382,7 @@ public final class JobStore { public void clear() { mJobSet.clear(); mPendingJobWriteUids.put(ALL_UIDS, true); mCurrentJobSetSize = 0; maybeWriteStatusToDiskAsync(); } Loading @@ -352,6 +393,7 @@ public final class JobStore { public void clearForTesting() { mJobSet.clear(); mPendingJobWriteUids.put(ALL_UIDS, true); mCurrentJobSetSize = 0; } void setUseSplitFiles(boolean useSplitFiles) { Loading Loading @@ -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; /** Loading Loading @@ -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(); } Loading Loading
apex/jobscheduler/service/java/com/android/server/job/JobStore.java +57 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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() { Loading Loading @@ -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(); Loading @@ -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); } Loading Loading @@ -303,6 +339,7 @@ public final class JobStore { } return false; } mCurrentJobSetSize--; if (removeFromPersisted && jobStatus.isPersisted()) { mPendingJobWriteUids.put(jobStatus.getUid(), true); maybeWriteStatusToDiskAsync(); Loading @@ -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); } Loading @@ -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. */ Loading @@ -342,6 +382,7 @@ public final class JobStore { public void clear() { mJobSet.clear(); mPendingJobWriteUids.put(ALL_UIDS, true); mCurrentJobSetSize = 0; maybeWriteStatusToDiskAsync(); } Loading @@ -352,6 +393,7 @@ public final class JobStore { public void clearForTesting() { mJobSet.clear(); mPendingJobWriteUids.put(ALL_UIDS, true); mCurrentJobSetSize = 0; } void setUseSplitFiles(boolean useSplitFiles) { Loading Loading @@ -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; /** Loading Loading @@ -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(); } Loading