JSS 第 5 篇 - JobSchedulerService - jobFinished

基于 Android 7.1.1 源码分析

前言

当任务完成时,应用需要手动调用 jobFinished 方法,这个方法是属于 JobService 的:
   
   
  1. public final void jobFinished(JobParameters params, boolean needsReschedule) {
  2. ensureHandler();
  3. Message m = Message.obtain(mHandler, MSG_JOB_FINISHED, params);
  4. m.arg2 = needsReschedule ? 1 : 0;
  5. m.sendToTarget();
  6. }
其实,参数很简单,这个消息 MSG_JOB_FINISHED 会发送到 JobHandler 中!

1 JS.JobHandler

进入 JobHandler 中来看看:
   
   
  1. class JobHandler extends Handler {
  2. JobHandler(Looper looper) {
  3. super(looper);
  4. }
  5. @Override
  6. public void handleMessage(Message msg) {
  7. final JobParameters params = (JobParameters) msg.obj;
  8. switch (msg.what) {
  9. ... ... ... ...
  10. case MSG_JOB_FINISHED:
  11. final boolean needsReschedule = (msg.arg2 == 1);
  12. // callback 是 JobServiceContext
  13. IJobCallback callback = params.getCallback();
  14. if (callback != null) {
  15. try {
  16. callback.jobFinished(params.getJobId(), needsReschedule);
  17. } catch (RemoteException e) {
  18. Log.e(TAG, "Error reporting job finish to system: binder has gone" + " away.");
  19. }
  20. } else {
  21. Log.e(TAG, "finishJob() called for a nonexistent job id.");
  22. }
  23. break;
  24. default:
  25. Log.e(TAG, "Unrecognised message received.");
  26. break;
  27. }
  28. }
  29. }
这里调用了 JObServiceContext 的 jobFinished 方法!

2 JSC.jobFinished

我们来看看 JobServiceContext 的 jobFinished 方法:
   
   
  1. @Override
  2. public void jobFinished(int jobId, boolean reschedule) {
  3. if (!verifyCallingUid()) {
  4. return;
  5. }
  6. mCallbackHandler.obtainMessage(MSG_CALLBACK, jobId, reschedule ? 1 : 0)
  7. .sendToTarget();
  8. }
这里先调用了 JobServiceContext 的 verifyCallingUid,校验 uid!
   
   
  1. private boolean verifyCallingUid() {
  2. synchronized (mLock) {
  3. if (mRunningJob == null || Binder.getCallingUid() != mRunningJob.getUid()) {
  4. if (DEBUG) {
  5. Slog.d(TAG, "Stale callback received, ignoring.");
  6. }
  7. return false;
  8. }
  9. return true;
  10. }
  11. }
接着发送了一个 MSG_CALLBACK 的消息给了 JobServiceHandler!

3 JSC.JobServiceHandler

接着进入了 JobServiceHandler,来看主要代码:
   
   
  1. case MSG_CALLBACK:
  2. if (DEBUG) {
  3. Slog.d(TAG, "MSG_CALLBACK of : " + mRunningJob
  4. + " v:" + VERB_STRINGS[mVerb]);
  5. }
  6. removeOpTimeOut();
  7. if (mVerb == VERB_STARTING) {
  8. final boolean workOngoing = message.arg2 == 1;
  9. handleStartedH(workOngoing);
  10. } else if (mVerb == VERB_EXECUTING || // 此时 mVerb 的状态为 VERB_EXECUTING
  11. mVerb == VERB_STOPPING) {
  12. final boolean reschedule = message.arg2 == 1;
  13. handleFinishedH(reschedule);
  14. } else {
  15. if (DEBUG) {
  16. Slog.d(TAG, "Unrecognised callback: " + mRunningJob);
  17. }
  18. }
  19. break;
调用了 handleFinishedH:
   
   
  1. private void handleFinishedH(boolean reschedule) {
  2. switch (mVerb) {
  3. case VERB_EXECUTING:
  4. case VERB_STOPPING:
  5. closeAndCleanupJobH(reschedule);
  6. break;
  7. default:
  8. Slog.e(TAG, "Got an execution complete message for a job that wasn't being" +
  9. "executed. Was " + VERB_STRINGS[mVerb] + ".");
  10. }
  11. }
这里就很简单了,调用了 closeAndCleanupJobH 来解除 bind 和将 JObServiceContext 恢复初始化!
   
   
  1. private void closeAndCleanupJobH(boolean reschedule) {
  2. final JobStatus completedJob;
  3. synchronized (mLock) {
  4. if (mVerb == VERB_FINISHED) {
  5. return;
  6. }
  7. completedJob = mRunningJob;
  8. mJobPackageTracker.noteInactive(completedJob);
  9. try {
  10. mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(),
  11. mRunningJob.getSourceUid());
  12. } catch (RemoteException e) {
  13. // Whatever.
  14. }
  15. if (mWakeLock != null) {
  16. mWakeLock.release();
  17. }
  18. mContext.unbindService(JobServiceContext.this);
  19. mWakeLock = null;
  20. mRunningJob = null;
  21. mParams = null;
  22. mVerb = VERB_FINISHED; // 状态变为 VERB_FINISHED
  23. mCancelled.set(false);
  24. service = null;
  25. mAvailable = true;
  26. }
  27. removeOpTimeOut();
  28. removeMessages(MSG_CALLBACK);
  29. removeMessages(MSG_SERVICE_BOUND);
  30. removeMessages(MSG_CANCEL);
  31. removeMessages(MSG_SHUTDOWN_EXECUTION);
  32. // 通知 JobSchedulerService,这个 job 已经 finished 了
  33. mCompletedListener.onJobCompleted(completedJob, reschedule);
  34. }
  35. }
接着,进入了 JobSchedulerService 方法中:

4 JSS.onJobCompleted

调用了 onJobCompleted 方法,来
   
   
  1. @Override
  2. public void onJobCompleted(JobStatus jobStatus, boolean needsReschedule) {
  3. if (DEBUG) {
  4. Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule);
  5. }
  6. // Do not write back immediately if this is a periodic job. The job may get lost if system
  7. // shuts down before it is added back.
  8. // 停止 track job,这里是第一次 stop,所以会将 job 从 JobStore 中删除!
  9. if (!stopTrackingJob(jobStatus, null, !jobStatus.getJob().isPeriodic())) {
  10. if (DEBUG) {
  11. Slog.d(TAG, "Could not find job to remove. Was job removed while executing?");
  12. }
  13. // We still want to check for jobs to execute, because this job may have
  14. // scheduled a new job under the same job id, and now we can run it.
  15. mHandler.obtainMessage(MSG_CHECK_JOB_GREEDY).sendToTarget();
  16. return;
  17. }
  18. // Note: there is a small window of time in here where, when rescheduling a job,
  19. // we will stop monitoring its content providers. This should be fixed by stopping
  20. // the old job after scheduling the new one, but since we have no lock held here
  21. // that may cause ordering problems if the app removes jobStatus while in here.
  22. // 判断是否要 reschedule 这个 job,如果需要,就 startTrackingJob
  23. if (needsReschedule) {
  24. JobStatus rescheduled = getRescheduleJobForFailure(jobStatus);
  25. startTrackingJob(rescheduled, jobStatus);
  26. } else if (jobStatus.getJob().isPeriodic()) {
  27. JobStatus rescheduledPeriodic = getRescheduleJobForPeriodic(jobStatus);
  28. startTrackingJob(rescheduledPeriodic, jobStatus);
  29. }
  30. reportActive();
  31. // 继续开始新一轮的 job 执行!
  32. mHandler.obtainMessage(MSG_CHECK_JOB_GREEDY).sendToTarget();
  33. }
这里和 cancel 就一样了,所以这里就不细说了!

































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值