diff options
author | Matthew Williams <mjwilliams@google.com> | 2014-07-25 11:30:40 -0700 |
---|---|---|
committer | Matthew Williams <mjwilliams@google.com> | 2014-07-29 11:11:41 -0700 |
commit | ee410da42b6b8352213f03f7725fd041f703b035 (patch) | |
tree | d79add63a7762d26f9d8396876fc8cc47ce0cb75 /tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp | |
parent | c503896a4d0cab029bca56cf7ac18ae182729a0a (diff) | |
download | frameworks_base-ee410da42b6b8352213f03f7725fd041f703b035.zip frameworks_base-ee410da42b6b8352213f03f7725fd041f703b035.tar.gz frameworks_base-ee410da42b6b8352213f03f7725fd041f703b035.tar.bz2 |
remove possible JobScheduler race in cancel()
Client can jobFinished() before getting a cancel msg.
1) Do better clean up of JobServiceContext after client jobFinished()
to remove superfluous MSG_CANCELs
2) When processing MSG_CANCEL check whether the context is still active
3) Do JobServiceContext cleanup before calling back to JobSchedulerService
Client can get a cancel msg even after calling jobFinished() (opposite to above)
1) explicitly check whether there are any MSG_CALLBACKs in the queue before
processing a MSG_CANCEL. If there are we can throw away the cancel.
Bug: 16547638
Change-Id: I90644586c7895a9ce97de752a5d657faf7f74b78
Diffstat (limited to 'tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp')
-rw-r--r-- | tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java index bf8e887..e2c3be0 100644 --- a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java +++ b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/service/TestJobService.java @@ -20,16 +20,21 @@ import android.app.job.JobInfo; import android.app.job.JobScheduler; import android.app.job.JobParameters; import android.app.job.JobService; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.os.AsyncTask; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.util.Log; +import android.util.SparseArray; import com.android.demo.jobSchedulerApp.MainActivity; +import java.util.HashMap; import java.util.LinkedList; +import java.util.Random; /** @@ -75,39 +80,76 @@ public class TestJobService extends JobService { @Override public boolean onStartJob(JobParameters params) { - jobParamsMap.add(params); + Log.i(TAG, "on start job: " + params.getJobId()); + currentId++; + jobParamsMap.put(currentId, params); + final int currId = this.currentId; + Log.d(TAG, "putting :" + currId + " for " + params.toString()); + Log.d(TAG, " pulled: " + jobParamsMap.get(currId)); if (mActivity != null) { mActivity.onReceivedStartJob(params); } - Log.i(TAG, "on start job: " + params.getJobId()); + + // Spin off a new task on a separate thread for a couple seconds. + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... voids) { + try { + Log.d(TAG, "Sleeping for 3 seconds."); + Thread.sleep(3000L); + } catch (InterruptedException e) {} + final JobParameters params = jobParamsMap.get(currId); + Log.d(TAG, "Pulled :" + currId + " " + params); + jobFinished(params, false); + + Log.d(TAG, "Rescheduling new job: " + params.getJobId()); + scheduleJob( + new JobInfo.Builder(params.getJobId(), + new ComponentName(getBaseContext(), TestJobService.class)) + .setMinimumLatency(2000L) + .setOverrideDeadline(3000L) + .setRequiresCharging(true) + .build() + ); + + return null; + } + }.execute(); return true; } + @Override public boolean onStopJob(JobParameters params) { - jobParamsMap.remove(params); - mActivity.onReceivedStopJob(); Log.i(TAG, "on stop job: " + params.getJobId()); + int ind = jobParamsMap.indexOfValue(params); + jobParamsMap.remove(ind); + mActivity.onReceivedStopJob(); return true; } + static int currentId = 0; MainActivity mActivity; - private final LinkedList<JobParameters> jobParamsMap = new LinkedList<JobParameters>(); + private final SparseArray<JobParameters> jobParamsMap = new SparseArray<JobParameters>(); + public void setUiCallback(MainActivity activity) { mActivity = activity; } /** Send job to the JobScheduler. */ - public void scheduleJob(JobInfo t) { - Log.d(TAG, "Scheduling job"); + public void scheduleJob(JobInfo job) { + Log.d(TAG, "Scheduling job " + job); JobScheduler tm = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); - tm.schedule(t); + tm.schedule(job); } public boolean callJobFinished() { - JobParameters params = jobParamsMap.poll(); + if (jobParamsMap.size() == 0) { + return false; + } + JobParameters params = jobParamsMap.valueAt(0); if (params == null) { return false; } else { |