JobSchedulerService|JobSchedulerService 源码分析—— IdleController (API 21)

设置了 Idle 约束条件的 Job 执行一次后不会被移除

/** * Policy: we decide that we're "idle" if the device has been unused * screen off or dreaming for at least this long * 息屏或进入 dreaming 状态 71min 后被认为是 idle 状态 */ 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

一、调用流程
public JobSchedulerService(Context context) { super(context); // Create the controllers. mControllers = new ArrayList(); 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(); // 注册一些需要监听的广播 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 设置当前的设备 idle 状态 mTrackedTasks.add(taskStatus); taskStatus.idleConstraintSatisfied.set(mIdleTracker.isIdle()); } } }

四、移除不再需要追踪的 Job
public void maybeStopTrackingJob(JobStatus taskStatus) { synchronized (mTrackedTasks) { mTrackedTasks.remove(taskStatus); } }

五、通过 Receiver 驱动 Job 执行的流程
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) { // 进入 idle 状态后被唤醒 // 设备已被唤醒,取消 71min 后要发送的广播 mAlarm.cancel(mIdleTriggerIntent); mIdle = false; // 设置追踪列表中 Job 的 idle 约束条件设置为 false // 触发 JobSchedulerService 检查所有满足执行条件的 Job,根据策略决定是否放入 mPendingJobs,随后执行 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 内发出广播,通知进入 idle 状态 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 状态进入 idle 状态 mIdle = true; // 设置追踪列表中 Job 的 idle 约束条件设置为 true, // 触发 JobSchedulerService 检查所有满足执行条件的 Job,根据策略决定是否放入 mPendingJobs,随后执行 mPendingJobs 中的 Job reportNewIdleState(mIdle); } } }

void reportNewIdleState(boolean isIdle) { synchronized (mTrackedTasks) { for (JobStatus task : mTrackedTasks) { task.idleConstraintSatisfied.set(isIdle); } } // 触发 JobSchedulerService 检查所有满足执行条件的 Job,根据策略决定是否放入 mPendingJobs,随后执行 mPendingJobs 中的 Job mStateChangedListener.onControllerStateChanged(); }

六、驱动 JobShedulerService 执行 Job
public void onControllerStateChanged() { mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget(); }

    推荐阅读