Loading apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +15 −3 Original line number Diff line number Diff line Loading @@ -153,6 +153,7 @@ import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.function.Consumer; import java.util.function.Predicate; Loading Loading @@ -242,6 +243,7 @@ public class JobSchedulerService extends com.android.server.SystemService final Object mLock = new Object(); /** Master list of jobs. */ final JobStore mJobs; private final CountDownLatch mJobStoreLoadedLatch; /** Tracking the standby bucket state of each app */ final StandbyTracker mStandbyTracker; /** Tracking amount of time each package runs for. */ Loading Loading @@ -2044,7 +2046,9 @@ public class JobSchedulerService extends com.android.server.SystemService publishLocalService(JobSchedulerInternal.class, new LocalService()); // Initialize the job store and set up any persisted jobs mJobs = JobStore.initAndGet(this); mJobStoreLoadedLatch = new CountDownLatch(1); mJobs = JobStore.get(this); mJobs.initAsync(mJobStoreLoadedLatch); mBatteryStateTracker = new BatteryStateTracker(); mBatteryStateTracker.startTracking(); Loading Loading @@ -2112,7 +2116,7 @@ public class JobSchedulerService extends com.android.server.SystemService // And kick off the work to update the affected jobs, using a secondary // thread instead of chugging away here on the main looper thread. new Thread(mJobTimeUpdater, "JobSchedulerTimeSetReceiver").start(); mJobs.runWorkAsync(mJobTimeUpdater); } } } Loading Loading @@ -2150,7 +2154,15 @@ public class JobSchedulerService extends com.android.server.SystemService @Override public void onBootPhase(int phase) { if (PHASE_SYSTEM_SERVICES_READY == phase) { if (PHASE_LOCK_SETTINGS_READY == phase) { // This is the last phase before PHASE_SYSTEM_SERVICES_READY. We need to ensure that // persisted jobs are loaded before we can proceed to PHASE_SYSTEM_SERVICES_READY. try { mJobStoreLoadedLatch.await(); } catch (InterruptedException e) { Slog.e(TAG, "Couldn't wait on job store loading latch"); } } else if (PHASE_SYSTEM_SERVICES_READY == phase) { mConstantsObserver.start(); for (StateController controller : mControllers) { controller.onSystemServicesReady(); Loading apex/jobscheduler/service/java/com/android/server/job/JobStore.java +28 −1 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ import java.util.List; import java.util.Objects; import java.util.Set; import java.util.StringJoiner; import java.util.concurrent.CountDownLatch; import java.util.function.Consumer; import java.util.function.Predicate; Loading Loading @@ -131,7 +132,7 @@ public final class JobStore { private JobStorePersistStats mPersistInfo = new JobStorePersistStats(); /** Used by the {@link JobSchedulerService} to instantiate the JobStore. */ static JobStore initAndGet(JobSchedulerService jobManagerService) { static JobStore get(JobSchedulerService jobManagerService) { synchronized (sSingletonLock) { if (sSingleton == null) { sSingleton = new JobStore(jobManagerService.getContext(), Loading @@ -147,6 +148,7 @@ public final class JobStore { @VisibleForTesting public static JobStore initAndGetForTesting(Context context, File dataDir) { JobStore jobStoreUnderTest = new JobStore(context, new Object(), dataDir); jobStoreUnderTest.init(); jobStoreUnderTest.clearForTesting(); return jobStoreUnderTest; } Loading Loading @@ -181,10 +183,16 @@ public final class JobStore { mXmlTimestamp = mJobsFile.exists() ? mJobsFile.getLastModifiedTime() : mJobFileDirectory.lastModified(); mRtcGood = (sSystemClock.millis() > mXmlTimestamp); } private void init() { readJobMapFromDisk(mJobSet, mRtcGood); } void initAsync(CountDownLatch completionLatch) { mIoHandler.post(new ReadJobMapFromDiskRunnable(mJobSet, mRtcGood, completionLatch)); } private AtomicFile createJobFile(String baseName) { return createJobFile(new File(mJobFileDirectory, baseName + ".xml")); } Loading @@ -201,6 +209,15 @@ public final class JobStore { return now >= mXmlTimestamp; } /** * Runs any necessary work asynchronously. If this is called after * {@link #initAsync(CountDownLatch)}, this ensures the given work runs after * the JobStore is initialized. */ void runWorkAsync(@NonNull Runnable r) { mIoHandler.post(r); } /** * Find all the jobs that were affected by RTC clock uncertainty at boot time. Returns * parallel lists of the existing JobStatus objects and of new, equivalent JobStatus instances Loading Loading @@ -998,14 +1015,21 @@ public final class JobStore { private final class ReadJobMapFromDiskRunnable implements Runnable { private final JobSet jobSet; private final boolean rtcGood; private final CountDownLatch mCompletionLatch; /** * @param jobSet Reference to the (empty) set of JobStatus objects that back the JobStore, * so that after disk read we can populate it directly. */ ReadJobMapFromDiskRunnable(JobSet jobSet, boolean rtcIsGood) { this(jobSet, rtcIsGood, null); } ReadJobMapFromDiskRunnable(JobSet jobSet, boolean rtcIsGood, @Nullable CountDownLatch completionLatch) { this.jobSet = jobSet; this.rtcGood = rtcIsGood; this.mCompletionLatch = completionLatch; } @Override Loading Loading @@ -1088,6 +1112,9 @@ public final class JobStore { if (needFileMigration) { migrateJobFilesAsync(); } if (mCompletionLatch != null) { mCompletionLatch.countDown(); } } private List<JobStatus> readJobMapImpl(InputStream fis, boolean rtcIsGood, long nowElapsed) Loading Loading
apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +15 −3 Original line number Diff line number Diff line Loading @@ -153,6 +153,7 @@ import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.function.Consumer; import java.util.function.Predicate; Loading Loading @@ -242,6 +243,7 @@ public class JobSchedulerService extends com.android.server.SystemService final Object mLock = new Object(); /** Master list of jobs. */ final JobStore mJobs; private final CountDownLatch mJobStoreLoadedLatch; /** Tracking the standby bucket state of each app */ final StandbyTracker mStandbyTracker; /** Tracking amount of time each package runs for. */ Loading Loading @@ -2044,7 +2046,9 @@ public class JobSchedulerService extends com.android.server.SystemService publishLocalService(JobSchedulerInternal.class, new LocalService()); // Initialize the job store and set up any persisted jobs mJobs = JobStore.initAndGet(this); mJobStoreLoadedLatch = new CountDownLatch(1); mJobs = JobStore.get(this); mJobs.initAsync(mJobStoreLoadedLatch); mBatteryStateTracker = new BatteryStateTracker(); mBatteryStateTracker.startTracking(); Loading Loading @@ -2112,7 +2116,7 @@ public class JobSchedulerService extends com.android.server.SystemService // And kick off the work to update the affected jobs, using a secondary // thread instead of chugging away here on the main looper thread. new Thread(mJobTimeUpdater, "JobSchedulerTimeSetReceiver").start(); mJobs.runWorkAsync(mJobTimeUpdater); } } } Loading Loading @@ -2150,7 +2154,15 @@ public class JobSchedulerService extends com.android.server.SystemService @Override public void onBootPhase(int phase) { if (PHASE_SYSTEM_SERVICES_READY == phase) { if (PHASE_LOCK_SETTINGS_READY == phase) { // This is the last phase before PHASE_SYSTEM_SERVICES_READY. We need to ensure that // persisted jobs are loaded before we can proceed to PHASE_SYSTEM_SERVICES_READY. try { mJobStoreLoadedLatch.await(); } catch (InterruptedException e) { Slog.e(TAG, "Couldn't wait on job store loading latch"); } } else if (PHASE_SYSTEM_SERVICES_READY == phase) { mConstantsObserver.start(); for (StateController controller : mControllers) { controller.onSystemServicesReady(); Loading
apex/jobscheduler/service/java/com/android/server/job/JobStore.java +28 −1 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ import java.util.List; import java.util.Objects; import java.util.Set; import java.util.StringJoiner; import java.util.concurrent.CountDownLatch; import java.util.function.Consumer; import java.util.function.Predicate; Loading Loading @@ -131,7 +132,7 @@ public final class JobStore { private JobStorePersistStats mPersistInfo = new JobStorePersistStats(); /** Used by the {@link JobSchedulerService} to instantiate the JobStore. */ static JobStore initAndGet(JobSchedulerService jobManagerService) { static JobStore get(JobSchedulerService jobManagerService) { synchronized (sSingletonLock) { if (sSingleton == null) { sSingleton = new JobStore(jobManagerService.getContext(), Loading @@ -147,6 +148,7 @@ public final class JobStore { @VisibleForTesting public static JobStore initAndGetForTesting(Context context, File dataDir) { JobStore jobStoreUnderTest = new JobStore(context, new Object(), dataDir); jobStoreUnderTest.init(); jobStoreUnderTest.clearForTesting(); return jobStoreUnderTest; } Loading Loading @@ -181,10 +183,16 @@ public final class JobStore { mXmlTimestamp = mJobsFile.exists() ? mJobsFile.getLastModifiedTime() : mJobFileDirectory.lastModified(); mRtcGood = (sSystemClock.millis() > mXmlTimestamp); } private void init() { readJobMapFromDisk(mJobSet, mRtcGood); } void initAsync(CountDownLatch completionLatch) { mIoHandler.post(new ReadJobMapFromDiskRunnable(mJobSet, mRtcGood, completionLatch)); } private AtomicFile createJobFile(String baseName) { return createJobFile(new File(mJobFileDirectory, baseName + ".xml")); } Loading @@ -201,6 +209,15 @@ public final class JobStore { return now >= mXmlTimestamp; } /** * Runs any necessary work asynchronously. If this is called after * {@link #initAsync(CountDownLatch)}, this ensures the given work runs after * the JobStore is initialized. */ void runWorkAsync(@NonNull Runnable r) { mIoHandler.post(r); } /** * Find all the jobs that were affected by RTC clock uncertainty at boot time. Returns * parallel lists of the existing JobStatus objects and of new, equivalent JobStatus instances Loading Loading @@ -998,14 +1015,21 @@ public final class JobStore { private final class ReadJobMapFromDiskRunnable implements Runnable { private final JobSet jobSet; private final boolean rtcGood; private final CountDownLatch mCompletionLatch; /** * @param jobSet Reference to the (empty) set of JobStatus objects that back the JobStore, * so that after disk read we can populate it directly. */ ReadJobMapFromDiskRunnable(JobSet jobSet, boolean rtcIsGood) { this(jobSet, rtcIsGood, null); } ReadJobMapFromDiskRunnable(JobSet jobSet, boolean rtcIsGood, @Nullable CountDownLatch completionLatch) { this.jobSet = jobSet; this.rtcGood = rtcIsGood; this.mCompletionLatch = completionLatch; } @Override Loading Loading @@ -1088,6 +1112,9 @@ public final class JobStore { if (needFileMigration) { migrateJobFilesAsync(); } if (mCompletionLatch != null) { mCompletionLatch.countDown(); } } private List<JobStatus> readJobMapImpl(InputStream fis, boolean rtcIsGood, long nowElapsed) Loading