1a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park/* 2a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park * Copyright (C) 2015 The Android Open Source Project 3a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park * 4a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park * Licensed under the Apache License, Version 2.0 (the "License"); 5a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park * you may not use this file except in compliance with the License. 6a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park * You may obtain a copy of the License at 7a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park * 8a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park * http://www.apache.org/licenses/LICENSE-2.0 9a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park * 10a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park * Unless required by applicable law or agreed to in writing, software 11a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park * distributed under the License is distributed on an "AS IS" BASIS, 12a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park * See the License for the specific language governing permissions and 14a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park * limitations under the License. 15a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park */ 16a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Parkpackage com.google.android.car.kitchensink.job; 17a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 18a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Parkimport android.app.job.JobParameters; 19a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Parkimport android.app.job.JobService; 20a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Parkimport android.os.AsyncTask; 21a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Parkimport android.os.Handler; 22a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Parkimport android.os.Message; 23a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Parkimport android.util.Log; 24a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Parkimport android.util.SparseArray; 25a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 26a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Parkimport java.lang.ref.WeakReference; 27a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 28a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Parkpublic class DishService extends JobService { 29a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park private static final String TAG = "JobScheduler_DishService"; 30a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park private static final int DELAY_MS = 1000; // wash a plate every second! 31a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 32a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park private static final int MSG_FINISHED = 0; 33a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park private static final int MSG_RUN_JOB = 1; 34a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park private static final int MSG_CANCEL_JOB = 2; 35a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 36a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park public static final String EXTRA_DISH_COUNT = "dish_count"; 37a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 38a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park private final Handler mHandler = new Handler() { 39a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park private SparseArray<JobParameters> mTaskMap = new SparseArray<JobParameters>(); 40a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park @Override 41a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park public void handleMessage(Message msg) { 42a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park JobParameters job = (JobParameters) msg.obj; 43a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park switch (msg.what) { 44a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park case MSG_FINISHED: 45a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park Log.d(TAG, "Job done! " + job.getJobId()); 46a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park mTaskMap.remove(job.getJobId()); 47a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park jobFinished(job, false); 48a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park break; 49a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park case MSG_RUN_JOB: 50a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park DishWasherTask task = new DishWasherTask(this, job, msg.arg1); 51a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park task.execute(); 52a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park mTaskMap.put(job.getJobId(), job); 53a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park break; 54a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park case MSG_CANCEL_JOB: 55a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park JobParameters job1 = mTaskMap.get(job.getJobId()); 56a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park if (job1 != null) { 57a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park removeMessages(MSG_RUN_JOB, job1); 58a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park Log.d(TAG, "cancelled job " + job1); 59a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park mTaskMap.remove(job.getJobId()); 60a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park } 61a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park break; 62a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park default: 63a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park Log.w(TAG, "Unknown message " + msg.what); 64a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park } 65a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park } 66a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park }; 67a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 68a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park @Override 69a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park public boolean onStopJob(JobParameters jobParameters) { 70a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park Log.d(TAG, "onStopJob " + jobParameters); 71a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park Message msg = mHandler.obtainMessage(MSG_CANCEL_JOB, 0, 0, jobParameters); 72a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park mHandler.sendMessage(msg); 73a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park return false; 74a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park } 75a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 76a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park @Override 77a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park public boolean onStartJob(final JobParameters jobParameters) { 78a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park Log.d(TAG, "onStartJob " + jobParameters); 79a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park Message msg = mHandler.obtainMessage(MSG_RUN_JOB, 0, 0, jobParameters); 80a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park mHandler.sendMessage(msg); 81a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park return true; 82a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park } 83a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 84a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park private static final class DishWasherTask extends AsyncTask<Void, Void, Boolean> { 85a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park private final WeakReference<Handler> mHandler; 86a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park private final JobParameters mJobParameter; 87a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park private final int mMyDishNum; 88a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 89a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 90a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park public DishWasherTask(Handler handler, JobParameters jobParameters, int dishNum) { 91a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park mHandler = new WeakReference<Handler>(handler); 92a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park mJobParameter = jobParameters; 93a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park mMyDishNum = dishNum; 94a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park } 95a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 96a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park @Override 97a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park protected Boolean doInBackground(Void... infos) { 98a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park int dishTotal = mJobParameter.getExtras().getInt(EXTRA_DISH_COUNT); 99a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 100a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park Log.d(TAG, "jobId: " + mJobParameter.getJobId() + " totalDish: " + dishTotal 101a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park + " washing: #" + mMyDishNum); 102a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park wash(); 103a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park if (mMyDishNum >= dishTotal - 1) { 104a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park // all done! 105a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park return false; 106a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park } 107a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park return true; 108a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park } 109a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 110a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park @Override 111a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park protected void onPostExecute(Boolean result) { 112a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park if (mHandler.get() == null) { 113a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park return; 114a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park } 115a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park if (result) { 116a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park Message msg = mHandler.get().obtainMessage(MSG_RUN_JOB, 117a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park mMyDishNum +1, 0, mJobParameter); 118a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park mHandler.get().sendMessageDelayed(msg, DELAY_MS); 119a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park } else { 120a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park Message msg = mHandler.get().obtainMessage(MSG_FINISHED, 0, 121a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 0, mJobParameter); 122a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park mHandler.get().sendMessage(msg); 123a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park } 124a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park } 125a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park 126a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park private void wash() { 127a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park // TODO: add heavy wash tasks here... 128a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park } 129a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park } 130a6521cd799e509b03ecbeea3b05f1dd5c0379387Keun-young Park} 131