設(shè)置了 Idle 約束條件的 Job 執(zhí)行一次后不會被移除
/**
* Policy: we decide that we're "idle" if the device has been unused
* screen off or dreaming for at least this long
* 息屏或進(jìn)入 dreaming 狀態(tài) 71min 后被認(rèn)為是 idle 狀態(tài)
*/
private static final long INACTIVITY_IDLE_THRESHOLD = 71 * 60 * 1000; // millis; 71 min
private static final long IDLE_WINDOW_SLOP = 5 * 60 * 1000; // 5 minute window, to be nice
一倒庵、調(diào)用流程
public JobSchedulerService(Context context) {
super(context);
// Create the controllers.
mControllers = new ArrayList<StateController>();
mControllers.add(ConnectivityController.get(this));
mControllers.add(TimeController.get(this));
mControllers.add(IdleController.get(this));
mControllers.add(BatteryController.get(this));
mHandler = new JobSchedulerService.JobHandler(context.getMainLooper());
mJobSchedulerStub = new JobSchedulerService.JobSchedulerStub();
mJobs = JobStore.initAndGet(this);
}
|
public static IdleController get(JobSchedulerService service) {
synchronized (sCreationLock) {
if (sController == null) {
sController = new IdleController(service, service.getContext());
}
return sController;
}
}
|
private IdleController(StateChangedListener stateChangedListener, Context context) {
super(stateChangedListener, context);
initIdleStateTracking();
}
二炫刷、初始化 IdlenessTracker
/**
* Idle state tracking, and messaging with the task manager when
* significant state changes occur
*/
private void initIdleStateTracking() {
mIdleTracker = new IdleController.IdlenessTracker();
// 注冊一些需要監(jiān)聽的廣播
mIdleTracker.startTracking();
}
public IdlenessTracker() {
mAlarm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(ACTION_TRIGGER_IDLE)
.setPackage("android")
.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mIdleTriggerIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
// At boot we presume that the user has just "interacted" with the
// device in some meaningful way.
mIdle = false;
}
public void startTracking() {
IntentFilter filter = new IntentFilter();
// Screen state
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
// Dreaming state
filter.addAction(Intent.ACTION_DREAMING_STARTED);
filter.addAction(Intent.ACTION_DREAMING_STOPPED);
// Debugging/instrumentation
filter.addAction(ACTION_TRIGGER_IDLE);
mContext.registerReceiver(this, filter);
}
三浑玛、添加需要追蹤的 Job
public void maybeStartTrackingJob(JobStatus taskStatus) {
if (taskStatus.hasIdleConstraint()) {
synchronized (mTrackedTasks) {
// 把 Job 添加入追蹤列表顾彰,為 Job 設(shè)置當(dāng)前的設(shè)備 idle 狀態(tài)
mTrackedTasks.add(taskStatus);
taskStatus.idleConstraintSatisfied.set(mIdleTracker.isIdle());
}
}
}
四、移除不再需要追蹤的 Job
public void maybeStopTrackingJob(JobStatus taskStatus) {
synchronized (mTrackedTasks) {
mTrackedTasks.remove(taskStatus);
}
}
五、通過 Receiver 驅(qū)動 Job 執(zhí)行的流程
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(Intent.ACTION_SCREEN_ON) || action.equals(Intent.ACTION_DREAMING_STOPPED)) {
// possible transition to not-idle
if (mIdle) {
// 進(jìn)入 idle 狀態(tài)后被喚醒
// 設(shè)備已被喚醒书在,取消 71min 后要發(fā)送的廣播
mAlarm.cancel(mIdleTriggerIntent);
mIdle = false;
// 設(shè)置追蹤列表中 Job 的 idle 約束條件設(shè)置為 false
// 觸發(fā) JobSchedulerService 檢查所有滿足執(zhí)行條件的 Job,根據(jù)策略決定是否放入 mPendingJobs栏账,隨后執(zhí)行 mPendingJobs 中的 Job
reportNewIdleState(mIdle);
}
} else if (action.equals(Intent.ACTION_SCREEN_OFF) || action.equals(Intent.ACTION_DREAMING_STARTED)) {
// when the screen goes off or dreaming starts, we schedule the
// alarm that will tell us when we have decided the device is truly idle.
final long nowElapsed = SystemClock.elapsedRealtime();
final long when = nowElapsed + INACTIVITY_IDLE_THRESHOLD;
// 71min 后挡爵,AlarmManager 要在 5min 內(nèi)發(fā)出廣播,通知進(jìn)入 idle 狀態(tài)
mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, IDLE_WINDOW_SLOP, mIdleTriggerIntent);
} else if (action.equals(ACTION_TRIGGER_IDLE)) {
// idle time starts now
if (!mIdle) {
// 由非 idle 狀態(tài)進(jìn)入 idle 狀態(tài)
mIdle = true;
// 設(shè)置追蹤列表中 Job 的 idle 約束條件設(shè)置為 true,
// 觸發(fā) JobSchedulerService 檢查所有滿足執(zhí)行條件的 Job涣雕,根據(jù)策略決定是否放入 mPendingJobs闭翩,隨后執(zhí)行 mPendingJobs 中的 Job
reportNewIdleState(mIdle);
}
}
}
void reportNewIdleState(boolean isIdle) {
synchronized (mTrackedTasks) {
for (JobStatus task : mTrackedTasks) {
task.idleConstraintSatisfied.set(isIdle);
}
}
// 觸發(fā) JobSchedulerService 檢查所有滿足執(zhí)行條件的 Job,根據(jù)策略決定是否放入 mPendingJobs兑障,隨后執(zhí)行 mPendingJobs 中的 Job
mStateChangedListener.onControllerStateChanged();
}
六蕉汪、驅(qū)動 JobShedulerService 執(zhí)行 Job
public void onControllerStateChanged() {
mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
}