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