【Android 电量优化】JobScheduler 相关源码分析 ( JobSchedulerService 源码分析 | Android 源码在线网址推荐 )
文章目錄
- 一、JobScheduler 提交任務 schedule 方法源碼分析
- 二、schedule(JobInfo job, int uId) 方法
- 三、scheduleAsPackage 方法
- 四、startTrackingJob 方法
- 五、JobSchedulerService 源碼注釋
上一篇博客 【Android 電量優化】電量優化 ( JobScheduler | JobService | AsyncTask ) 中使用了 JobScheduler 進行電量優化 , 將消耗電量的操作 , 都在設定的條件下集中執行 , 達到減少喚醒硬件的頻率 , 省電的目的 ; 本篇博客中從源碼角度分析上述操作的底層原理 ;
推薦代碼查看網站 :
-
https://www.androidos.net.cn/sourcecode ( 推薦 )
-
http://androidxref.com/
一、JobScheduler 提交任務 schedule 方法源碼分析
JobScheduler 的功能依賴 JobSchedulerService 系統服務完成 ;
使用 JobScheduler 對象提交任務的方法 schedule(jobInfo) , 最終跨進程調用的 JobSchedulerService 中的 int schedule(JobInfo job, int uId) 方法 ;
二、schedule(JobInfo job, int uId) 方法
JobSchedulerService 中的 int schedule(JobInfo job, int uId) 方法解析 :
JobScheduler 的提交任務方法 schedule , 最終調用到 int schedule(JobInfo job, int uId) 方法 , 該調用是跨進程調用的 ;
int schedule(JobInfo job, int uId) 方法 是客戶端的 JobScheduler 調用 schedule 方法執行后的入口函數 , 提供一個 JobInfo job 任務 ; 如果任務已經被安排 , 那么取消該任務 , 并使用新傳入的該 JobInfo job 參數代替原來的任務 ;
三、scheduleAsPackage 方法
在 int schedule(JobInfo job, int uId) 方法中 , 實際調用了 int scheduleAsPackage(JobInfo job, int uId, String packageName, int userId, String tag) 方法 ,
參數說明 :
- job 任務信息
- uId 任務 id
- packageName 包名
- userId 用戶 id ;
在上述 scheduleAsPackage 方法中 , 進行了一系列的狀態判定 , 如包名不能為空 , 當前任務數量沒有超過最大值 MAX_JOBS_PER_APP , 如果上述判定通過 , 就調用 void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) 方法 , 該方法用于追蹤任務狀態 ;
四、startTrackingJob 方法
當我們有一個任務狀態對象 , 我們需要插入到 JobStore 時 , 回調 void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) 方法 , 確保所有相關的控制器知道該狀態 ;
以下控制器需要知道任務狀態 :
- ConnectivityController
- TimeController
- IdleController
- BatteryController
- AppIdleController
- ContentObserverController
- DeviceIdleJobsController
這些控制器都封裝在 List mControllers 成員變量中 , 該集合是 JobSchedulerService 的成員變量 ;
上述控制器在 public JobSchedulerService(Context context) 構造函數中初始化并放入 mControllers 集合中 ;
五、JobSchedulerService 源碼注釋
public class JobSchedulerService extends com.android.server.SystemServiceimplements StateChangedListener, JobCompletedListener {/** 任務的主要集合. */final JobStore mJobs;/** 控制器集合 , 提醒該 Service 服務區更新任務. */List<StateController> mControllers;/*** 初始化系統服務* <p>* 子類必須定義一個單參數的構造函數 , 接收 Context context 參數 , 并且傳遞給父類* </p>** @param context 系統服務上下文對象*/public JobSchedulerService(Context context) {super(context);mHandler = new JobHandler(context.getMainLooper());mConstants = new Constants(mHandler);mJobSchedulerStub = new JobSchedulerStub();mJobs = JobStore.initAndGet(this);// 創建控制器集合// 后續會遍歷該集合 , 遍歷出的元素會調用 maybeStartTrackingJobLocked 方法mControllers = new ArrayList<StateController>();// 網絡控制器mControllers.add(ConnectivityController.get(this));mControllers.add(TimeController.get(this));mControllers.add(IdleController.get(this));// 電量控制器mControllers.add(BatteryController.get(this));mControllers.add(AppIdleController.get(this));mControllers.add(ContentObserverController.get(this));mControllers.add(DeviceIdleJobsController.get(this));}// JobScheduler 的提交任務方法 schedule , 最終調用到該方法// 跨進程方式調用 // 這是客戶端的 JobScheduler 調用 schedule 方法執行后的入口函數 , 提供一個 JobInfo job 任務 ; // 如果任務已經被安排 , 那么取消該任務 , 并使用新傳入的該 JobInfo job 參數代替原來的任務 ; public int schedule(JobInfo job, int uId) {return scheduleAsPackage(job, uId, null, -1, null);}// 實際調用的方法 , 傳入 JobInfo job 任務信息 , uId 任務 id , packageName 包名 , userId 用戶 id , public int scheduleAsPackage(JobInfo job, int uId, String packageName, int userId,String tag) {// 創建任務狀態JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag);// ... 省略 JobStatus toCancel;synchronized (mLock) {// 判定狀態是否合法 , 包名不能為空 , 當前任務數量沒有超過最大值 MAX_JOBS_PER_APPif (ENFORCE_MAX_JOBS && packageName == null) {if (mJobs.countJobsForUid(uId) > MAX_JOBS_PER_APP) {Slog.w(TAG, "Too many jobs for uid " + uId);// 如果多于最大任務數 , 就要拋出異常 throw new IllegalStateException("Apps may not schedule more than "+ MAX_JOBS_PER_APP + " distinct jobs");}}toCancel = mJobs.getJobByUidAndJobId(uId, job.getId());if (toCancel != null) {cancelJobImpl(toCancel, jobStatus);}// 如果上述判定通過 , 就調用該方法 , 該方法用于追蹤任務狀態 startTrackingJob(jobStatus, toCancel);}mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();return JobScheduler.RESULT_SUCCESS;}/*** 當我們有一個任務狀態對象 , 我們需要插入到 JobStore 時 , 回調該方法 , * 確保所有相關的控制器知道它 ;*/private void startTrackingJob(JobStatus jobStatus, JobStatus lastJob) {synchronized (mLock) {// 將本次調度的任務加入到 JobStore mJobs 集合中final boolean update = mJobs.add(jobStatus);if (mReadyToRock) {// 遍歷控制器集合 List<StateController> mControllersfor (int i = 0; i < mControllers.size(); i++) {StateController controller = mControllers.get(i);if (update) {controller.maybeStopTrackingJobLocked(jobStatus, null, true);}// 調用控制器的 maybeStartTrackingJobLocked 函數 controller.maybeStartTrackingJobLocked(jobStatus, lastJob);}}}} }
該代碼路徑為 /frameworks/base/services/core/java/com/android/server/job/JobSchedulerService.java , 點擊鏈接可跳轉查看完整源碼 ;
總結
以上是生活随笔為你收集整理的【Android 电量优化】JobScheduler 相关源码分析 ( JobSchedulerService 源码分析 | Android 源码在线网址推荐 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 电量优化】电量优化 (
- 下一篇: 【Android 电量优化】JobSch