天天看點

【Android 電量優化】JobScheduler 源碼分析 ( JobServiceContext 源碼分析 | 閉環操作總結 | 使用者送出任務 | 廣播接收者接受相關廣播觸發任務執行 )★

文章目錄

  • 一、JobServiceContext 引入
  • 二、JobServiceContext 源碼分析
  • 三、使用者在應用層如何使用 JobScheduler
  • 四、使用者送出任務
  • 五、廣播接收者監聽廣播觸發 JobService 執行任務

推薦代碼檢視網站 :

  • https://www.androidos.net.cn/sourcecode ( 推薦 )
  • http://androidxref.com/

一、JobServiceContext 引入

上一篇部落格 【Android 電量優化】JobScheduler 相關源碼分析 ( JobSchedulerService 源碼分析 | 任務檢查 | 任務執行 ) 中在 JobSchedulerService 中的 assignJobsToContextsLocked 方法中 , 有如下代碼 :

// /frameworks/base/services/core/java/com/android/server/job/JobSchedulerService.java 中的代碼
mActiveServices.get(i).executeRunnableJob(pendingJob)
           

mActiveServices 就是 JobServiceContext 集合 , 上述方法調用了 JobServiceContext 的 executeRunnableJob 方法 , 目的是要執行傳入的 pendingJob 任務 ;

二、JobServiceContext 源碼分析

在 JobServiceContext 類的 executeRunnableJob 方法的作用 : 該方法傳遞一個 Job 任務給 JobServiceContext 執行 , 調用者需要先檢查如下兩個條件 :

  • 目前是否有運作中的任務 , getRunningJob() 必須為空 ;
  • 同時還需要確定該 JobServiceContext 上下文是有效的 ;

在該方法中建立了 Intent , 并使用該意圖綁定了一個服務 , 這個服務就是建立 JobInfo 時 , 開發者自定義的 JobService 服務 , 送出任務時需要送出該服務 ;

綁定服務 , 執行 JobService 服務中的 onStartJob 方法

截止到此處 , 基本 JobScheduler 整個運作的閉環 , 進行了簡單的源碼分析 , 沒有深入分析 , 僅限于簡單了解 ;

public class JobServiceContext extends IJobCallback.Stub implements ServiceConnection {

	// ... 

    /**
     * 該方法傳遞一個 Job 任務給 JobServiceContext 執行 . 
     * 調用者需要先檢查目前是否有運作中的任務 , getRunningJob() 為空 ; 
     * 并且確定該 JobServiceContext 上下文是有效的 ; 
     * 
     * @param 将要運作的任務的狀态 ;
     * @return True 如果該任務是有效的 , 并且正在執行 ; 
     * 		   False 如果該任務不能被執行 ; 
     */
    boolean executeRunnableJob(JobStatus job) {
        synchronized (mLock) {
            // ...
            
			// 此處建立了 Intent , 并使用該意圖綁定了一個服務 
            final Intent intent = new Intent().setComponent(job.getServiceComponent());
            // 使用上述意圖 Intent 綁定服務 
            // 這個服務就是建立 JobInfo 時 , 開發者自定義的 JobService 服務 , 送出任務時需要送出該服務  
            boolean binding = mContext.bindServiceAsUser(intent, this,
                    Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND,
                    new UserHandle(job.getUserId()));
            // ... 
            try {
             	// 啟動服務 , 會執行 JobService 服務中的 onStartJob 方法
                mBatteryStats.noteJobStart(job.getBatteryName(), job.getSourceUid());
            } catch (RemoteException e) {
                // Whatever.
            }
            mJobPackageTracker.noteActive(job);
            mAvailable = false;
            return true;
        }
    }

}
           
該代碼路徑為 /frameworks/base/services/core/java/com/android/server/job/JobServiceContext.java , 點選連結可跳轉檢視完整源碼 ;

三、使用者在應用層如何使用 JobScheduler

先講解使用者在應用層如何使用 JobScheduler :

在 【Android 電量優化】電量優化 ( JobScheduler | JobService | AsyncTask ) 部落格中 , 講解了 JobScheduler 如何使用 ;

  • 擷取服務 : 首先擷取系統的 JobScheduler 服務 , 就是之前分析的 JobSchedulerService 類 ;
  • 建立任務 : 建立 JobInfo 任務資訊 , 使用 JobScheduler 送出該任務 ; mJobScheduler.schedule(jobInfo) ;
  • 自定義 JobService : 開發者在應用中自定義 JobService 服務 ;
  • 服務執行 : 系統會在合适的時間調用 JobService 服務的 boolean onStartJob(JobParameters params) 方法 ;

其中涉及到兩個入口 , 一個是使用者送出任務 , 另一個是系統在某個時間回調 JobService 服務中的開始執行任務方法 ;

主要針對上述兩個入口進行分析 ;

使用者送出任務的驅動事件是開發者寫的送出任務的代碼 ;

系統回調 JobService 服務的驅動事件 , 是使用者對手機的操作 , 如插拔電源線 , 切換 WIFI 網絡等操作 , 這些操作觸發廣播 , 相應廣播接收者收到這些廣播 , 就會觸發一系列相關的操作 ;

四、使用者送出任務

分析使用者送出任務 :

【Android 電量優化】JobScheduler 相關源碼分析 ( JobSchedulerService 源碼分析 | Android 源碼線上網址推薦 ) 部落格中講解了如下内容 :

  • JobScheduler 送出任務的方法 schedule(jobInfo) , 最終調用的是 JobSchedulerService 中的 schedule 方法 ;
  • 在 schedule 方法中調用了 scheduleAsPackage 方法 , 傳入任務相關資訊 , 進行了一系列的狀态判定 ;
  • 在 scheduleAsPackage 方法中調用 startTrackingJob 方法 , 該方法中周遊所有的狀态控制器 , 確定所有相關的控制器知道該狀态 ;

【Android 電量優化】JobScheduler 相關源碼分析 ( ConnectivityController 底層源碼分析 | 構造函數 | 追蹤任務更新 | 注冊接收者監聽連接配接變化 ) 部落格中接着上面的部落格繼續分析 :

  • 在 startTrackingJob() 方法中 , 調用狀态控制器 StateController 的 maybeStartTrackingJobLocked 方法 , 該方法的作用是更新所有對應的狀态控制器監聽的任務 ;

五、廣播接收者監聽廣播觸發 JobService 執行任務

廣播接收者監聽廣播 : 這是觸發系統回調 JobService 服務的入口 ;

  • 注冊廣播接收者 : ConnectivityController 中注冊了廣播接收者 , 用于監聽 ConnectivityManager.CONNECTIVITY_ACTION 廣播 , 這是網絡狀态改變後發出的廣播 ;
  • 廣播接收者收到網絡狀态改變的廣播後 , 會調用 updateTrackedJobs(-1) 方法 ;
  • 該方法會更新所有對網絡狀态敏感的任務 , 例如有的任務要求在 WIFI 條件下執行 , 此時就會觸發該任務的狀态改變 ;
  • updateTrackedJobs 方法中又會調用 狀态改變監聽器 mStateChangedListener 的 onControllerStateChanged 方法 ;
  • 狀态改變監聽器 mStateChangedListener 就是 JobSchedulerService 類 ;
  • 在實作的 StateChangedListener 接口的 onControllerStateChanged() 回調方法中 , 使用 JobHandler mHandler 發送了 MSG_CHECK_JOB 消息 ;
  • 在 JobHandler 中接收上述消息 , 并檢查任務 , 最終調用 maybeRunPendingJobsH() 方法 , 執行任務 ;
  • 在 maybeRunPendingJobsH 方法中 , 調用 assignJobsToContextsLocked , 執行任務 ;
  • 在 assignJobsToContextsLocked 方法中 , 最終調用了 JobServiceContext 執行 executeRunnableJob(pendingJob) 方法 , 用于執行 pendingJob 任務 ;
  • 最終在 JobServiceContext 中綁定使用者自定義的 JobService , 開始執行任務 , 會自動回調下面代碼中的 onStartJob 方法 ;
public class BpJobService extends JobService {
    @Override
    public boolean onStartJob(JobParameters params) {
        // 啟動 AsyncTask 異步任務處理工作
        new JobAsyncTask().execute(params);
        return false;
    }
    // ... 省略部分代碼
}
           
  • /frameworks/base/services/core/java/com/android/server/job/JobSchedulerService.java
  • frameworks/base/services/core/java/com/android/server/job/controllers/ConnectivityController.java
  • /frameworks/base/services/core/java/com/android/server/job/JobServiceContext.java