美文网首页Android 源码分析
JobSchedulerService 源码分析—— IdleC

JobSchedulerService 源码分析—— IdleC

作者: _夜 | 来源:发表于2017-11-23 19:10 被阅读0次

    设置了 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<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();
        // 注册一些需要监听的广播
        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 源码分析—— IdleC

        本文链接:https://www.haomeiwen.com/subject/uhhtbxtx.html