Merge "Make persisted job loading asynchronous."
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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. */
|
||||
@@ -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();
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(),
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"));
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user