Fields Summary |
---|
private static final String | TAG |
private static final String | ACTION_JOB_EXPIRED |
private static final String | ACTION_JOB_DELAY_EXPIRED |
private final android.app.PendingIntent | mDeadlineExpiredAlarmIntentSet an alarm for the next job expiry. |
private final android.app.PendingIntent | mNextDelayExpiredAlarmIntentSet an alarm for the next job delay expiry. This |
private long | mNextJobExpiredElapsedMillis |
private long | mNextDelayExpiredElapsedMillis |
private android.app.AlarmManager | mAlarmService |
private final List | mTrackedJobsList of tracked jobs, sorted asc. by deadline |
private static TimeController | mSingletonSingleton. |
private final android.content.BroadcastReceiver | mAlarmExpiredReceiver |
Methods Summary |
---|
private boolean | canStopTrackingJob(JobStatus job)Determines whether this controller can stop tracking the given job.
The controller is no longer interested in a job once its time constraint is satisfied, and
the job's deadline is fulfilled - unlike other controllers a time constraint can't toggle
back and forth.
return (!job.hasTimingDelayConstraint() ||
job.timeDelayConstraintSatisfied.get()) &&
(!job.hasDeadlineConstraint() ||
job.deadlineConstraintSatisfied.get());
|
private synchronized void | checkExpiredDeadlinesAndResetAlarm()Checks list of jobs for ones that have an expired deadline, sending them to the JobScheduler
if so, removing them from this list, and updating the alarm for the next expiry time.
long nextExpiryTime = Long.MAX_VALUE;
final long nowElapsedMillis = SystemClock.elapsedRealtime();
Iterator<JobStatus> it = mTrackedJobs.iterator();
while (it.hasNext()) {
JobStatus job = it.next();
if (!job.hasDeadlineConstraint()) {
continue;
}
final long jobDeadline = job.getLatestRunTimeElapsed();
if (jobDeadline <= nowElapsedMillis) {
job.deadlineConstraintSatisfied.set(true);
mStateChangedListener.onRunJobNow(job);
it.remove();
} else { // Sorted by expiry time, so take the next one and stop.
nextExpiryTime = jobDeadline;
break;
}
}
setDeadlineExpiredAlarm(nextExpiryTime);
|
private synchronized void | checkExpiredDelaysAndResetAlarm()Handles alarm that notifies us that a job's delay has expired. Iterates through the list of
tracked jobs and marks them as ready as appropriate.
final long nowElapsedMillis = SystemClock.elapsedRealtime();
long nextDelayTime = Long.MAX_VALUE;
boolean ready = false;
Iterator<JobStatus> it = mTrackedJobs.iterator();
while (it.hasNext()) {
final JobStatus job = it.next();
if (!job.hasTimingDelayConstraint()) {
continue;
}
final long jobDelayTime = job.getEarliestRunTime();
if (jobDelayTime <= nowElapsedMillis) {
job.timeDelayConstraintSatisfied.set(true);
if (canStopTrackingJob(job)) {
it.remove();
}
if (job.isReady()) {
ready = true;
}
} else { // Keep going through list to get next delay time.
if (nextDelayTime > jobDelayTime) {
nextDelayTime = jobDelayTime;
}
}
}
if (ready) {
mStateChangedListener.onControllerStateChanged();
}
setDelayExpiredAlarm(nextDelayTime);
|
public void | dumpControllerState(java.io.PrintWriter pw)
final long nowElapsed = SystemClock.elapsedRealtime();
pw.println("Alarms (" + SystemClock.elapsedRealtime() + ")");
pw.println(
"Next delay alarm in " + (mNextDelayExpiredElapsedMillis - nowElapsed)/1000 + "s");
pw.println("Next deadline alarm in " + (mNextJobExpiredElapsedMillis - nowElapsed)/1000
+ "s");
pw.println("Tracking:");
for (JobStatus ts : mTrackedJobs) {
pw.println(String.valueOf(ts.hashCode()).substring(0, 3) + ".."
+ ": (" + (ts.hasTimingDelayConstraint() ? ts.getEarliestRunTime() : "N/A")
+ ", " + (ts.hasDeadlineConstraint() ?ts.getLatestRunTimeElapsed() : "N/A")
+ ")");
}
|
private void | ensureAlarmService()
if (mAlarmService == null) {
mAlarmService = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
}
|
public static synchronized com.android.server.job.controllers.TimeController | get(com.android.server.job.JobSchedulerService jms)
if (mSingleton == null) {
mSingleton = new TimeController(jms, jms.getContext());
}
return mSingleton;
|
private long | maybeAdjustAlarmTime(long proposedAlarmTimeElapsedMillis)
final long earliestWakeupTimeElapsed = SystemClock.elapsedRealtime();
if (proposedAlarmTimeElapsedMillis < earliestWakeupTimeElapsed) {
return earliestWakeupTimeElapsed;
}
return proposedAlarmTimeElapsedMillis;
|
public synchronized void | maybeStartTrackingJob(JobStatus job)Check if the job has a timing constraint, and if so determine where to insert it in our
list.
if (job.hasTimingDelayConstraint() || job.hasDeadlineConstraint()) {
maybeStopTrackingJob(job);
ListIterator<JobStatus> it = mTrackedJobs.listIterator(mTrackedJobs.size());
while (it.hasPrevious()) {
JobStatus ts = it.previous();
if (ts.getLatestRunTimeElapsed() < job.getLatestRunTimeElapsed()) {
// Insert
break;
}
}
it.add(job);
maybeUpdateAlarms(
job.hasTimingDelayConstraint() ? job.getEarliestRunTime() : Long.MAX_VALUE,
job.hasDeadlineConstraint() ? job.getLatestRunTimeElapsed() : Long.MAX_VALUE);
}
|
public synchronized void | maybeStopTrackingJob(JobStatus job)When we stop tracking a job, we only need to update our alarms if the job we're no longer
tracking was the one our alarms were based off of.
Really an == comparison should be enough, but why play with fate? We'll do <=.
if (mTrackedJobs.remove(job)) {
checkExpiredDelaysAndResetAlarm();
checkExpiredDeadlinesAndResetAlarm();
}
|
private void | maybeUpdateAlarms(long delayExpiredElapsed, long deadlineExpiredElapsed)
if (delayExpiredElapsed < mNextDelayExpiredElapsedMillis) {
setDelayExpiredAlarm(delayExpiredElapsed);
}
if (deadlineExpiredElapsed < mNextJobExpiredElapsedMillis) {
setDeadlineExpiredAlarm(deadlineExpiredElapsed);
}
|
private void | setDeadlineExpiredAlarm(long alarmTimeElapsedMillis)Set an alarm with the {@link android.app.AlarmManager} for the next time at which a job's
deadline will expire.
This alarm will wake up the phone.
alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
mNextJobExpiredElapsedMillis = alarmTimeElapsedMillis;
updateAlarmWithPendingIntent(mDeadlineExpiredAlarmIntent, mNextJobExpiredElapsedMillis);
|
private void | setDelayExpiredAlarm(long alarmTimeElapsedMillis)Set an alarm with the {@link android.app.AlarmManager} for the next time at which a job's
delay will expire.
This alarm will not wake up the phone.
alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);
mNextDelayExpiredElapsedMillis = alarmTimeElapsedMillis;
updateAlarmWithPendingIntent(mNextDelayExpiredAlarmIntent, mNextDelayExpiredElapsedMillis);
|
private void | updateAlarmWithPendingIntent(android.app.PendingIntent pi, long alarmTimeElapsed)
ensureAlarmService();
if (alarmTimeElapsed == Long.MAX_VALUE) {
mAlarmService.cancel(pi);
} else {
if (DEBUG) {
Slog.d(TAG, "Setting " + pi.getIntent().getAction() + " for: " + alarmTimeElapsed);
}
mAlarmService.set(AlarmManager.ELAPSED_REALTIME, alarmTimeElapsed, pi);
}
|