JobScheduler调度器过程(JobSchedulerService的启动过程)

本文详细剖析了Android系统中JobSchedulerService的启动流程,包括如何从jobs.xml读取任务配置,转换为JobInfo,以及JobSchedulerService内部组件如JobStore、JobHandler的工作原理。
摘要由CSDN通过智能技术生成

 

JobSchedulerService启动过程,最主要工作是从jobs.xml文件收集所有的jobs,放入到JobStore的成员变量mJobSet,转成jobinfo。

 

JobScheduler服务启动

2.1 startOtherServices

[-> SystemServer.java]

private void startOtherServices() { ... mSystemServiceManager.startService(JobSchedulerService.class); ... } 

该方法先初始化JSS,然后再调用其onStart()方法。

 

2.2 JobSchedulerService

[-> JobSchedulerService.java]

JobSchedulerService {
    List<StateController> mControllers;
    final JobHandler mHandler;
    final JobSchedulerStub mJobSchedulerStub;
    final JobStore mJobs;
    ...

    public JobSchedulerService(Context context) {
        super(context);
        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)); //创建主线程的looper[见小节2.3] mHandler = new JobHandler(context.getMainLooper()); //创建binder服务端[见小节2.4] mJobSchedulerStub = new JobSchedulerStub(); //[见小节2.5] mJobs = JobStore.initAndGet(this); } public void onStart() { publishBinderService(Context.JOB_SCHEDULER_SERVICE, mJobSchedulerStub); } } 

创建了5个不同的StateController,分别添加到mControllers。

类型说明
ConnectivityController注册监听网络连接状态的广播
TimeController注册监听job时间到期的广播
IdleController注册监听屏幕亮/灭,dream进入/退出,状态改变的广播
BatteryController注册监听电池是否充电,电量状态的广播
AppIdleController监听app是否空闲

state_controller

接下来,以ConnectivityController为例,说一说相应Controller的创建过程, 其他Controller也基本类似.

 

 

2.2.1 ConnectivityController

[-> ConnectivityController.java]

public class ConnectivityController extends StateController implements ConnectivityManager.OnNetworkActiveListener { public static ConnectivityController get(JobSchedulerService jms) { synchronized (sCreationLock) { if (mSingleton == null) { //单例模式 mSingleton = new ConnectivityController(jms, jms.getContext()); } return mSingleton; } } private ConnectivityController(StateChangedListener stateChangedListener, Context context) { super(stateChangedListener, context); //注册监听网络连接状态的广播,且采用BackgroundThread线程 IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); mContext.registerReceiverAsUser( mConnectivityChangedReceiver, UserHandle.ALL, intentFilter, null, BackgroundThread.getHandler()); ConnectivityService cs = (ConnectivityService)ServiceManager.getService(Context.CONNECTIVITY_SERVICE); if (cs != null) { if (cs.getActiveNetworkInfo() != null) { mNetworkConnected = cs.getActiveNetworkInfo().isConnected(); } mNetworkUnmetered = mNetworkConnected && !cs.isActiveNetworkMetered(); } } } 

当监听到CONNECTIVITY_ACTION广播,onReceive方法的执行位于“android.bg”线程。

 

 

2.3 JSS.JobHandler

[-> JobSchedulerService.java ::JobHandler]

public class JobSchedulerService extends com.android.server.SystemService implements StateChangedListener, JobCompletedListener { private class JobHandler extends Handler { public JobHandler(Looper looper) { super(looper); } public void handleMessage(Message message) { synchronized (mJobs) { //当系统启动到phase 600,则mReadyToRock=true. if (!mReadyToRock) { return; } } switch (message.what) { case MSG_JOB_EXPIRED: ... case MSG_CHECK_JOB: ... } maybeRunPendingJobsH(); removeMessages(MSG_CHECK_JOB); } 

JobHandler采用的是system_server进程的主线程Looper,也就是该过程运行在主线程。

 

 

2.4 JobSchedulerStub

[-> JobSchedulerService.java ::JobSchedulerStub]

final class JobSchedulerStub extends IJobScheduler.Stub { ... } 

JobSchedulerStub作为实现接口IJobScheduler的binder服务端。

 

 

2.5 JS.initAndGet

[-> JobStore.java]

static JobStore initAndGet(JobSchedulerService jobManagerService) {
    synchronized (sSingletonLock) { if (sSingleton == null) { //[见小节2.6] sSingleton = new JobStore(jobManagerService.getContext(), Environment.getDataDirectory()); } return sSingleton; } }

2.6 创建JobStore

[-> JobStore.java]

public class JobStore {
    final ArraySet<JobStatus> mJobSet; private final Handler mIoHandler = IoThread.getHandler(); ... private JobStore(Context context, File dataDir) { mContext = context; mDirtyOperations = 0; File systemDir = new File(dataDir, "system"); File jobDir = new File(systemDir, "job"); jobDir.mkdirs(); // 创建/data/system/job/jobs.xml mJobsFile = new AtomicFile(new File(jobDir, "jobs.xml")); mJobSet = new ArraySet<JobStatus>(); //[见小节2.7.1] readJobMapFromDisk(mJobSet); } } 

该方法会创建job目录以及jobs.xml文件, 以及从文件中读取所有的JobStatus。

 

 

 

2.7 xml解析

2.7.1 ReadJobMapFromDiskRunnable

[-> JobStore.java]

private class ReadJobMapFromDiskRunnable implements Runnable { private final ArraySet<JobStatus> jobSet; ReadJobMapFromDiskRunnable(ArraySet<JobStatus> jobSet) { this.jobSet = jobSet; } public void run() { List<JobStatus> jobs; FileInputStream fis = mJobsFile.openRead(); synchronized (JobStore.this) { jobs = readJobMapImpl(fis); //[见小节2.7.2] if (jobs != null) { for (int i=0; i<jobs.size(); i++) { this.jobSet.add(jobs.get(i)); } } } fis.close(); } } 

此处mJobsFile便是/data/system/job/jobs.xml。

 

 

2.7.2 readJobMapImpl

[-> JobStore.java]

private List<JobStatus> readJobMapImpl(FileInputStream fis)
         throws XmlPullParserException, IOException {
     XmlPullParser parser = Xml.newPullParser();
     parser.setInput(fis, StandardCharsets.UTF_8.name());
     ...

     String tagName = parser.getName();
     if ("job-info".equals(tagName)) {
         final List<JobStatus> jobs = new ArrayList<JobStatus>(); ... eventType = parser.next(); do { //读取每一个 <job/> if (eventType == XmlPullParser.START_TAG) { tagName = parser.getName(); if ("job".equals(tagName)) { //[见小节2.7.3] JobStatus persistedJob = restoreJobFromXml(parser); if (persistedJob != null) { jobs.add(persistedJob); } } } eventType = parser.next(); } while (eventType != XmlPullParser.END_DOCUMENT); return jobs; } return null; } 

从文件jobs.xml中读取并创建JobStatus,然后添加到mJobSet.

 

 

2.7.3 restoreJobFromXml

[-> JobStore.java]

private JobStatus restoreJobFromXml(XmlPullParser parser) throws XmlPullParserException, IOException { JobInfo.Builder jobBuilder; int uid; //创建用于获取jobInfo的Builder[见小节2.7.4] jobBuilder = buildBuilderFromXml(parser); jobBuilder.setPersisted(true); uid = Integer.valueOf(parser.getAttributeValue(null, "uid")); ... buildConstraintsFromXml(jobBuilder, parser); //读取常量 //读取job执行的两个时间点:delay和deadline Pair<Long, Long> elapsedRuntimes = buildExecutionTimesFromXml(parser); ... //[见小节2.8] return new JobStatus(jobBuilder.build(), uid, elapsedRuntimes.first, elapsedRuntimes.second); }

2.7.4 buildBuilderFromXml

[-> JobStore.java]

private JobInfo.Builder buildBuilderFromXml(XmlPullParser parser) throws NumberFormatException { int jobId = Integer.valueOf(parser.getAttributeValue(null, "jobid")); String packageName = parser.getAttributeValue(null, "package"); String className = parser.getAttributeValue(null, "class"); ComponentName cname = new ComponentName(packageName, className); //[见小节2.7.5] return new JobInfo.Builder(jobId, cname); } 

创建的JobInfo对象,记录着任务的jobid, package, class。

 

 

2.7.5 创建JobInfo

[-> JobInfo.java]

public class JobInfo implements Parcelable { public static final class Builder { public Builder(int jobId, ComponentName jobService) { mJobService = jobService; mJobId = jobId; } public JobInfo build() { mExtras = new PersistableBundle(mExtras); return new JobInfo(this); //创建JobInfo } } }

2.8 创建JobStatus

[-> JobStatus.java]

public JobStatus(JobInfo job, int uId, long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis) { this(job, uId, 0); this.earliestRunTimeElapsedMillis = earliestRunTimeElapsedMillis; this.latestRunTimeElapsedMillis = latestRunTimeElapsedMillis; } private JobStatus(JobInfo job, int uId, int numFailures) { this.job = job; this.uId = uId; this.name = job.getService().flattenToShortString(); this.tag = "*job*/" + this.name; this.numFailures = numFailures; } 

JobStatus对象记录着任务的jobId, ComponentName, uid以及标签和失败次数信息。

 

 

2.9 JSS.onBootPhase

public void onBootPhase(int phase) { if (PHASE_SYSTEM_SERVICES_READY == phase) { //阶段500,则开始注册package和use移除的广播监听 final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED); filter.addDataScheme("package"); getContext().registerReceiverAsUser( mBroadcastReceiver, UserHandle.ALL, filter, null, null); final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED); userFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); getContext().registerReceiverAsUser( mBroadcastReceiver, UserHandle.ALL, userFilter, null, null); mPowerManager = (PowerManager)getContext().getSystemService(Context.POWER_SERVICE); } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { synchronized (mJobs) { mReadyToRock = true; mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( BatteryStats.SERVICE_NAME)); for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) { //创建JobServiceContext对象 mActiveServices.add( new JobServiceContext(this, mBatteryStats, getContext().getMainLooper())); } ArraySet<JobStatus> jobs = mJobs.getJobs(); for (int i=0; i<jobs.size(); i++) { JobStatus job = jobs.valueAt(i); for (int controller=0; controller<mControllers.size(); controller++) { mControllers.get(controller).deviceIdleModeChanged(mDeviceIdleMode); mControllers.get(controller).maybeStartTrackingJob(job); } } //[见小节3.8] mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget(); } } } 

对于低内存的设备,则只创建一个创建JobServiceContext对象;否则创建3个该对象。

 

 

2.9.1 创建JobServiceContext

[-> JobServiceContext.java]

JobServiceContext(JobSchedulerService service, IBatteryStats batteryStats, Looper looper) {
    this(service.getContext(), batteryStats, service, looper);
}

JobServiceContext(Context context, IBatteryStats batteryStats,
        JobCompletedListener completedListener, Looper looper) {
    mContext = context;
    mBatteryStats = batteryStats;
    mCallbackHandler = new JobServiceHandler(looper);
    mCompletedListener = completedListener;
    mAvailable = true;
}

此处的JobServiceHandler采用的是system_server进程的主线程。

 

 

2.10 小结

  1. JSS.JobHandler运行在system_server进程的主线程;
  2. JobServiceContext.JobServiceHandler运行在system_server进程的主线程;
  3. JobSchedulerStub作为实现接口IJobScheduler的binder服务端;
  4. JobStore:其成员变量mIoHandler运行在”android.io”线程;
  5. JobStatus:从/data/system/job/jobs.xml文件中读取每个JobInfo,再解析成JobStatus对象,添加到mJobSet。

 

转载于:https://www.cnblogs.com/softwarelanguagebs/p/9531562.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值