1.概述
Android版本:5.1.1
2.服务端JobSchedulerService初始化
1. 初始化StateController
StateController是job运行的触发器,只有系统的各个state满足某个job的条件时,job才能有机会运行起来。
这些state包括Battery、Connectivity、Idle和Time。他们大部分是在监听系统的某些广播,并进一步组织状态,并在自己状态改变时通知JobSchedulerService去start或者stop某些job。
2. JobHandler
这里的context是system context,所以这里的looper是system_server进程的main looper,所以这个Handler是在system_server进程的主线程中运行。
mHandler = new JobHandler(context.getMainLooper())
3. JobSchedulerStub
它是IJobScheduler的服务端,不过真正的实现都在JobSchedulerService,不过在call JobSchedulerService的具体方法前,它也会做些预处理。
在onStart阶段,会publish这个服务。
final class JobSchedulerStub extends IJobScheduler.Stub
mJobSchedulerStub = new JobSchedulerStub();
public void onStart() {
publishBinderService(Context.JOB_SCHEDULER_SERVICE, mJobSchedulerStub);
}
4. JobStore
它存储所有的JobStatus,本质就是一个ArraySet。
它从jobs.xml中读取上次开机遗留的需要继续处理的job,还可以动态地增加和删除由app_proc进程schdule和cancel的job。
mJobs = JobStore.initAndGet(this);
File systemDir = new File(dataDir, "system");
File jobDir = new File(systemDir, "job");
jobDir.mkdirs();
mJobsFile = new AtomicFile(new File(jobDir, "jobs.xml"));
3.客户端shedule a job
标准的Binder通讯,接口是IJobScheduler.aidl
核心方法是schedule和cancel。
Client端:JobSchedulerImpl运行在app_proc中
Server端:JobSchedulerStub,但真正实现是JobSchedulerService,运行在system_server进程中。
interface IJobScheduler {
int schedule(in JobInfo job);
void cancel(int jobId);
void cancelAll();
List<JobInfo> getAllPendingJobs();
}
以schdule为例,它只做两件事,第一是把这个JobInfo增加到mJobs中,第二是把它交给各个StateController去关注state change是否会导致这个job的开始或结束状态变化。之后,就静候state change了。
4.StateController发生变化触发Job运行
这里有必要介绍下各个StateController……
来说下它和JobSchedulerService的交互。
JobSchedulerService拥有所有StateController,所以它可以直接控制StateController。
StateController通知JobSchedulerService则是通过回调的方式,接口是StateChangedListener。JobSchedulerService实现了这个接口,并在初始化StateController时传递到StateController。
List<StateController> mControllers;
class JobSchedulerService implements StateChangedListener
5.JobServiceContext与JobService交互运行job
JobSchedulerService(以后简称为JSS)在条件合适的时候,会真正地通知JobServiceContext(以后简称为JSC)运行某个job。
JSC不是唯一的,它一共有三个实例。每个实例在同一时刻只能运行一个job,所以意味着系统最多只能同时运行三个job。
JSC也有个Handler(JobServiceHandler),也运行在system_server的主线程中。
/** The number of concurrent jobs we run at one time. */
private static final int MAX_JOB_CONTEXTS_COUNT = 3;
// Create the "runners".
for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
mActiveServices.add(
new JobServiceContext(this, mBatteryStats,
getContext().getMainLooper()));
}
在JSC和JobService的交互过程中,JSC是作为client端,而JobService。也是典型的Binder通讯。
IJobService.aidl
特别注意,这里的oneway。而JSC每次call到JobService之后,又确实需要它反馈状态,所以,JobService需要反馈信息给到JSC,通过IJobCallback.aidl。而JSC也会在每次交互时都定时,如果在规定时间未得到反馈,就会触发timeout。
比如:一般的交互需要在8s内反馈状态;如果是在运行job,那不能超过60s,这个60s也是一个job运行的最长时间:如果它在60s内还没有结束,那么系统会把它finish,只能下次再运行啦。这里提下,job运行结束后,必须调用jobFinished方法通知系统。
综上,IJobService.aidl和IJobCallback.aidl基本上实现里JSC和JobService的双向Binder通讯。在这个双向通讯过程中,两者都担任了Client和Server的角色。不过,先发生的是IJobService.aidl代表的Binder通讯。
还有一点要说明,JobService也是运行在app_proc的主线程中的。这意味着onStartJob和onStopJob方法也是运行在主线程中。如果需要执行耗时的任务,必须另起线程来完成。
oneway interface IJobService {
/** Begin execution of application's job. */
void startJob(in JobParameters jobParams);
/** Stop execution of application's job. */
void stopJob(in JobParameters jobParams);
}
/** Amount of time a job is allowed to execute for before being considered timed-out. */
private static final long EXECUTING_TIMESLICE_MILLIS = 60 * 1000;
/** Amount of time the JobScheduler will wait for a response from an app for a message. */
private static final long OP_TIMEOUT_MILLIS = 8 * 1000;
这里需要一张JSC的状态转换图。。。。。。
6.其它
何时使用JobSchduler?
具体的实例解析,比如BackgroundDexOptService?