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();
}

你可能感兴趣的:(JobSchedulerService 源码分析—— IdleController (API 21))