1 調用流程
2 源碼分析
/**
* JobScheduler實體抽象類
*/
abstract class JobScheduler {
//定義接口方法
schedule(JobInfo job);
cancel(int jobId);
}
/**
* JobScheduler實體實作類
*/
class JobSchedulerImpl extends JobScheduler {
IJobScheduler mBinder;
JobSchedulerImpl(IJobScheduler binder) {
mBinder = binder;
}
}
/**
* aidl:是一種android内部程序通信接口的描述語言,通過它我們可以定義程序間的通信接口.
* 以下檔案用于:系統架構層程序 與 應用程式層程序 程序間通信
*/
/**
* 程序1-aidl接口檔案:IJobScheduler.aidl
*/
interface IJobScheduler {
//定義接口方法
schedule(JobInfo job);
cancel(int jobId);
}
/**
* 程序2-aidl接口檔案:IJobService.aidl
*/
interface IJobService {
//定義接口方法
schedule(JobInfo job);
cancel(int jobId);
}
/**
* 系統架構層
* IPC接口:IJobScheduler接口
*/
interface IJobScheduler extends IInterface {
abstract class Stub
()extends Binder implements IJobScheduler
{
Stub() {
this.attachInterface(this, DESCRIPTOR);
}
//接口原生方法
static IJobScheduler asInterface(IBinder obj);
schedule(JobInfo job);
cancel(int jobId);
}
}
/**
* 應用程式層
* IPC接口:IJobService接口
* 這接口用于系統架構 與 實作JobService方法的應用程式代碼通信。最終使用者代碼不直接實作此接口; 使用時(JobService),應用程式的服務實作将擴充IJobService。
*/
interface IJobService extends IInterface {
abstract class Stub()extends Binder implements IJobService {
Stub() {
this.attachInterface(this, DESCRIPTOR);
}
//接口原生方法
static IJobService asInterface(IBinder obj);//将IBinder對象轉換為android.app.job.IJobService接口,如果需要,生成代理。
schedule(JobInfo job);
cancel(int jobId);
}
}
/**
* 核心類
* 系統架構層服務-JobSchedulerService
*/
class JobSchedulerService extends SystemService {
public JobSchedulerService(Context context) {
super(context);
// Create the controllers.控制器
mControllers = new ArrayList<StateController>();
mControllers.add(ConnectivityController.get(this));//wifi\蜂窩控制器
mControllers.add(TimeController.get(this));//逾時時間
mControllers.add(IdleController.get(this));//idle
mControllers.add(BatteryController.get(this));//充電情況
mHandler = new JobHandler(context.getMainLooper());
mJobSchedulerStub = new JobSchedulerStub();
mJobs = JobStore.initAndGet(this);
}
class JobSchedulerStub extends IJobScheduler.Stub {//實作IJobScheduler接口
schedule(JobInfo job) {//實作接口方法
JobSchedulerService.schedule(JobInfo job, int uId);
}
schedule(JobInfo job, int uId) {
JobStatus jobStatus = new JobStatus(job, uId);
cancelJob(uId, job.getId());
startTrackingJob(jobStatus);//當有一個工作狀态對象進入時,我們需要插入JobStore,并確定所有相關的控制器知道此事開始監聽&反應。
mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();//***1.handler發送MSG_CHECK_JOB執行排隊準備執行Jobs消息
return JobScheduler.RESULT_SUCCESS;
}
cancel(int jobId);
}
class JobHandler extends Handler {
void handleMessage(Message message) {
switch (message.what) {
case MSG_JOB_EXPIRED:
break;
case MSG_CHECK_JOB:
maybeQueueReadyJobsForExecutionLockedH();//***2.排隊準備執行Jobs
break;
}
maybeRunPendingJobsH();//***4.執行延遲工作(PendingJobs)
}
}
//排隊準備執行Jobs方法
private void maybeQueueReadyJobsForExecutionLockedH() {
int chargingCount = ;
int idleCount = ;
int backoffCount = ;
int connectivityCount = ;
List<JobStatus> runnableJobs = new ArrayList<JobStatus>();
ArraySet<JobStatus> jobs = mJobs.getJobs();
for (int i = ; i < jobs.size(); i++) {
JobStatus job = jobs.valueAt(i);
if (isReadyToBeExecutedLocked(job)) {//對job的控制狀态判斷并添加到runnableJobs
if (job.getNumFailures() > ) {
backoffCount++;
}
if (job.hasIdleConstraint()) {
idleCount++;
}
if (job.hasConnectivityConstraint() || job.hasUnmeteredConstraint()) {
connectivityCount++;
}
if (job.hasChargingConstraint()) {
chargingCount++;
}
runnableJobs.add(job);
} else if (isReadyToBeCancelledLocked(job)) {
stopJobOnServiceContextLocked(job);//停止
}
}
if (backoffCount > || idleCount >= MIN_IDLE_COUNT || connectivityCount >= MIN_CONNECTIVITY_COUNT ||
chargingCount >= MIN_CHARGING_COUNT || runnableJobs.size() >= MIN_READY_JOBS_COUNT) {
for (int i = ; i < runnableJobs.size(); i++) {
mPendingJobs.add(runnableJobs.get(i));//***3.添加到延遲工作(PendingJobs)中
}
}
}
//執行延遲工作(PendingJobs)
private void maybeRunPendingJobsH() {
synchronized (mJobs) {
Iterator<JobStatus> it = mPendingJobs.iterator();
if (DEBUG) {
Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs.");
}
while (it.hasNext()) {
JobStatus nextPending = it.next();
JobServiceContext availableContext = null;//****5.1 調用JobServiceContext類啟用onServiceConnected()方法執行延遲工作方法
for (int i = ; i < mActiveServices.size(); i++) {
JobServiceContext jsc = mActiveServices.get(i);
final JobStatus running = jsc.getRunningJob();
if (running != null && running.matches(nextPending.getUid(), nextPending.getJobId())) {
availableContext = null;
break;
}
if (jsc.isAvailable()) {
availableContext = jsc;
}
}
if (availableContext != null) {
if (!availableContext.executeRunnableJob(nextPending)) {//***5.2 判斷JobServiceContext的job是否執行
mJobs.remove(nextPending);
}
it.remove();
}
}
}
}
}
/**
* 處理用戶端綁定和生命周期的工作。 喬布斯的一個執行個體上執行一次類。有兩個重要的互動類的JobSchedulerService。執行工作,取消工作。
*/
class JobServiceContext extends IJobCallback.Stub implements ServiceConnection {
/**
* 我們擷取/釋放wakelock
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (!name.equals(mRunningJob.getServiceComponent())) {
mCallbackHandler.obtainMessage(MSG_SHUTDOWN_EXECUTION).sendToTarget();
return;
}
this.service = IJobService.Stub.asInterface(service);//6.建立連接配接擷取Job服務:IJobService.Stub.asInterface
final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);//擷取/釋放WakeLock
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mRunningJob.getTag());
mWakeLock.setWorkSource(new WorkSource(mRunningJob.getUid()));
mWakeLock.setReferenceCounted(false);
mWakeLock.acquire();
mCallbackHandler.obtainMessage(MSG_SERVICE_BOUND).sendToTarget();//Handler發送消息MSG_SERVICE_BOUND
}
private class JobServiceHandler extends Handler {
JobServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message message) {
switch (message.what) {
case MSG_SERVICE_BOUND:
removeOpTimeOut();
handleServiceBoundH();***7.執行handleServiceBoundH()方法
break;
}
}
/**
* 在服務中開啟執行job.
*/
private void handleServiceBoundH() {
service.startJob(mParams);//********8.終點,startJob()開啟執行方法 ———0
}
//檢查如果工作是有效的,正在運作。 假如果工作不能被執行。
boolean executeRunnableJob(JobStatus job) {
return true;
}
}
/**
* 應用程式層服務-JobService
*/
class JobService extends Service {
//使用時,應用程式的服務實作将擴充JobService
static final class JobInterface extends IJobService.Stub {//實作IJobService接口
startJob();
stopJob();
}
IJobService mBinder;
}
/**
* 應用測試-TestJobService
*/
class TestJobService extends JobService {
//關鍵代碼-開啟JobScheduler
public void scheduleJob(JobInfo t) {
JobScheduler tm = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
tm.schedule(t);//JobSchedulerService
}
//關鍵代碼-執行耗時操作
boolean onStartJob(JobParameters params) {//********0.起點,startJob()開啟執行方法 ———8
jobParamsMap.add(params);
if (mActivity != null) {
mActivity.onReceivedStartJob(params);
//執行耗時操作:下載下傳檔案———
}
return false;
}
//停止操作
boolean onStopJob(JobParameters params) {
// Stop tracking these job parameters, as we've 'finished' executing.
jobParamsMap.remove(params);
if (mActivity != null) {
mActivity.onReceivedStopJob();
}
return true;
}
}
/**
* 系統程序
* 開啟系統後Zygote程序(Linux核心)啟動系統程序SystemServer,開啟一些列的關鍵服務:AMS/PMS/WMS/JobSchedulerService
*/
class SystemServer {
mSystemServiceManager.startService(JobSchedulerService.class);//通過反射啟動Service并添加到Service集合中(864行)
}
/**
* Context/ContextImpl 在系統架構層與應用程式層程序間綁定Binder,實作程序間通信
*/
class ContextImpl {
//開啟服務
startService(Intent service) {
return startServiceCommon(service, mUser);
}
startServiceCommon(Intent service, UserHandle user) {
ComponentName cn = ActivityManagerNative.getDefault().startService(mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
return cn;
}
}
/**
* 應用程式層,服務端:調用服務
*/
class TestJobService extends JobService {
JobScheduler jobs = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);//擷取系統程序getSystemService = JobSchedulerService. JobSchedulerStub
jobs.schedule(t);//調用接口方法
}
/**
* 應用程式層,用戶端:調用服務
*/
class MainActivity extends Activity {
onCreate(Bundle savedInstanceState) {
//開啟服務
Intent startServiceIntent = new Intent(this, TestJobService.class);
startServiceIntent.putExtra("messenger", new Messenger(mHandler));
startService(startServiceIntent);//要求給定應用程式服務啟動
}
}