JobScheduler服务

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?

7.小结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值