android之Jobscheduler运行机制详解

如果想在将来达到一定条件下执行某项任务时,可以在一个实现了JobService的子类的onStartJob方法中执行这项任务,使用JobInfo的Builder方法来设定条件并和实现了JobService的子类的组件名绑定,然后调用系统服务JobScheduler的schedule方法。这样,即便在执行任务之前应用程序进程被杀,也不会导致任务不会执行,因为系统服务JobScheduler会使用bindServiceAsUser的方法把实现了JobService的子类服务启动起来,并执行它的onStartJob方法。

由于JobSchedulerService是系统服务,故这里按照启动流程和使用流程分开分析源码,下面先看下启动流程的时序图:

由于JobSchedulerService的构造方法中执行的操作比较多,时序图中没有详细画出。

Zygote进程启动后会启动System进程,在System进程启动过程中会启动系统中的关键服务,如AMS、PMS以及这里要用到的JobSchedulerService等。

SystemServer启动JobSchedulerService服务调用的是SystemServiceManager类的startService方法:

private void startOtherServices() {

. . .

if(mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {

// 开启JobSchedulerService服务

mSystemServiceManager.startService(JobSchedulerService.class);

. . .

}

}

看下SystemServiceManager类的startService方法的具体操作:

private final ArrayList<SystemService> mServices = newArrayList<SystemService>();

/**

* 创建并启动一个继承自SystemService类的系统服务。

*

* @param 一个继承自SystemService类的服务类

* @return 服务类的实例

* @throws 如果服务启动失败则抛RuntimeException异常

*/

@SuppressWarnings("unchecked")

public <T extends SystemService> T startService(Class<T>serviceClass) {

// 获取服务类的类名

final Stringname = serviceClass.getName();

Slog.i(TAG, "Starting" + name);

// 判断服务类是否是SystemService的子类

if(!SystemService.class.isAssignableFrom(serviceClass)) {

throw newRuntimeException("Failed to create " + name

+ ":service must extend " + SystemService.class.getName());

}

final Tservice;

try {

// 获取服务类包含一个Context参数的构造方法

Constructor<T> constructor =serviceClass.getConstructor(Context.class);

// 创建这个服务类的实例

service =constructor.newInstance(mContext);

} catch(InstantiationException ex) {

throw newRuntimeException("Failed to create service " + name

+ ":service could not be instantiated", ex);

} catch(IllegalAccessException ex) {

throw newRuntimeException("Failed to create service " + name

+ ":service must have a public constructor with a Context argument", ex);

} catch(NoSuchMethodException ex) {

throw newRuntimeException("Failed to create service " + name

+ ":service must have a public constructor with a Context argument", ex);

} catch(InvocationTargetException ex) {

throw newRuntimeException("Failed to create service " + name

+ ":service constructor threw an exception", ex);

}

// 把服务添加到mServices列表中,方便后续使用时取出

mServices.add(service);

try {

// 回调服务的onStart方法

service.onStart();

} catch(RuntimeException ex) {

throw newRuntimeException("Failed to start service " + name

+ ":onStart threw an exception", ex);

}

return service;

}

在开启JobSchedulerService服务时,会创建该服务的实例,来看下该服务的创建过程:

// 任务状态控制器列表

List<StateController> mControllers;

final JobHandler mHandler;

final JobSchedulerStub mJobSchedulerStub;

// 任务主列表

final JobStore mJobs;

public JobSchedulerService(Context context) {

super(context);

// 创建控制器

mControllers = newArrayList<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));

// 初始化JobHandler,主要处理任务到期和检查任务的消息

mHandler = newJobHandler(context.getMainLooper());

// 初始化mJobSchedulerStub

mJobSchedulerStub = new JobSchedulerStub();

// 初始化JobStore并返回从data/system/job/jobs.xml文件中读取的永久性任务

mJobs =JobStore.initAndGet(this);

}

由上面代码可以看出,创建服务有下面几个步骤:

1.初始化各种控制器并添加到列表中

2.初始化JobHandler

3.初始化JobSchedulerStub代理对象

4.初始化任务主列表

下面按顺序分析上面几个步骤:

1.初始化各种控制器并添加到列表中:

抽象类StateController:

public abstract class StateController {

protected staticfinal boolean DEBUG = JobSchedulerService.DEBUG;

protectedContext mContext;

protectedStateChangedListener mStateChangedListener;

protected booleanmDeviceIdleMode;

public StateController(StateChangedListenerstateChangedListener, Context context) {

mStateChangedListener = stateChangedListener;

mContext =context;

}

public void deviceIdleModeChanged(booleanenabled) {

mDeviceIdleMode = enabled;

}

/**

* 该方法中实现控制器添加追踪任务的逻辑

*/

public abstractvoid maybeStartTrackingJob(JobStatus jobStatus);

/**

* 如果任务被取消、执行完成等则remove掉该任务

*/

public abstractvoid maybeStopTrackingJob(JobStatus jobStatus);

public abstractvoid dumpControllerState(PrintWriter pw);

}

接口StateChangedListener:

public interface StateChangedListener {

/**

* 控制器调用该方法通知JobManager该检查某项任务的状态

*/

public void onControllerStateChanged();

/**

* 控制器调用该方法通知JobManager执行该项任务

* @paramjobStatus 直接执行任务,null表示刷新所有准备好的任务

*/

public void onRunJobNow(JobStatusjobStatus);

}

说明:第三方应用使用JobInfo设置任务信息时会调用maybeStartTrackingJob方法,如果设置了该控制器相关的控制项时,就会把该任务添加到追踪列表中。后面会分析任务的添加过程。

下面按JobSchedulerService的构造方法中添加控制器的顺序分析各个控制器的实现原理:

1.ConnectivityController:

该控制器的大致实现流程:

初始化该控制器时,动态注册接收网络变化的广播,并给mNetworkConnected变量和mNetworkUnmetered变量赋初值,收到广播后会修改这两个参数的值并调用updateTrackedJobs方法,该方法主要是遍历保存在追踪列表中的任务,查看是否有任务的两个参数值相对于之前保存的值有变化,如果有则调用mStateChangedListener监听器的onControllerStateChanged()方法通知JobSchedulerService约束任务的条件状态发生改变,这里的mStateChangedListener就是构造方法传递来的JobSchedulerService的实例。由于控制器实现了ConnectivityManage.OnNetworkActiveListener接口,故当网络可用时会调用该接口中的onNetworkActive方法,在该方法中会调用监听器的onRunJobNow方法通知JobSchedulerService执行任务。

下面看下代码实现部分:

public class ConnectivityController extends StateControllerimplements

ConnectivityManager.OnNetworkActiveListener{

private static finalString TAG = "JobScheduler.Conn";

// 追踪任务状态列表

private finalList<JobStatus> mTrackedJobs = new LinkedList<JobStatus>();

// 网络变化的广播

private final BroadcastReceivermConnectivityChangedReceiver =

newConnectivityChangedReceiver();

/** Singleton.*/

private staticConnectivityController mSingleton;

private staticObject sCreationLock = new Object();

/** 追踪最新活动网络是否可计量(网络连接是否收费) */

private booleanmNetworkUnmetered;

/** 追踪最新活动网络是否已经连接 */

private booleanmNetworkConnected;

// 单例模式获取实例

public staticConnectivityController get(JobSchedulerService jms) {

synchronized(sCreationLock) {

if (mSingleton== null) {

mSingleton = new ConnectivityController(jms, jms.getContext());

}

returnmSingleton;

}

}

private ConnectivityController(StateChangedListenerstateChangedListener, Context context) {

super(stateChangedListener,context);

// 注册接收网络变化的广播

IntentFilter intentFilter = new IntentFilter();

intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);

mContext.registerReceiverAsUser(

mConnectivityChangedReceiver, UserHandle.ALL, intentFilter, null, null);

ConnectivityService cs =

(ConnectivityService)ServiceManager.getService(Context.CONNECTIVITY_SERVICE);

if (cs != null){

if(cs.getActiveNetworkInfo() != null) {

// 给网络连接变量赋值

mNetworkConnected = cs.getActiveNetworkInfo().isConnected();

}

// 给不可计量变量赋值

mNetworkUnmetered= mNetworkConnected && !cs.isActiveNetworkMetered();

}

}

@Override

public void maybeStartTrackingJob(JobStatusjobStatus) {

// 任务是否有连接约束或不可计量约束。说明:任务的约束是通过JobInfo的builder方法设置的

if(jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) {

synchronized(mTrackedJobs) {

jobStatus.connectivityConstraintSatisfied.set(mNetworkConnected);

jobStatus.unmeteredConstraintSatisfied.set(mNetworkUnmetered);

// 把任务添加到追踪列表中

mTrackedJobs.add(jobStatus);

}

}

}

@Override

public void maybeStopTrackingJob(JobStatusjobStatus) {

if (jobStatus.hasConnectivityConstraint()|| jobStatus.hasUnmeteredConstraint()) {

synchronized(mTrackedJobs) {

// 把任务从列表中移除

mTrackedJobs.remove(jobStatus);

}

}

}

/**

* @param userIdId of the user for whom we are updating the connectivity state.

*/

private void updateTrackedJobs(intuserId) {

synchronized(mTrackedJobs) {

booleanchanged = false;

// 遍历保存在mTrackedJobs列表中的任务

for (JobStatusjs : mTrackedJobs) {

if(js.getUserId() != userId) {

continue;

}

//getAndSet方法返回上次保存的值,并把新值替换旧值保存

booleanprevIsConnected =

js.connectivityConstraintSatisfied.getAndSet(mNetworkConnected);

booleanprevIsMetered = js.unmeteredConstraintSatisfied.getAndSet(mNetworkUnmetered);

// 如果本次的mNetworkConnected或mNetworkUnmetered与上一次保存的值不一样,则设置changed为true

if (prevIsConnected !=mNetworkConnected || prevIsMetered != mNetworkUnmetered) {

changed = true;

}

}

// 如果changed为true,则调用监听器(即JobSchedulerService)的onControllerStateChanged方法

if (changed) {

mStateChangedListener.onControllerStateChanged();

}

}

}

// 该方法是OnNetworkActiveListener接口中的方法,网络可用时调用该方法

public synchronizedvoid onNetworkActive() {

synchronized(mTrackedJobs) {

for(JobStatus js : mTrackedJobs) {

// 判断该任务的所有约束条件是否都已得到满足

if(js.isReady()) {

if (DEBUG) {

Slog.d(TAG, "Running " + js + " due to networkactivity.");

}

// 调用监听器的onRunJobNow方法执行任务

mStateChangedListener.onRunJobNow(js);

}

}

}

}

class ConnectivityChangedReceiverextends BroadcastReceiver {

// TODO:Test whether this will be called twice for each user.

@Override

public voidonReceive(Context context, Intent intent) {

if(DEBUG) {

Slog.d(TAG, "Received connectivity event: " +intent.getAction() + " u"

+ context.getUserId());

}

finalString action = intent.getAction();

if(action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {

// 取出广播传递来的网络连接类型

finalint networkType =

intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,

ConnectivityManager.TYPE_NONE);

//Connectivity manager for THIS context - important!

finalConnectivityManager connManager = (ConnectivityManager)

context.getSystemService(Context.CONNECTIVITY_SERVICE);

finalNetworkInfo activeNetwork = connManager.getActiveNetworkInfo();

finalint userid = context.getUserId();

//This broadcast gets sent a lot, only update if the active network has changed.

// 网络不可用

if(activeNetwork == null) {

mNetworkUnmetered = false;

mNetworkConnected = false;

// 更新追踪任务

updateTrackedJobs(userid);

// 判断当前激活的网络连接类型是否和广播传递来的网络连接类型相同

} elseif (activeNetwork.getType() == networkType) {

mNetworkUnmetered = false;

mNetworkConnected = !intent.getBooleanExtra(

ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);

if (mNetworkConnected) {  // Nopoint making the call if we know there's no conn.

mNetworkUnmetered =!connManager.isActiveNetworkMetered();

}

// 更新追踪任务

updateTrackedJobs(userid);

}

} else{

if(DEBUG) {

Slog.d(TAG, "Unrecognisedaction in intent: " + action);

}

}

}

};

@Override

public void dumpControllerState(PrintWriterpw) {

pw.println("Conn.");

pw.println("connected:" + mNetworkConnected + " unmetered: " + mNetworkUnmetered);

for(JobStatus js: mTrackedJobs) {

pw.println(String.valueOf(js.hashCode()).substring(0, 3) + ".."

+ ": C=" + js.hasConnectivityConstraint()

+ ", UM=" + js.hasUnmeteredConstraint());

}

}

}

2.TimeController

由于该控制器跟任务执行时间相关,故调用maybeStartTrackingJob方法添加任务时会根据任务执行时间点插入到追踪列表中,并更新下一个要执行任务的执行时间点。

该控制器的大致实现流程:

初始化控制器时,初始化任务的deadline到期和延迟到期时发送广播的操作,动态注册这两个广播,根据接收到不同的广播执行不同的检查机制:

遍历检查任务的延迟时间是否已经到期,如果有任务的延迟时间到期并且所有的约束都得到满足时,调用mStateChangedListener监听器的onControllerStateChanged方法;

或者检查任务追踪列表中是否有deadline过期导致该任务需要执行,如果有则调用mStateChangedListener监听器的onRunJobNow方法。

下面看下代码实现部分:

/**

* 该类为下一个到期任务设置一个alarm,并确定任务的最小延迟是否已经满足

*/

public class TimeController extends StateController {

private static finalString TAG = "JobScheduler.Time";

private static finalString ACTION_JOB_EXPIRED =

"android.content.jobscheduler.JOB_DEADLINE_EXPIRED";

private static finalString ACTION_JOB_DELAY_EXPIRED =

"android.content.jobscheduler.JOB_DELAY_EXPIRED";

/** 任务的deadline到期时执行的操作. */

private finalPendingIntent mDeadlineExpiredAlarmIntent;

/** 任务的延迟时间到期时执行的操作. */

private finalPendingIntent mNextDelayExpiredAlarmIntent;

private longmNextJobExpiredElapsedMillis;

private longmNextDelayExpiredElapsedMillis;

privateAlarmManager mAlarmService = null;

/** 按任务执行时间点从小到大的顺序排列的任务列表 */

private finalList<JobStatus> mTrackedJobs = new LinkedList<JobStatus>();

/** Singleton.*/

private staticTimeController mSingleton;

public static synchronizedTimeController get(JobSchedulerService jms) {

if(mSingleton == null) {

mSingleton = new TimeController(jms, jms.getContext());

}

returnmSingleton;

}

private TimeController(StateChangedListenerstateChangedListener, Context context) {

super(stateChangedListener,context);

// 任务的deadline到期时会发送一个ACTION_JOB_EXPIRED广播

mDeadlineExpiredAlarmIntent =

PendingIntent.getBroadcast(mContext, 0 /* ignored */,

new Intent(ACTION_JOB_EXPIRED), 0);

// 任务的延迟时间到期时会发送一个ACTION_JOB_DELAY_EXPIRED广播

mNextDelayExpiredAlarmIntent =

PendingIntent.getBroadcast(mContext, 0 /* ignored */,

new Intent(ACTION_JOB_DELAY_EXPIRED), 0);

// 初始化下一个将要执行的任务的到期时间和延迟时间都为最大长整形

mNextJobExpiredElapsedMillis = Long.MAX_VALUE;

mNextDelayExpiredElapsedMillis= Long.MAX_VALUE;

// 注册广播

IntentFilter intentFilter = new IntentFilter(ACTION_JOB_EXPIRED);

intentFilter.addAction(ACTION_JOB_DELAY_EXPIRED);

mContext.registerReceiver(mAlarmExpiredReceiver, intentFilter);

}

/**

* 把设置了时间约束的任务,根据任务执行时间点插入到列表中正确的位置

*/

@Override

public synchronizedvoid maybeStartTrackingJob(JobStatus job) {

// 判断任务是否有延迟约束或deadline约束

if (job.hasTimingDelayConstraint()|| job.hasDeadlineConstraint()) {

maybeStopTrackingJob(job);

// 插入操作

booleanisInsert = false;

ListIterator<JobStatus> it =mTrackedJobs.listIterator(mTrackedJobs.size());

//从列表后面往前遍历,如果前一个任务的执行时间点小于该任务的执行时间点则插入该任务

while(it.hasPrevious()) {

JobStatus ts = it.previous();

if(ts.getLatestRunTimeElapsed() < job.getLatestRunTimeElapsed()) {

// Insert

isInsert = true;

break;

}

}

if(isInsert)

{

// 获取要插入该任务的位置

it.next();

}

//插入该任务

it.add(job);

// 更新下一个将要执行任务的alarm时间

maybeUpdateAlarms(

job.hasTimingDelayConstraint() ? job.getEarliestRunTime() :Long.MAX_VALUE,

job.hasDeadlineConstraint() ? job.getLatestRunTimeElapsed() :Long.MAX_VALUE);

}

}

/**

* 停止追踪任务时,只需要更新alarm

*/

@Override

public synchronizedvoid maybeStopTrackingJob(JobStatus job) {

if(mTrackedJobs.remove(job)) {

// 检查延迟alarm

checkExpiredDelaysAndResetAlarm();

// 检查deadline的alarm

checkExpiredDeadlinesAndResetAlarm();

}

}

/**

* 任务的约束得到满足后,控制器不再追踪该任务

*/

private booleancanStopTrackingJob(JobStatus job) {

return(!job.hasTimingDelayConstraint() ||

job.timeDelayConstraintSatisfied.get()) &&

(!job.hasDeadlineConstraint() ||

job.deadlineConstraintSatisfied.get());

}

private void ensureAlarmService(){

if(mAlarmService == null) {

mAlarmService= (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);

}

}

/**

* 检查任务追踪列表是否有该执行的任务

*/

private synchronizedvoid checkExpiredDeadlinesAndResetAlarm() {

longnextExpiryTime = Long.MAX_VALUE;

// 获取手机开机时间

final longnowElapsedMillis = SystemClock.elapsedRealtime();

Iterator<JobStatus> it = mTrackedJobs.iterator();

while(it.hasNext()) {

JobStatus job = it.next();

// 如果任务没有设置deadline约束,则跳过本次循环

if (!job.hasDeadlineConstraint()) {

continue;

}

// 获取任务下一次执行的时间

final longjobDeadline = job.getLatestRunTimeElapsed();

// 如果任务的下一次执行时间小于手机运行时间,则设置任务的deadline已经得到满足,并运行该任务

if (jobDeadline <= nowElapsedMillis) {

job.deadlineConstraintSatisfied.set(true);

mStateChangedListener.onRunJobNow(job);

it.remove();

} else{  // Sorted by expiry time, so take thenext one and stop.

nextExpiryTime = jobDeadline;

break;

}

}

// 更新下一个将要执行任务的deadline时间

setDeadlineExpiredAlarm(nextExpiryTime);

}

/**

* 遍历检查任务的延迟时间是否已经到期

*/

private synchronizedvoid checkExpiredDelaysAndResetAlarm() {

// 获取手机当前运行时间

final longnowElapsedMillis = SystemClock.elapsedRealtime();

longnextDelayTime = Long.MAX_VALUE;

booleanready = false;

Iterator<JobStatus> it = mTrackedJobs.iterator();

while(it.hasNext()) {

finalJobStatus job = it.next();

// 如果任务没有设置延迟约束则跳过本次循环

if(!job.hasTimingDelayConstraint()) {

continue;

}

// 获取任务的最早执行时间

final longjobDelayTime = job.getEarliestRunTime();

//判断任务的最早执行时间是否小于等于开机时间

if(jobDelayTime <= nowElapsedMillis) {

// 设置任务的延迟已经得到满足

job.timeDelayConstraintSatisfied.set(true);

// 判断任务是否可以停止追踪

if (canStopTrackingJob(job)) {

it.remove();

}

if(job.isReady()) {

ready = true;

}

} else{  // Keep going through list to get nextdelay time.

// 如果任务的最早执行时间小于最大长整形,则更新nextDelayTime变量为最早执行任务的时间

if(nextDelayTime > jobDelayTime) {

nextDelayTime = jobDelayTime;

}

}

}

// 如果任务的约束条件都得到满足,则调用监听器(即JobSchedulerService)的onControllerStateChanged方法

if (ready){

mStateChangedListener.onControllerStateChanged();

}

// 更新下一个将要执行任务的延迟过期时间

setDelayExpiredAlarm(nextDelayTime);

}

private void maybeUpdateAlarms(longdelayExpiredElapsed, long deadlineExpiredElapsed) {

// 如果该任务的延迟过期时间小于下一个将要执行的任务的延迟过期时间,则更新下一个将要执行任务的延迟过期时间

if(delayExpiredElapsed < mNextDelayExpiredElapsedMillis) {

setDelayExpiredAlarm(delayExpiredElapsed);

}

// 如果该任务的deadline时间小于下一个将要执行的任务的deadline时间,则更新下一个将要执行任务的deadline时间

if(deadlineExpiredElapsed < mNextJobExpiredElapsedMillis) {

setDeadlineExpiredAlarm(deadlineExpiredElapsed);

}

}

/**

* 用AlarmManager为下一个将要执行的任务设置一个alarm,该alarm不会唤醒手机

*/

private void setDelayExpiredAlarm(longalarmTimeElapsedMillis) {

// 调整alarm时间,如果alarm时间设置不对则调整

alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);

// 更新下一个将要执行任务的延迟过期时间

mNextDelayExpiredElapsedMillis = alarmTimeElapsedMillis;

// 更新执行任务延迟时间到期操作的时间

updateAlarmWithPendingIntent(mNextDelayExpiredAlarmIntent,mNextDelayExpiredElapsedMillis);

}

/**

* 用AlarmManager为deadline将要到期的任务设置一个alarm,该alarm将会唤醒手机

*/

private void setDeadlineExpiredAlarm(longalarmTimeElapsedMillis) {

// 调整alarm时间,如果alarm时间设置不对则调整

alarmTimeElapsedMillis = maybeAdjustAlarmTime(alarmTimeElapsedMillis);

// 更新下一个将要执行任务的deadline到期时间

mNextJobExpiredElapsedMillis =alarmTimeElapsedMillis;

// 更新执行任务deadline到期操作的时间

updateAlarmWithPendingIntent(mDeadlineExpiredAlarmIntent,mNextJobExpiredElapsedMillis);

}

// 调整alarm时间,如果alarm时间设置不对则调整

private long maybeAdjustAlarmTime(longproposedAlarmTimeElapsedMillis) {

final longearliestWakeupTimeElapsed = SystemClock.elapsedRealtime();

// 如果设置值小于开机时间则返回开机时间,因为AlarmManager的set方法只能设置比开机时间晚的时间点

if(proposedAlarmTimeElapsedMillis < earliestWakeupTimeElapsed) {

returnearliestWakeupTimeElapsed;

}

returnproposedAlarmTimeElapsedMillis;

}

// 更新执行pi的alarm时间

private void updateAlarmWithPendingIntent(PendingIntentpi, long alarmTimeElapsed) {

ensureAlarmService();

// 如果传递过来的时间是最大长整形,则取消该PendingIntent

if(alarmTimeElapsed == Long.MAX_VALUE) {

mAlarmService.cancel(pi);

} else {

if(DEBUG) {

Slog.d(TAG, "Setting " + pi.getIntent().getAction() + "for: " + alarmTimeElapsed);

}

// 否则更新pi的执行时间,AlarmManager的set方法是设置在alarmTimeElapsed时间启动pi指定的组件

mAlarmService.set(AlarmManager.ELAPSED_REALTIME, alarmTimeElapsed, pi);

}

}

private finalBroadcastReceiver mAlarmExpiredReceiver = new BroadcastReceiver() {

@Override

public voidonReceive(Context context, Intent intent) {

if(DEBUG) {

Slog.d(TAG, "Just received alarm: " + intent.getAction());

}

// 根据接收到广播的Action检查不同的alarm

if(ACTION_JOB_EXPIRED.equals(intent.getAction())) {

checkExpiredDeadlinesAndResetAlarm();

} else if(ACTION_JOB_DELAY_EXPIRED.equals(intent.getAction())) {

checkExpiredDelaysAndResetAlarm();

}

}

};

@Override

public void dumpControllerState(PrintWriterpw) {

final longnowElapsed = SystemClock.elapsedRealtime();

pw.println("Alarms(" + SystemClock.elapsedRealtime() + ")");

pw.println(

"Nextdelay alarm in " + (mNextDelayExpiredElapsedMillis - nowElapsed)/1000 + "s");

pw.println("Nextdeadline alarm in " + (mNextJobExpiredElapsedMillis - nowElapsed)/1000

+ "s");

pw.println("Tracking:");

for(JobStatus ts : mTrackedJobs) {

pw.println(String.valueOf(ts.hashCode()).substring(0, 3) + ".."

+ ": (" + (ts.hasTimingDelayConstraint() ?ts.getEarliestRunTime() : "N/A")

+ ", " +(ts.hasDeadlineConstraint() ?ts.getLatestRunTimeElapsed() : "N/A")

+ ")");

}

}

}

3.IdleController:

该控制器的大致实现流程:

初始化该控制器时,动态注册监听息屏/亮屏,进入休眠/退出休眠以及进入空闲状态的广播。

收到亮屏/退出休眠广播时,设置mScreenOn为true,并取消空闲时发送空闲广播的PendingIntent,如果mIdle为true,则修改为false,并上报空闲状态改变,遍历追踪任务,设置任务的空闲满足状态为isIdle,并调用mStateChangedListener监听器的onControllerStateChanged方法;

收到息屏/进入休眠广播时设置mScreenOn为false,并设置一个在开机时间+息屏/进入休眠阈值的时间点、IDLE_WINDOW_SLOP时间窗内触发的发送进入空闲状态的广播;

收到进入空闲状态广播时,符合(!mIdle && !mScreenOn)判断时,设置mIdle为true,并上报新的空闲状态,遍历追踪任务,设置任务的空闲满足状态为isIdle,并调用mStateChangedListener监听器的onControllerStateChanged方法。

下面看下代码实现部分:

public class IdleController extends StateController {

private static finalString TAG = "IdleController";

// 息屏或休眠阈值

private static finallong INACTIVITY_IDLE_THRESHOLD = 71 * 60 * 1000; // millis; 71 min

// 触发发送广播的时间窗

private static finallong IDLE_WINDOW_SLOP = 5 * 60 * 1000; // 5 minute window, to be nice

private static finalString ACTION_TRIGGER_IDLE =

"com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE";

finalArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();

IdlenessTrackermIdleTracker;

// Singletonfactory

private staticObject sCreationLock = new Object();

private static volatileIdleController sController;

public staticIdleController get(JobSchedulerService service) {

synchronized(sCreationLock) {

if(sController == null) {

sController = new IdleController(service, service.getContext());

}

returnsController;

}

}

private IdleController(StateChangedListenerstateChangedListener, Context context) {

super(stateChangedListener,context);

// 初始化空闲状态追踪

initIdleStateTracking();

}

/**

*StateController interface

*/

@Override

public void maybeStartTrackingJob(JobStatustaskStatus) {

// 判断任务是否设置了空闲约束

if (taskStatus.hasIdleConstraint()){

synchronized(mTrackedTasks) {

// 把任务添加到追踪任务列表

mTrackedTasks.add(taskStatus);

// 获取当前手机状态并设置任务的空闲约束满足状态

taskStatus.idleConstraintSatisfied.set(mIdleTracker.isIdle());

}

}

}

@Override

public void maybeStopTrackingJob(JobStatustaskStatus) {

synchronized(mTrackedTasks) {

mTrackedTasks.remove(taskStatus);

}

}

/**

* 上报新的空闲状态

*/

void reportNewIdleState(booleanisIdle) {

synchronized(mTrackedTasks) {

// 遍历追踪任务,设置任务的空闲满足状态为isIdle

for(JobStatus task : mTrackedTasks) {

task.idleConstraintSatisfied.set(isIdle);

}

}

// 调用监听器的onControllerStateChanged方法

mStateChangedListener.onControllerStateChanged();

}

/**

* 空闲状态追踪,当状态发生改变时通知任务管理器

*/

private void initIdleStateTracking(){

// 初始化空闲状态追踪器广播

mIdleTracker = new IdlenessTracker();

// 注册广播开始追踪

mIdleTracker.startTracking();

}

class IdlenessTrackerextends BroadcastReceiver {

privateAlarmManager mAlarm;

privatePendingIntent mIdleTriggerIntent;

booleanmIdle;

boolean mScreenOn;

public IdlenessTracker(){

mAlarm= (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);

Intentintent = new Intent(ACTION_TRIGGER_IDLE)

.setPackage("android")

.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);

//初始化发送ACTION_TRIGGER_IDLE广播的延迟Intent

mIdleTriggerIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);

// 开机时假设用户刚使用过手机

mIdle =false;

mScreenOn= true;

}

public booleanisIdle() {

returnmIdle;

}

public voidstartTracking() {

IntentFilter filter = new IntentFilter();

//Screen state

filter.addAction(Intent.ACTION_SCREEN_ON);

filter.addAction(Intent.ACTION_SCREEN_OFF);

//Dreaming state

filter.addAction(Intent.ACTION_DREAMING_STARTED);

filter.addAction(Intent.ACTION_DREAMING_STOPPED);

// Debugging/instrumentation

filter.addAction(ACTION_TRIGGER_IDLE);

// 注册广播

mContext.registerReceiver(this, filter);

}

@Override

public voidonReceive(Context context, Intent intent) {

finalString action = intent.getAction();

if(action.equals(Intent.ACTION_SCREEN_ON)

|| action.equals(Intent.ACTION_DREAMING_STOPPED)) {

if(DEBUG) {

Slog.v(TAG,"exiting idle : " + action);

}

mScreenOn = true;

//cancelthe alarm

mAlarm.cancel(mIdleTriggerIntent);

if(mIdle) {

//possible transition to not-idle

mIdle = false;

// 上报新的空闲状态

reportNewIdleState(mIdle);

}

} else if(action.equals(Intent.ACTION_SCREEN_OFF)

|| action.equals(Intent.ACTION_DREAMING_STARTED)) {

final long nowElapsed =SystemClock.elapsedRealtime();

//开机时间+息屏/进入休眠阈值

finallong when = nowElapsed + INACTIVITY_IDLE_THRESHOLD;

if(DEBUG) {

Slog.v(TAG, "Scheduling idle : " + action + " now:"+ nowElapsed + " when="

+ when);

}

mScreenOn = false;

//设置一个在时间窗内触发的mIdleTriggerIntent。类似于set方法,只不过setWindow允许系统调整触发任务的时间。

mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,

when, IDLE_WINDOW_SLOP, mIdleTriggerIntent);

} else if(action.equals(ACTION_TRIGGER_IDLE)) {

//idle time starts now. Do not set mIdle if screen is on.

if(!mIdle && !mScreenOn) {

if (DEBUG) {

Slog.v(TAG, "Idle trigger fired @ " +SystemClock.elapsedRealtime());

}

mIdle = true;

reportNewIdleState(mIdle);

}

}

}

}

@Override

public void dumpControllerState(PrintWriterpw) {

synchronized(mTrackedTasks) {

pw.print("Idle: ");

pw.println(mIdleTracker.isIdle() ? "true" : "false");

pw.println(mTrackedTasks.size());

for (inti = 0; i < mTrackedTasks.size(); i++) {

finalJobStatus js = mTrackedTasks.get(i);

pw.print("  ");

pw.print(String.valueOf(js.hashCode()).substring(0, 3));

pw.println("..");

}

}

}

}

4.BatteryController:

该控制器的大致实现流程:

初始化该控制器时,动态注册监听电量低/电量OK,充电/非充电的广播。

收到电量低的广播时,设置mBatteryHealthy为false;

收到电量OK的广播时,设置mBatteryHealthy为true,并上报新的充电状态:如果是否可以开始执行任务的状态发生变化,则调用监听器的onControllerStateChanged方法,如果可以开始执行任务,则刷新所有准备好的任务;

收到充电/非充电广播时,分别设置mCharging为true/false,并上报新的充电状态。

下面看下代码实现部分:

/**

* 追踪手机是否在充电的简单控制器,如果手机充电超过两分钟,则系统会发送ACTION_BATTERY_OK广播

*/

public class BatteryController extends StateController {

private static finalString TAG = "JobScheduler.Batt";

private static finalObject sCreationLock = new Object();

private static volatileBatteryController sController;

privateList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();

private ChargingTrackermChargeTracker;

public staticBatteryController get(JobSchedulerService taskManagerService) {

synchronized(sCreationLock) {

if(sController == null) {

sController = new BatteryController(taskManagerService,

taskManagerService.getContext());

}

}

returnsController;

}

@VisibleForTesting

publicChargingTracker getTracker() {

returnmChargeTracker;

}

@VisibleForTesting

public staticBatteryController getForTesting(StateChangedListener stateChangedListener,

Context context) {

return newBatteryController(stateChangedListener, context);

}

private BatteryController(StateChangedListenerstateChangedListener, Context context) {

super(stateChangedListener,context);

// 初始化充电追踪器广播

mChargeTracker = new ChargingTracker();

// 注册广播开始追踪

mChargeTracker.startTracking();

}

@Override

public void maybeStartTrackingJob(JobStatustaskStatus) {

// 获取当前手机是否在充电并且可以开始执行任务

final booleanisOnStablePower = mChargeTracker.isOnStablePower();

// 判断任务是否设置了充电约束

if (taskStatus.hasChargingConstraint()){

synchronized(mTrackedTasks) {

// 添加任务到追踪列表

mTrackedTasks.add(taskStatus);

// 设置任务的充电满足状态为isOnStablePower

taskStatus.chargingConstraintSatisfied.set(isOnStablePower);

}

}

}

@Override

public void maybeStopTrackingJob(JobStatustaskStatus) {

if(taskStatus.hasChargingConstraint()) {

synchronized(mTrackedTasks) {

mTrackedTasks.remove(taskStatus);

}

}

}

// 上报新的充电状态

private void maybeReportNewChargingState(){

final booleanstablePower = mChargeTracker.isOnStablePower();

if (DEBUG){

Slog.d(TAG, "maybeReportNewChargingState: " + stablePower);

}

booleanreportChange = false;

synchronized(mTrackedTasks) {

for(JobStatus ts : mTrackedTasks) {

// 获取任务上一次的是否可以开始执行任务的判断

booleanprevious = ts.chargingConstraintSatisfied.getAndSet(stablePower);

//如果是否可以开始执行任务的状态发生变化

if(previous != stablePower) {

reportChange = true;

}

}

}

// 如果是否可以开始执行任务的状态发生变化,则调用监听器的onControllerStateChanged方法

if(reportChange) {

mStateChangedListener.onControllerStateChanged();

}

// 如果可以开始执行任务,则刷新所有准备好的任务

if(stablePower) {

mStateChangedListener.onRunJobNow(null);

}

}

public class ChargingTrackerextends BroadcastReceiver {

private booleanmCharging;

private booleanmBatteryHealthy;

public ChargingTracker(){

}

public voidstartTracking() {

IntentFilter filter = new IntentFilter();

//Battery health.

filter.addAction(Intent.ACTION_BATTERY_LOW);

filter.addAction(Intent.ACTION_BATTERY_OKAY);

//Charging/not charging.

filter.addAction(BatteryManager.ACTION_CHARGING);

filter.addAction(BatteryManager.ACTION_DISCHARGING);

// 注册广播

mContext.registerReceiver(this, filter);

// 初始化追踪器状态

BatteryManagerInternal batteryManagerInternal =

LocalServices.getService(BatteryManagerInternal.class);

mBatteryHealthy = !batteryManagerInternal.getBatteryLevelLow();

mCharging =batteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);

}

// 判断是否可以开始执行任务

boolean isOnStablePower(){

returnmCharging && mBatteryHealthy;

}

@Override

public voidonReceive(Context context, Intent intent) {

onReceiveInternal(intent);

}

@VisibleForTesting

public voidonReceiveInternal(Intent intent) {

finalString action = intent.getAction();

if(Intent.ACTION_BATTERY_LOW.equals(action)) {

if(DEBUG) {

Slog.d(TAG, "Battery life too low to do work. @ "

+SystemClock.elapsedRealtime());

}

//If we get this action, the battery is discharging => it isn't plugged in so

//there's no work to cancel. We track this variable for the case where it is

//charging, but hasn't been for long enough to be healthy.

mBatteryHealthy = false;

} else if(Intent.ACTION_BATTERY_OKAY.equals(action)) {

if(DEBUG) {

Slog.d(TAG, "Battery life healthy enough to do work. @ "

+SystemClock.elapsedRealtime());

}

mBatteryHealthy = true;

// 上报新的充电状态

maybeReportNewChargingState();

} else if(BatteryManager.ACTION_CHARGING.equals(action)) {

if(DEBUG) {

Slog.d(TAG, "Received charging intent, fired @ "

+SystemClock.elapsedRealtime());

}

mCharging = true;

//上报新的充电状态

maybeReportNewChargingState();

} else if(BatteryManager.ACTION_DISCHARGING.equals(action)) {

if(DEBUG) {

Slog.d(TAG, "Disconnected from power.");

}

mCharging = false;

//上报新的充电状态

maybeReportNewChargingState();

}

}

}

@Override

public void dumpControllerState(PrintWriterpw) {

pw.println("Batt.");

pw.println("Stablepower: " + mChargeTracker.isOnStablePower());

synchronized(mTrackedTasks) {

Iterator<JobStatus> it = mTrackedTasks.iterator();

if(it.hasNext()) {

pw.print(String.valueOf(it.next().hashCode()));

}

while(it.hasNext()) {

pw.print("," + String.valueOf(it.next().hashCode()));

}

pw.println();

}

}

}

5.AppIdleController:

该控制器的大致实现流程:

初始化该控制器时,添加一个继承了UsageStatsManagerInternal.AppIdleStateChangeListener的APP空闲状态监听器来监听APP的空闲状态。

如果应用的空闲状态发生改变,会调用onAppIdleStateChanged方法,在该方法中循环判断空闲状态发生变化的应用是否在追踪列表中,在则调用监听器的onControllerStateChanged方法;

如果假释状态变化时,会调用onParoleStateChanged方法,该方法中的处理逻辑和onAppIdleStateChanged方法中一致。

下面看下代码实现部分:

public class AppIdleController extends StateController {

private static finalString LOG_TAG = "AppIdleController";

private static finalboolean DEBUG = false;

// Singletonfactory

private staticObject sCreationLock = new Object();

private static volatileAppIdleController sController;

finalArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();

private finalUsageStatsManagerInternal mUsageStatsInternal;

booleanmAppIdleParoleOn;

public static AppIdleController get(JobSchedulerServiceservice) {

synchronized(sCreationLock) {

if(sController == null) {

sController = new AppIdleController(service, service.getContext());

}

returnsController;

}

}

private AppIdleController(StateChangedListenerstateChangedListener, Context context) {

super(stateChangedListener,context);

mUsageStatsInternal =LocalServices.getService(UsageStatsManagerInternal.class);

mAppIdleParoleOn = mUsageStatsInternal.isAppIdleParoleOn();

mUsageStatsInternal.addAppIdleStateChangeListener(newAppIdleStateChangeListener());

}

@Override

public void maybeStartTrackingJob(JobStatusjobStatus) {

synchronized (mTrackedTasks) {

// 把任务添加到追踪列表

mTrackedTasks.add(jobStatus);

// 获取任务所在应用的包名

StringpackageName = jobStatus.job.getService().getPackageName();

// 判断该应用是否空处于闲状态

final booleanappIdle = !mAppIdleParoleOn &&mUsageStatsInternal.isAppIdle(packageName,

jobStatus.uId, jobStatus.getUserId());

if(DEBUG) {

Slog.d(LOG_TAG, "Start tracking, setting idle state of "

+ packageName + " to " +appIdle);

}

// 设置任务的空闲约束不满足状态

jobStatus.appNotIdleConstraintSatisfied.set(!appIdle);

}

}

@Override

public void maybeStopTrackingJob(JobStatusjobStatus) {

synchronized(mTrackedTasks) {

mTrackedTasks.remove(jobStatus);

}

}

@Override

public void dumpControllerState(PrintWriterpw) {

pw.println("AppIdle");

pw.println("ParoleOn: " + mAppIdleParoleOn);

synchronized(mTrackedTasks) {

for(JobStatus task : mTrackedTasks) {

pw.print(task.job.getService().getPackageName());

pw.print(":idle=" +!task.appNotIdleConstraintSatisfied.get());

pw.print(", ");

}

pw.println();

}

}

void setAppIdleParoleOn(booleanisAppIdleParoleOn) {

// Flag ifany app's idle state has changed

booleanchanged = false;

synchronized(mTrackedTasks) {

if(mAppIdleParoleOn == isAppIdleParoleOn) {

return;

}

mAppIdleParoleOn = isAppIdleParoleOn;

// 循环判断是否有应用的空闲状态发生变化

for(JobStatus task : mTrackedTasks) {

String packageName = task.job.getService().getPackageName();

finalboolean appIdle = !mAppIdleParoleOn &&mUsageStatsInternal.isAppIdle(packageName,

task.uId, task.getUserId());

if(DEBUG) {

Slog.d(LOG_TAG, "Setting idle state of " + packageName + "to " + appIdle);

}

if(task.appNotIdleConstraintSatisfied.get() == appIdle) {

task.appNotIdleConstraintSatisfied.set(!appIdle);

changed = true;

}

}

}

// 如果应用的空闲状态发生变化,则调用监听器的onControllerStateChanged方法

if(changed) {

mStateChangedListener.onControllerStateChanged();

}

}

private class AppIdleStateChangeListener

extends UsageStatsManagerInternal.AppIdleStateChangeListener{

@Override

public voidonAppIdleStateChanged(String packageName, int userId, boolean idle) {

booleanchanged = false;

synchronized(mTrackedTasks) {

// 如果已经是空闲状态,则直接返回

if(mAppIdleParoleOn) {

return;

}

// 循环判断空闲状态发生变化的应用是否在追踪列表中

for(JobStatus task : mTrackedTasks) {

if (task.job.getService().getPackageName().equals(packageName)

&&task.getUserId() == userId) {

//判断任务的空闲状态是否发生改变

if (task.appNotIdleConstraintSatisfied.get() != !idle) {

if (DEBUG) {

Slog.d(LOG_TAG, "AppIdle state changed, setting idle state of "

+packageName + " to " + idle);

}

task.appNotIdleConstraintSatisfied.set(!idle);

changed = true;

}

}

}

}

if(changed) {

// 调用监听器的onControllerStateChanged方法

mStateChangedListener.onControllerStateChanged();

}

}

@Override

public voidonParoleStateChanged(boolean isParoleOn) {

if(DEBUG) {

Slog.d(LOG_TAG, "Parole on: " + isParoleOn);

}

//假释应用空闲

setAppIdleParoleOn(isParoleOn);

}

}

}

上面5种约束条件的实现都差不多,在maybeStartTrackingJob方法中添加设置有各自约束的任务,在maybeStopTrackingJob方法中移除任务。然后监听各自关心的状态是否发生改变或得到满足,发生变化则调用JobSchedulerService类的onControllerStateChanged方法,得到满足则调用onRunJobNow方法:

/**

* 当某个控制器状态发生变化时,向JobSchedulerService.JobHandler发送一条消息,以便将列表中某个任务开启或停止执行

*/

@Override

public void onControllerStateChanged() {

mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();

}

@Override

public void onRunJobNow(JobStatus jobStatus) {

// 向Handler发送消息,开始执行任务jobStatus

mHandler.obtainMessage(MSG_JOB_EXPIRED, jobStatus).sendToTarget();

}

2.初始化JobHandler

那么接下来就看下JobSchedulerService的内部类JobHandler的初始化以及handleMessage方法:

/**

* 等待执行任务列表。JobServiceContext类将会接收到该列表中可以开始执行的任务

*/

final ArrayList<JobStatus> mPendingJobs = newArrayList<>();

/**

* Track Servicesthat have currently active or pending jobs. The index is provided by

* {@linkJobStatus#getServiceToken()}

*/

final List<JobServiceContext> mActiveServices = newArrayList<>();

private class JobHandler extends Handler {

public JobHandler(Looperlooper) {

super(looper);

}

@Override

public void handleMessage(Messagemessage) {

synchronized(mJobs) {

// 如果没有准备好执行任务则直接返回

if(!mReadyToRock) {

return;

}

}

switch(message.what) {

caseMSG_JOB_EXPIRED:

synchronized(mJobs) {

// 从消息中获取到要执行的任务

JobStatus runNow = (JobStatus)message.obj;

// runNow为null时所有准备好的任务都要开始执行

if (runNow != null && !mPendingJobs.contains(runNow)

&&mJobs.containsJob(runNow)) {

// 把要执行的任务添加到等待执行任务列表

mPendingJobs.add(runNow);

}

// 遍历任务列表,把准备好执行的任务添加到等待执行任务列表,把准备好取消的正在运行的任务取消

queueReadyJobsForExecutionLockedH();

}

break;

caseMSG_CHECK_JOB:

synchronized(mJobs) {

// 检查任务列表,把符合执行要求的添加到等待执行任务列表中

maybeQueueReadyJobsForExecutionLockedH();

}

break;

}

// 开始执行等待执行任务列表中的任务

maybeRunPendingJobsH();

// Don'tremove JOB_EXPIRED in case one came along while processing the queue.

removeMessages(MSG_CHECK_JOB);

}

/**

* 遍历任务列表,把准备好执行的任务添加到等待执行任务列表,把准备好取消的正在运行的任务取消

*/

private void queueReadyJobsForExecutionLockedH(){

// 取出任务

ArraySet<JobStatus> jobs = mJobs.getJobs();

if (DEBUG){

Slog.d(TAG, "queuing all ready jobs for execution:");

}

for (int i=0;i<jobs.size(); i++) {

JobStatus job = jobs.valueAt(i);

// 判断任务是否准备好执行

if(isReadyToBeExecutedLocked(job)) {

if(DEBUG) {

Slog.d(TAG, "    queued" + job.toShortString());

}

// 把任务添加到等待执行任务列表中

mPendingJobs.add(job);

// 判断任务是否准备好取消

} else if(isReadyToBeCancelledLocked(job)) {

// 取消正在运行的任务

stopJobOnServiceContextLocked(job);

}

}

if (DEBUG) {

final intqueuedJobs = mPendingJobs.size();

if(queuedJobs == 0) {

Slog.d(TAG, "No jobs pending.");

} else{

Slog.d(TAG, queuedJobs + " jobs queued.");

}

}

}

/**

* 任务的状态发生改变时,检查所有任务,并把符合开始执行要求的任务添加到等待执行任务列表中。

*/

private void maybeQueueReadyJobsForExecutionLockedH(){

// 记录满足充电条件的任务数量

intchargingCount = 0;

// 记录满足空闲状态的任务数量

intidleCount =  0;

// 记录后退任务的数量

intbackoffCount = 0;

// 记录满足连接任务的数量

intconnectivityCount = 0;

// 准备好执行任务的列表

List<JobStatus> runnableJobs = new ArrayList<JobStatus>();

ArraySet<JobStatus> jobs = mJobs.getJobs();

for (int i=0;i<jobs.size(); i++) {

JobStatus job = jobs.valueAt(i);

// 判断任务是否准备好执行

if(isReadyToBeExecutedLocked(job)) {

// 判断任务执行失败的次数是否大于0

if(job.getNumFailures() > 0) {

backoffCount++;

}

// 判断是否满足任务的空闲状态要求

if(job.hasIdleConstraint()) {

idleCount++;

}

// 判断是否满足任务的连接要求

if(job.hasConnectivityConstraint() || job.hasUnmeteredConstraint()) {

connectivityCount++;

}

// 判断是否满足任务的充电要求

if(job.hasChargingConstraint()) {

chargingCount++;

}

// 把准备好执行的任务添加到runnableJobs列表中

runnableJobs.add(job);

// 判断任务是否准备好取消执行

} else if(isReadyToBeCancelledLocked(job)) {

// 取消正在执行的任务

stopJobOnServiceContextLocked(job);

}

}

if (backoffCount > 0 ||

idleCount >= MIN_IDLE_COUNT ||

connectivityCount >= MIN_CONNECTIVITY_COUNT ||

chargingCount >= MIN_CHARGING_COUNT ||

runnableJobs.size() >= MIN_READY_JOBS_COUNT) {

if(DEBUG) {

Slog.d(TAG, "maybeQueueReadyJobsForExecutionLockedH: Runningjobs.");

}

for (inti=0; i<runnableJobs.size(); i++) {

// 把准备好执行的任务添加到等待执行任务列表中

mPendingJobs.add(runnableJobs.get(i));

}

} else {

if(DEBUG) {

Slog.d(TAG, "maybeQueueReadyJobsForExecutionLockedH: Not runninganything.");

}

}

if (DEBUG){

Slog.d(TAG, "idle=" + idleCount + " connectivity=" +

connectivityCount + " charging=" + chargingCount + "tot=" +

runnableJobs.size());

}

}

/**

* 把任务添加到等待执行列表中的条件:

*      - It's ready.

*      - It's not pending.

*      -It's not already running on a JSC.

*      - The user that requested the job isrunning.

*/

private booleanisReadyToBeExecutedLocked(JobStatus job) {

final booleanjobReady = job.isReady();

final booleanjobPending = mPendingJobs.contains(job);

final booleanjobActive = isCurrentlyActiveLocked(job);

final booleanuserRunning = mStartedUsers.contains(job.getUserId());

if (DEBUG){

Slog.v(TAG, "isReadyToBeExecutedLocked: " +job.toShortString()

+ " ready=" + jobReady + " pending=" + jobPending

+ " active=" + jobActive + " userRunning=" +userRunning);

}

returnuserRunning && jobReady && !jobPending && !jobActive;

}

/**

* 取消一个激活任务的条件:

*      - It's not ready

*      - It's running on a JSC.

*/

private booleanisReadyToBeCancelledLocked(JobStatus job) {

return!job.isReady() && isCurrentlyActiveLocked(job);

}

/**

* 运行等待执行任务列表中的任务

*/

private void maybeRunPendingJobsH(){

/*要开始执行任务了,故这里可以增加判断,如果是息屏状态或非充电状态则直接return*/

synchronized(mJobs) {

// 如果设备处于空闲状态,则直接返回

if(mDeviceIdleMode) {

return;

}

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;

//系统初始化时会循环给mActiveServices添加jsc,而循环的次数是:ActivityManager.isLowRamDeviceStatic()? 1 : 3

for(int i=0; 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 (DEBUG) {

Slog.d(TAG, "About to run job "

+nextPending.getJob().getService().toString());

}

// 调用JobServiceContext的executeRunnableJob方法执行任务

if (!availableContext.executeRunnableJob(nextPending)) {

if (DEBUG) {

Slog.d(TAG, "Errorexecuting " + nextPending);

}

// 如果任务不能正常执行,则从mJobs列表中移除该任务

mJobs.remove(nextPending);

}

it.remove();

}

}

}

}

}

// 判断任务是否在激活状态

private boolean isCurrentlyActiveLocked(JobStatus job) {

for (int i=0;i<mActiveServices.size(); i++) {

JobServiceContext serviceContext = mActiveServices.get(i);

finalJobStatus running = serviceContext.getRunningJob();

if (running!= null && running.matches(job.getUid(), job.getJobId())) {

return true;

}

}

return false;

}

// 取消正在运行的任务

private boolean stopJobOnServiceContextLocked(JobStatusjob) {

for (int i=0;i<mActiveServices.size(); i++) {

JobServiceContextjsc = mActiveServices.get(i);

finalJobStatus executing = jsc.getRunningJob();

if(executing != null && executing.matches(job.getUid(), job.getJobId())){

jsc.cancelExecutingJob();

return true;

}

}

return false;

}

执行任务时调用的是JobServiceContext类中的executeRunnableJob方法:

/**

* 执行传递过来的任务,调用者必须先检查context可用以确保能正常执行任务。

* @param job Thestatus of the job that we are going to run.

* @return True ifthe job is valid and is running. False if the job cannot be executed.

*/

boolean executeRunnableJob(JobStatus job) {

synchronized(mLock) {

// 如果context无效则直接返回false

if(!mAvailable) {

Slog.e(TAG, "Starting new runnable but context is unavailable >Error.");

return false;

}

mRunningJob= job;

// deadline约束得到满足并且上次运行时间小于开机时间

final booleanisDeadlineExpired =

job.hasDeadlineConstraint() &&

(job.getLatestRunTimeElapsed() < SystemClock.elapsedRealtime());

mParams = newJobParameters(this, job.getJobId(), job.getExtras(), isDeadlineExpired);

mExecutionStartTimeElapsed = SystemClock.elapsedRealtime();

mVerb =VERB_BINDING;

scheduleOpTimeOut();

// 以任务所在服务的组件名创建Intent

finalIntent intent = new Intent().setComponent(job.getServiceComponent());

/*这里可以为intent put一个参数,在ActiveServices类的bindServiceLocked方法

* 中取出该参数以判断服务是从JobSchedulerService开启的,以便禁止服务启动来达到禁止

* 应用通过JobSchedulerService的方式来自启的目的*/

// 通过bindServiceAsUser的方式开启任务所在的服务

booleanbinding = mContext.bindServiceAsUser(intent, this,

Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND,

newUserHandle(job.getUserId()));

if(!binding) {

if(DEBUG) {

Slog.d(TAG, job.getServiceComponent().getShortClassName() + "unavailable.");

}

mRunningJob = null;

mParams= null;

mExecutionStartTimeElapsed= 0L;

removeOpTimeOut();

return false;

}

try {

mBatteryStats.noteJobStart(job.getName(), job.getUid());

} catch(RemoteException e) {

//Whatever.

}

mAvailable= false;

return true;

}

}

上面bindServiceAsUser方法中传递的服务是this,故绑定成功后调用的是JobServiceContext类中的onServiceConnected方法:

/**

* 在onServiceConnected或unbindService中获取或释放wakelock。当服务unbound时停止向客户端发送任务,直到持有wakelock。

* @param name Theconcrete component name of the service that has been connected.

* @param serviceThe IBinder of the Service's communication channel,

*/

@Override

public void onServiceConnected(ComponentName name,IBinder service) {

JobStatusrunningJob;

synchronized(mLock) {

// Thisisn't strictly necessary b/c the JobServiceHandler is running on the main

// looperand at this point we can't get any binder callbacks from the client. Better

// safethan sorry.

runningJob= mRunningJob;

}

// 如果正在执行的任务为null或者正在执行的任务所在的组件名不等于绑定服务的组件名则停止执行任务

if (runningJob== null || !name.equals(runningJob.getServiceComponent())) {

mCallbackHandler.obtainMessage(MSG_SHUTDOWN_EXECUTION).sendToTarget();

return;

}

this.service =IJobService.Stub.asInterface(service);

finalPowerManager pm =

(PowerManager) mContext.getSystemService(Context.POWER_SERVICE);

mWakeLock =pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, runningJob.getTag());

mWakeLock.setWorkSource(newWorkSource(runningJob.getUid()));

mWakeLock.setReferenceCounted(false);

mWakeLock.acquire();

// 向mCallbackHandler发送绑定服务成功的消息

mCallbackHandler.obtainMessage(MSG_SERVICE_BOUND).sendToTarget();

}

private class JobServiceHandler extends Handler {

JobServiceHandler(Looper looper) {

super(looper);

}

@Override

public void handleMessage(Messagemessage) {

switch(message.what) {

caseMSG_SERVICE_BOUND:

// 移除掉操作超时的任务

removeOpTimeOut();

// 处理绑定成功的操作

handleServiceBoundH();

break;

. . .

default:

Slog.e(TAG, "Unrecognised message: " + message);

}

}

/** 处理绑定服务成功的操作. */

private void handleServiceBoundH(){

if (DEBUG){

Slog.d(TAG, "MSG_SERVICE_BOUND for " +mRunningJob.toShortString());

}

if (mVerb!= VERB_BINDING) {

Slog.e(TAG, "Sending onStartJob for a job that isn't pending."

+ VERB_STRINGS[mVerb]);

closeAndCleanupJobH(false /* reschedule */);

return;

}

if(mCancelled.get()) {

if(DEBUG) {

Slog.d(TAG,"Job cancelled while waiting for bind to complete. "

+ mRunningJob);

}

closeAndCleanupJobH(true /* reschedule */);

return;

}

try {

mVerb =VERB_STARTING;

scheduleOpTimeOut();

// 调用JobService的startJob方法

service.startJob(mParams);

} catch(RemoteException e) {

Slog.e(TAG, "Error sending onStart message to '" +

mRunningJob.getServiceComponent().getShortClassName() + "' ",e);

}

}

}

到这里调用到了JobService的startJob方法。下面看下JobService的实现原理:

/**

* 从JobScheduler回调方法的入口。这是处理之前安排的异步请求的基类。

* 使用时需要重写onStartJob方法来写任务的执行逻辑。

* 该服务执行运行在应用程序主线程的Handler传递过来的每个任务。这意味着你必须在thread/handler/AsyncTask

* 中实现执行的逻辑。不这样做将导致来自JobManager的任务阻塞,无法继续执行。

*/

// JobService是实现了Service的抽象类

public abstract class JobService extends Service {

private static finalString TAG = "JobService";

/**

* JobService的子类必须在Manifest中声明该权限,如:

* <serviceandroid:name="MyJobService"

*         android:permission="android.permission.BIND_JOB_SERVICE" >

*     ...

*</service>

*/

public static finalString PERMISSION_BIND =

"android.permission.BIND_JOB_SERVICE";

// 调用onStartJob方法的标识符

private final intMSG_EXECUTE_JOB = 0;

// 调用onStopJob方法的标识符

private final intMSG_STOP_JOB = 1;

// 任务完成的标识符

private final intMSG_JOB_FINISHED = 2;

// mHandler的锁对象

private finalObject mHandlerLock = new Object();

// 处理post传来的任务:负责调用到客户端的逻辑和处理系统回调

@GuardedBy("mHandlerLock")

JobHandlermHandler;

// 服务的Binder,后面重写的onBind方法中会返回该Binder的实例,

// mBinder是IJobService.aidl的接口的一个对象

IJobService mBinder = new IJobService.Stub(){

@Override

public voidstartJob(JobParameters jobParams) {

ensureHandler();

// 把jobParams封装成一个消息

Messagem = Message.obtain(mHandler, MSG_EXECUTE_JOB, jobParams);

// 把消息发送给mHandler

m.sendToTarget();

}

@Override

public voidstopJob(JobParameters jobParams) {

ensureHandler();

Messagem = Message.obtain(mHandler, MSG_STOP_JOB, jobParams);

m.sendToTarget();

}

};

/** @hide */

void ensureHandler(){

synchronized(mHandlerLock) {

if(mHandler == null) {

// 创建Handler对象时传递的是主线程的looper,即消息会在主线程中处理

mHandler = new JobHandler(getMainLooper());

}

}

}

/**

* 运行在应用程序的主线程 - callbacks are meant to offboard work tosome other

*(app-specified) mechanism.

* @hide

*/

class JobHandlerextends Handler {

JobHandler(Looper looper) {

super(looper);

}

@Override

public voidhandleMessage(Message msg) {

// 从msg消息中取出JobParameters对象

finalJobParameters params = (JobParameters) msg.obj;

switch(msg.what) {

caseMSG_EXECUTE_JOB:

try {

// 执行JobService中的onStartJob方法,该方法是一个抽象方法,需要子类重写

boolean workOngoing = JobService.this.onStartJob(params);

ackStartMessage(params, workOngoing);

} catch (Exception e) {

Log.e(TAG, "Error while executing job: " + params.getJobId());

throw new RuntimeException(e);

}

break;

caseMSG_STOP_JOB:

try {

// 执行JobService中的onStopJob方法,该方法是一个抽象方法,需要子类重写

boolean ret = JobService.this.onStopJob(params);

ackStopMessage(params, ret);

} catch (Exception e) {

Log.e(TAG, "Application unable to handle onStopJob.", e);

throw new RuntimeException(e);

}

break;

case MSG_JOB_FINISHED:

// 从消息中获取任务是否需要重试

final boolean needsReschedule = (msg.arg2 == 1);

// 从参数中获取回调接口

IJobCallback callback = params.getCallback();

if (callback != null) {

try {

// 调用回调接口中的jobFinished方法

callback.jobFinished(params.getJobId(), needsReschedule);

} catch (RemoteException e) {

Log.e(TAG, "Errorreporting job finish to system: binder has gone" +

"away.");

}

} else {

Log.e(TAG, "finishJob() called for a nonexistent job id.");

}

break;

default:

Log.e(TAG, "Unrecognised message received.");

break;

}

}

private voidackStartMessage(JobParameters params,

booleanworkOngoing) {

// 获取params的回调接口

finalIJobCallback callback = params.getCallback();

final intjobId = params.getJobId();

if(callback != null) {

try{

//调用回调接口中的acknowledgeStartMessage方法

callback.acknowledgeStartMessage(jobId, workOngoing);

} catch(RemoteException e) {

Log.e(TAG, "System unreachable for starting job.");

}

} else{

// 任务已经处理完了

if(Log.isLoggable(TAG, Log.DEBUG)) {

Log.d(TAG,

"Attempting toack a job that has already been processed.");

}

}

}

private voidackStopMessage(JobParameters params, boolean reschedule) {

finalIJobCallback callback = params.getCallback();

final intjobId = params.getJobId();

if (callback!= null) {

try{

callback.acknowledgeStopMessage(jobId, reschedule);

} catch(RemoteExceptione) {

Log.e(TAG, "System unreachable for stopping job.");

}

} else {

if(Log.isLoggable(TAG, Log.DEBUG)) {

Log.d(TAG, "Attempting to ack a job that has already beenprocessed.");

}

}

}

}

// JobService重写了onBind方法,返回mBinder的一个对象

/** @hide */

public finalIBinder onBind(Intent intent) {

returnmBinder.asBinder();

}

/**

* 抽象方法,需要子类重写该方法,在该方法中写执行任务的逻辑,该方法运行在主线程

*

* @paramparams 任务相关的参数,包括在创建任务时自己设定的所有参数

* @return true:如果要执行的任务比较耗时,并且当任务完成时需要调用jobFinished()方法来通知系统

*         false:如果要执行的任务不耗时

*

*/

public abstractboolean onStartJob(JobParameters params);

/**

* 抽象方法,需要子类重写该方法,在该方法中写任务停止时的逻辑,该方法运行在主线程

* 该方法被调用场景:在执行任务时,规定的要求已不再满足。

* 如果不重写这个方法,系统可能不再为你的应用程序持有wakelock

*

* @paramparams 任务相关的参数.

* @returntrue:基于在创建任务时设定的重试机制指示JobManager是否要重新安排任务。

*         false:丢弃本次任务。

* 无论返回什么值,任务必须停止执行。

*/

public abstractboolean onStopJob(JobParameters params);

/**

* 通知JobManager任务已经执行完成的回调方法。该方法可以从任何线程中调用,因为该方法最终会在应用程序的主线程中执行。

* 当系统收到这个消息时,它会释放持有的wakelock锁。

* 可以根据needsReschedule参数写执行后的操作,基于默认值或使用setBackoffCriteria方法设置的值回退任务的定时器。

* 运行在空闲模式的任务是不能回退的。这可能会导致任务重复添加到任务队列中,并且在未来的某个空闲时间内重复执行该任务。

*

* @paramparams 通过onStartJob方法传递的JobParameters参数

* @paramneedsReschedule true:如果该任务需要重写安排

*                        false:其他情况

*/

public final voidjobFinished(JobParameters params, boolean needsReschedule) {

ensureHandler();

// 把参数封装成消息

Message m =Message.obtain(mHandler, MSG_JOB_FINISHED, params);

m.arg2 =needsReschedule ? 1 : 0;

// 把消息发送给mHandler

m.sendToTarget();

}

}

看下IJobService.aidl的定义:

package android.app.job;

import android.app.job.JobParameters;

/**

* 这是一个framework用来与继承自JobService的应用程序代码进行通信的接口。

* 应用程序代码不直接实现该接口,而是继承自JobService。

* {@hide}

*/

oneway interface IJobService {

/** Beginexecution of application's job. */

void startJob(inJobParameters jobParams);

/** Stopexecution of application's job. */

void stopJob(inJobParameters jobParams);

}

上面接口定义中用到了oneway,意思是如果调用者和被调用者在同一个进程则同步执行,如果不在同一个进程则异步执行,即:调用该接口中的方法后不需要等待方法执行完成。

3.初始化JobSchedulerStub代理对象

下面就看下JobSchedulerService的内部类JobSchedulerStub,它是一个Binder接口的代理类:

/**

* Binder stubtrampoline implementation

*/

final class JobSchedulerStub extends IJobScheduler.Stub {

/** Cachedetermination of whether a given app can persist jobs

* key is uidof the calling app; value is undetermined/true/false

*/

private finalSparseArray<Boolean> mPersistCache = new SparseArray<Boolean>();

// 执行只有应用程序自己可以调度运行在自己服务中的任务,以及验证服务是否有BIND_JOB_SERVICE权限。

private void enforceValidJobRequest(intuid, JobInfo job) {

finalIPackageManager pm = AppGlobals.getPackageManager();

// 获取任务所在服务组件名

finalComponentName service = job.getService();

try {

// 获取服务相关信息

ServiceInfo si = pm.getServiceInfo(service, 0,UserHandle.getUserId(uid));

// 如果服务相关信息为null则抛异常

if (si== null) {

thrownew IllegalArgumentException("No such service " + service);

}

// 如果调用者的uid和服务所在应用程序的uid不同则抛异常

if (si.applicationInfo.uid != uid) {

thrownew IllegalArgumentException("uid " + uid +

" cannot schedule job in " + service.getPackageName());

}

// 如果服务没有设置BIND_JOB_SERVICE权限,则抛异常

if(!JobService.PERMISSION_BIND.equals(si.permission)) {

thrownew IllegalArgumentException("Scheduled service " + service

+ " does not require android.permission.BIND_JOB_SERVICEpermission");

}

} catch (RemoteException e) {

//Can't happen; the Package Manager is in this same process

}

}

private booleancanPersistJobs(int pid, int uid) {

// 检查服务是否可以是永久性的执行任务

final booleancanPersist;

synchronized(mPersistCache) {

Booleancached = mPersistCache.get(uid);

// 如果cached不为null,则直接取值返回

if(cached != null) {

canPersist = cached.booleanValue();

} else{

// 永久性任务相当于在手机启动时运行,所以它所在的app需要声明RECEIVE_BOOT_COMPLETED权限

intresult = getContext().checkPermission(

android.Manifest.permission.RECEIVE_BOOT_COMPLETED, pid, uid);

canPersist = (result == PackageManager.PERMISSION_GRANTED);

mPersistCache.put(uid, canPersist);

}

}

returncanPersist;

}

//IJobScheduler implementation

@Override

public int schedule(JobInfojob) throws RemoteException {

if (DEBUG){

Slog.d(TAG, "Scheduling job: " +job.toString());

}

// 获取调用者pid

final intpid = Binder.getCallingPid();.

// 获取调用者uid

final intuid = Binder.getCallingUid();

// 判断服务的有效性

enforceValidJobRequest(uid,job);

// 服务是否是永久性的判断

if(job.isPersisted()) {

// 根据pid、uid判断服务是否可以是永久性的,如果不是则抛异常

if(!canPersistJobs(pid, uid)) {

thrownew IllegalArgumentException("Error: requested job be persistedwithout"

+ " holding RECEIVE_BOOT_COMPLETED permission.");

}

}

long ident= Binder.clearCallingIdentity();

try {

// 调用JobSchedulerService类的schedule方法

returnJobSchedulerService.this.schedule(job, uid);

} finally {

Binder.restoreCallingIdentity(ident);

}

}

@Override

publicList<JobInfo> getAllPendingJobs() throws RemoteException {

final int uid= Binder.getCallingUid();

long ident= Binder.clearCallingIdentity();

try {

// 调用JobSchedulerService类的getPendingJobs方法

returnJobSchedulerService.this.getPendingJobs(uid);

} finally {

Binder.restoreCallingIdentity(ident);

}

}

@Override

public void cancelAll()throws RemoteException {

final intuid = Binder.getCallingUid();

long ident= Binder.clearCallingIdentity();

try {

// 调用JobSchedulerService类的cancelJobsForUid方法

JobSchedulerService.this.cancelJobsForUid(uid);

} finally {

Binder.restoreCallingIdentity(ident);

}

}

@Override

public void cancel(intjobId) throws RemoteException {

final int uid = Binder.getCallingUid();

long ident= Binder.clearCallingIdentity();

try {

// 调用JobSchedulerService类的cancelJob方法

JobSchedulerService.this.cancelJob(uid, jobId);

} finally {

Binder.restoreCallingIdentity(ident);

}

}

/**

*"dumpsys" infrastructure

*/

@Override

public void dump(FileDescriptorfd, PrintWriter pw, String[] args) {

getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,TAG);

longidentityToken = Binder.clearCallingIdentity();

try {

JobSchedulerService.this.dumpInternal(pw);

} finally {

Binder.restoreCallingIdentity(identityToken);

}

}

};

4.初始化任务主列表

接着看JobStore类的initAndGet方法:

/** 使用JobSchedulerService初始化JobStore. */

static JobStore initAndGet(JobSchedulerServicejobManagerService) {

synchronized(sSingletonLock) {

if(sSingleton == null) {

sSingleton = new JobStore(jobManagerService.getContext(),

Environment.getDataDirectory());

}

returnsSingleton;

}

}

/**

* 构造任务存储的实例。结果是一个会从磁盘中读出的块

* Construct theinstance of the job store. This results in a blocking read from disk.

*/

private JobStore(Context context, File dataDir) {

mContext =context;

mDirtyOperations = 0;

File systemDir= new File(dataDir, "system");

File jobDir = newFile(systemDir, "job");

// 创建data/system/job目录

jobDir.mkdirs();

// 在data/system/job目录下创建jobs.xml文件

mJobsFile = newAtomicFile(new File(jobDir, "jobs.xml"));

mJobSet = newArraySet<JobStatus>();

// 从磁盘中读取任务map存放在mJobSet中,xml文件的解析,不再粘贴源码

readJobMapFromDisk(mJobSet);

}

下面看下JobSchedulerService类的onStart方法:

@Override

public void onStart() {

// 调用父类SystemService的publishBinderService方法将mJobSchedulerStub发布出去

publishBinderService(Context.JOB_SCHEDULER_SERVICE, mJobSchedulerStub);

}

SystemService类中的publishBinderService方法:

/**

* 发布服务,以便其他服务或应用程序能调用该服务。

*/

protected final void publishBinderService(String name,IBinder service) {

publishBinderService(name, service, false);

}

/**

* 发布服务,以便其他服务或应用程序能调用该服务。

*/

protected final void publishBinderService(String name,IBinder service,

booleanallowIsolated) {

// 把服务添加到ServiceManager中,以便其他服务或应用程序能够调用该服务

//getSystemService时就是根据name获取到该服务的

ServiceManager.addService(name, service, allowIsolated);

}

到这里JobSchedulerService的启动流程就分析完了。在分析启动流程的时候,任务各种约束的添加任务、移除任务、监听任务的状态变化以及任务的执行等操作也都跟着分析了。

下面分析下使用JobSchedulerService的流程,主要是看怎么把任务添加到主任务列表中并开始追踪的。

应用通过getSystemService方法获取系统服务时,会调用到ContextImpl类的getSystemService方法中:

@Override

public Object getSystemService(String name) {

returnSystemServiceRegistry.getSystemService(this, name);

}

SystemServiceRegistry类中的getSystemService方法:

/**

* Gets a systemservice from a given context.

*/

public static Object getSystemService(ContextImpl ctx,String name) {

// 根据服务名从map中取出ServiceFetcher

ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);

// 如果fetcher不为null,则从fetcher中根据ctx取出对应的服务并返回

return fetcher!= null ? fetcher.getService(ctx) : null;

}

但是在SystemServiceRegistry类的静态代码块中注册服务时,就是把上面发布到ServiceManager中的Binder代理对象mJobSchedulerStub返回给createService方法:

static {

. . .

registerService(Context.JOB_SCHEDULER_SERVICE, JobScheduler.class,

newStaticServiceFetcher<JobScheduler>() {

@Override

publicJobScheduler createService() {

IBinderb = ServiceManager.getService(Context.JOB_SCHEDULER_SERVICE);

return newJobSchedulerImpl(IJobScheduler.Stub.asInterface(b));

}});

}

private static <T> void registerService(StringserviceName, Class<T> serviceClass,

ServiceFetcher<T> serviceFetcher) {

SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);

SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);

}

static abstract interface ServiceFetcher<T> {

T getService(ContextImplctx);

}

static abstract class StaticServiceFetcher<T> implementsServiceFetcher<T> {

private TmCachedInstance;

@Override

public final T getService(ContextImplunused) {

// 单例懒加载模式,具体的创建由子类实现

synchronized(StaticServiceFetcher.this) {

if(mCachedInstance == null) {

mCachedInstance = createService();

}

returnmCachedInstance;

}

}

public abstractT createService();

}

看下JobSchedulerImpl类:

public class JobSchedulerImpl extends JobScheduler {

IJobSchedulermBinder;

/* package */JobSchedulerImpl(IJobScheduler binder) {

mBinder =binder;

}

@Override

public int schedule(JobInfojob) {

try {

return mBinder.schedule(job);

} catch(RemoteException e) {

returnJobScheduler.RESULT_FAILURE;

}

}

. . .

}

也就是说,其他应用通过getSystemService(Context.JOB_SCHEDULER_SERVICE)方法获取到的JobScheduler对象中的Binder对象其实就是JobSchedulerService类中的JobSchedulerStub代理对象。

下面看下其他应用调用JobScheduler的schedule方法的流程,由上面分析知,其他应用通过JobScheduler对象调用schedule方法其实是调用的JobSchedulerService类中的JobSchedulerStub代理对象的schedule方法。由上面代理对象的schedule方法知,它调用了JobSchedulerService类的schedule方法:

public int schedule(JobInfo job, int uId) {

JobStatusjobStatus = new JobStatus(job, uId);

// 如果任务已经在等待队列或已经在执行则从等待队列中移除或取消任务的执行

cancelJob(uId,job.getId());

// 开始追踪任务

startTrackingJob(jobStatus);

// 向Handler发送检查任务的消息

mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();

returnJobScheduler.RESULT_SUCCESS;

}

private void startTrackingJob(JobStatus jobStatus) {

boolean update;

booleanrocking;

synchronized(mJobs) {

// 把新任务添加到主列表中

update =mJobs.add(jobStatus);

rocking =mReadyToRock;

}

if (rocking) {

// 循环获取所有控制器,并回调控制器的开始追踪方法

for (int i=0;i<mControllers.size(); i++) {

StateController controller = mControllers.get(i);

if(update) {

controller.maybeStopTrackingJob(jobStatus);

}

controller.maybeStartTrackingJob(jobStatus);

}

}

}

到这里,任务的添加、追踪逻辑就分析完了。

android系统(63)---Jobscheduler运行机制详解相关推荐

  1. JavaScript 运行机制详解(理解同步、异步和事件循环)

    1.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. Java ...

  2. Android 系统属性读取和设置详解

    Android 系统属性读取和设置详解 一.在adb中进行属性读取和设置 1.Settings Provider设置和读取 获取 设置 2.SystemProperties属性读取和设置 二.Andr ...

  3. python语言程序的特点_Python语言概述及其运行机制详解

    即日起,我们将打开一个新的编程世界的大门--Python语言.Python是一种跨平台的计算机程序设计语言.是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新 ...

  4. Python语言概述及其运行机制详解

    即日起,我们将打开一个新的编程世界的大门--Python语言.Python是一种跨平台的计算机程序设计语言.是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新 ...

  5. SSL / TLS 协议运行机制详解

    转载自  SSL / TLS 协议运行机制详解 互联网的通信安全,建立在SSL/TLS协议之上. 本文简要介绍SSL/TLS协议的运行机制.文章的重点是设计思想和运行过程,不涉及具体的实现细节.如果想 ...

  6. 我看朴灵评注阮一峰的《JavaScript 运行机制详解:再谈Event Loop》

    阮一峰和朴灵对我来说都是大牛,他们俩的书我都买过,阮老师的译作<软件随想录>和朴灵的<深入浅出node.js>.这个事情已经过了4个月了,所以我拿来讲应该也没啥问题. 这件事情 ...

  7. 【大数据day14】——MapReduce的运行机制详解(案列:Reduce 端实现 JOIN, Map端实现 JOIN,求共同好友)

    文章目录 1 .MapReduce的运行机制详解 1.1:MapTask 工作机制 详细步骤 配置 1.2 :ReduceTask 工作机制 详细步骤 1.3:Shuffle 过程 2. 案例: Re ...

  8. MapTask运行机制详解以及Map任务的并行度,ReduceTask 工作机制以及reduceTask的并行度,MapReduce总体工作机制

    MapTask运行机制详解 整个Map阶段流程大体如图所示 简单概述 inputFile通过split被逻辑切分为多个split文件, 通过Record按行读取内容给map(用户自己实现的)进行处理, ...

  9. Android运行机制详解

    Android应用程序是用Java语言写的,通过aapt工具把应用程序所需要的任何数据.资源文件打包成apk文件,这个文件是一个将应用安装到手机上的一个载体. 每个android应用程序存在于不同的世 ...

最新文章

  1. SQL Server 中的ROWID
  2. 免费赠送年终汇报总结模板福利合集
  3. 全国计算机证件照要露耳朵吗,结婚证照片要露耳朵么 结婚登记照露一只耳朵行吗...
  4. python调试蓝牙适配器_我写了一个查看Android手机的蓝牙模块是否开启的代码。在AVD上调试,因为是电脑,没有蓝牙适配器,可是...
  5. Flask插件---flask_script与flask_migrate
  6. 华为Mate30 5G评测:首款5G爆品, 一步到位兼容5G双模全网通
  7. Python使用递归对任意嵌套列表进行扁平化
  8. LG_2051_[AHOI2009]中国象棋
  9. S3C2440 进行微秒级、毫秒级延时函数
  10. SWIFT显示底部的工具条
  11. CompoundButton 选中/未选中状态的按钮
  12. WS2811单线传输三通道LED驱动控制专用芯片
  13. unity 走马灯packageManager
  14. 地震数据.dat文件转.sgy文件
  15. 新手入门笔记——linux常用命令总结
  16. GlassFish安装
  17. 【春节档排片地域可视化分析】
  18. anaconda安装包
  19. excel用图标表示数据增减
  20. 第0篇日记 先立一个flag——开始有了做阅读器的想法

热门文章

  1. [设计模式] - 工厂模式
  2. html自动播放auto,为移动而生的 HTML 属性autocapitalize和autocorrect
  3. System.gc()和Runtime.gc()的区别?
  4. 黑马公开课——运行原理与GC学习笔记
  5. 响应式布局这件小事有哪些优点和缺点该怎么设计
  6. 浏览器调试时控制台出现:Uncaught SyntaxError: Unexpected identifier
  7. 编写base64图片文件
  8. 宏定义是写在.h文件里还是.c文件里
  9. 【ExtJS实践】之五 :常用语句及脚本备忘
  10. [转]Delphi过程函数传递参数的几种方式