JobSchedulerService

1 成员变量

    /** Master list of jobs. */
    final JobStore mJobs;  //job list
    /** Tracking the standby bucket state of each app */
    final StandbyTracker mStandbyTracker;
    /**
     * Track Services that have currently active or pending jobs. The index is provided by
     * {@link JobStatus#getServiceToken()}
     */
    final List mActiveServices = new ArrayList<>();
    /** List of controllers that will notify this service of updates to jobs. */
    final List mControllers;
    /**
     * Queue of pending jobs. The JobServiceContext class will receive jobs from this list
     * when ready to execute them.
     */
    final ArrayList mPendingJobs = new ArrayList<>();
    /** Need directly for receiving thermal events */
    private IThermalService mThermalService;

    final JobHandler mHandler;
    /**
     * Whether to use heartbeats or rolling window for quota management. True will use
     * heartbeats, false will use a rolling window.
     */
     public boolean USE_HEARTBEATS = DEFAULT_USE_HEARTBEATS; //默认未false
            // Max job counts for screen on / off, for each memory trim level.
     final MaxJobCountsPerMemoryTrimLevel MAX_JOB_COUNTS_SCREEN_ON =
                new MaxJobCountsPerMemoryTrimLevel(
                        new MaxJobCounts(
                                8, "max_job_total_on_normal",
                                6, "max_job_max_bg_on_normal",
                                2, "max_job_min_bg_on_normal"),
                        new MaxJobCounts(
                                8, "max_job_total_on_moderate",
                                4, "max_job_max_bg_on_moderate",
                                2, "max_job_min_bg_on_moderate"),
                        new MaxJobCounts(
                                5, "max_job_total_on_low",
                                1, "max_job_max_bg_on_low",
                                1, "max_job_min_bg_on_low"),
                        new MaxJobCounts(
                                5, "max_job_total_on_critical",
                                1, "max_job_max_bg_on_critical",
                                1, "max_job_min_bg_on_critical"));

    final MaxJobCountsPerMemoryTrimLevel MAX_JOB_COUNTS_SCREEN_OFF =
                new MaxJobCountsPerMemoryTrimLevel(
                        new MaxJobCounts(
                                10, "max_job_total_off_normal",
                                6, "max_job_max_bg_off_normal",
                                2, "max_job_min_bg_off_normal"),
                        new MaxJobCounts(
                                10, "max_job_total_off_moderate",
                                4, "max_job_max_bg_off_moderate",
                                2, "max_job_min_bg_off_moderate"),
                        new MaxJobCounts(
                                5, "max_job_total_off_low",
                                1, "max_job_max_bg_off_low",
                                1, "max_job_min_bg_off_low"),
                        new MaxJobCounts(
                                5, "max_job_total_off_critical",
                                1, "max_job_max_bg_off_critical",
                                1, "max_job_min_bg_off_critical"));

2 mJobs = JobStore.initAndGet(this);

//读取/data/system/job/jobs.xml中的persist的job任务


    
    
    
        PERIODIC_TASK
    



    
    
    


 
    
    
    

constraints: 满足条件
periodic:job的周期

3 schedule

-> scheduleAsPackage
        -> 判断isAppStartModeDisabled,确认是否允许后台执行.
        -> 根据jobinfo创建jobStatus
        -> startTrackingJobLocked
            // If the job is immediately ready to run, then we can just immediately
            // put it in the pending list and try to schedule it.  This is especially
            // important for jobs with a 0 deadline constraint, since they will happen a fair
            // amount, we want to handle them as quickly as possible, and semantically we want to
            // make sure we have started holding the wake lock for the job before returning to
            // the caller.
            // If the job is not yet ready to run, there is nothing more to do -- we are
            // now just waiting for one of its controllers to change state and schedule
            // the job appropriately.
        -> isReadyToBeExecutedLocked
            -> maybeRunPendingJobsLocked 
         or -> evaluateControllerStatesLocked

3.1 判断是否可以执行job

/**
     * Criteria for moving a job into the pending queue:
     *      - It's ready.
     *      - It's not pending.
     *      - It's not already running on a JSC.
     *      - Temperture is too high, and don't run job of request network and proity
     *      - The user that requested the job is running.
     *      - The job's standby bucket has come due to be runnable.
     *      - The component is enabled and runnable.
     */
    private boolean isReadyToBeExecutedLocked(JobStatus job)

3.2 决定是否实际需要执行

/**
     * ** Reconcile jobs in the pending queue against available execution contexts.**
     * A controller can force a job into the pending queue even if it's already running, but
     * here is where we decide whether to actually execute it.
     */
    void maybeRunPendingJobsLocked() {
        /**
         * Takes jobs from pending queue and runs them on available contexts.
         * If no contexts are available, preempts lower priority jobs to
         * run higher priority ones.
         * Lock on mJobs before calling this function.
         */
        assignJobsToContextsLocked//核心逻辑

3.3 assignJobsToContextsLocked

private void assignJobsToContextsInternalLocked() {
        if (DEBUG) {
            Slog.d(TAG, printPendingQueueLocked());
        }

        final JobPackageTracker tracker = mService.mJobPackageTracker;
        final List pendingJobs = mService.mPendingJobs;//获取pending jobs
        final List activeServices = mService.mActiveServices;//获取active jobservicecontext
        final List controllers = mService.mControllers;//获取状态控制器

        updateMaxCountsLocked();//更新最大counts

        // To avoid GC churn, we recycle the arrays.
        JobStatus[] contextIdToJobMap = mRecycledAssignContextIdToJobMap;//实际是索引ActiveServices的状态
        boolean[] slotChanged = mRecycledSlotChanged;
        int[] preferredUidForContext = mRecycledPreferredUidForContext;


        // Initialize the work variables and also count running jobs.
        mJobCountTracker.reset(
                mMaxJobCounts.getMaxTotal(),
                mMaxJobCounts.getMaxBg(),
                mMaxJobCounts.getMinBg());

        for (int i=0; i= nextPending.lastEvaluatedPriority) {
                    continue;
                }

                // TODO lastEvaluatedPriority should be evaluateJobPriorityLocked. (double check it)
                if (minPriorityForPreemption > nextPending.lastEvaluatedPriority) {
                    minPriorityForPreemption = nextPending.lastEvaluatedPriority;
                    selectedContextId = j;
                    // In this case, we're just going to preempt a low priority job, we're not
                    // actually starting a job, so don't set startingJob.
                }
            }
            if (selectedContextId != -1) {
                contextIdToJobMap[selectedContextId] = nextPending;
                slotChanged[selectedContextId] = true;
            }
            if (startingJob) {
                // Increase the counters when we're going to start a job.
                mJobCountTracker.onStartingNewJob(isPendingFg);
            }
        }
        if (DEBUG) {
            Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs final"));
        }

        mJobCountTracker.logStatus();

        tracker.noteConcurrency(mJobCountTracker.getTotalRunningJobCountToNote(),
                mJobCountTracker.getFgRunningJobCountToNote());

        for (int i=0; i

你可能感兴趣的:(JobSchedulerService)