1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tv.dvr.provider;
18 
19 import android.content.Context;
20 import android.database.Cursor;
21 import android.os.AsyncTask;
22 import android.support.annotation.Nullable;
23 
24 import com.android.tv.dvr.ScheduledRecording;
25 import com.android.tv.dvr.SeriesRecording;
26 import com.android.tv.dvr.provider.DvrContract.Schedules;
27 import com.android.tv.dvr.provider.DvrContract.SeriesRecordings;
28 import com.android.tv.util.NamedThreadFactory;
29 
30 import java.util.ArrayList;
31 import java.util.List;
32 import java.util.concurrent.ExecutorService;
33 import java.util.concurrent.Executors;
34 
35 /**
36  * {@link AsyncTask} that defaults to executing on its own single threaded Executor Service.
37  */
38 public abstract class AsyncDvrDbTask<Params, Progress, Result>
39         extends AsyncTask<Params, Progress, Result> {
40     private static final NamedThreadFactory THREAD_FACTORY = new NamedThreadFactory(
41             AsyncDvrDbTask.class.getSimpleName());
42     private static final ExecutorService DB_EXECUTOR = Executors
43             .newSingleThreadExecutor(THREAD_FACTORY);
44 
45     private static DvrDatabaseHelper sDbHelper;
46 
initializeDbHelper(Context context)47     private static synchronized DvrDatabaseHelper initializeDbHelper(Context context) {
48         if (sDbHelper == null) {
49             sDbHelper = new DvrDatabaseHelper(context.getApplicationContext());
50         }
51         return sDbHelper;
52     }
53 
54     final Context mContext;
55 
AsyncDvrDbTask(Context context)56     private AsyncDvrDbTask(Context context) {
57         mContext = context;
58     }
59 
60     /**
61      * Execute the task on the {@link #DB_EXECUTOR} thread.
62      */
63     @SafeVarargs
executeOnDbThread(Params... params)64     public final void executeOnDbThread(Params... params) {
65         executeOnExecutor(DB_EXECUTOR, params);
66     }
67 
68     @Override
doInBackground(Params... params)69     protected final Result doInBackground(Params... params) {
70         initializeDbHelper(mContext);
71         return doInDvrBackground(params);
72     }
73 
74     /**
75      * Executes in the background after {@link #initializeDbHelper(Context)}
76      */
77     @Nullable
doInDvrBackground(Params... params)78     protected abstract Result doInDvrBackground(Params... params);
79 
80      /**
81      * Inserts schedules.
82      */
83     public static class AsyncAddScheduleTask
84             extends AsyncDvrDbTask<ScheduledRecording, Void, Void> {
AsyncAddScheduleTask(Context context)85         public AsyncAddScheduleTask(Context context) {
86             super(context);
87         }
88 
89         @Override
doInDvrBackground(ScheduledRecording... params)90         protected final Void doInDvrBackground(ScheduledRecording... params) {
91             sDbHelper.insertSchedules(params);
92             return null;
93         }
94     }
95 
96     /**
97      * Update schedules.
98      */
99     public static class AsyncUpdateScheduleTask
100             extends AsyncDvrDbTask<ScheduledRecording, Void, Void> {
AsyncUpdateScheduleTask(Context context)101         public AsyncUpdateScheduleTask(Context context) {
102             super(context);
103         }
104 
105         @Override
doInDvrBackground(ScheduledRecording... params)106         protected final Void doInDvrBackground(ScheduledRecording... params) {
107             sDbHelper.updateSchedules(params);
108             return null;
109         }
110     }
111 
112     /**
113      * Delete schedules.
114      */
115     public static class AsyncDeleteScheduleTask
116             extends AsyncDvrDbTask<ScheduledRecording, Void, Void> {
AsyncDeleteScheduleTask(Context context)117         public AsyncDeleteScheduleTask(Context context) {
118             super(context);
119         }
120 
121         @Override
doInDvrBackground(ScheduledRecording... params)122         protected final Void doInDvrBackground(ScheduledRecording... params) {
123             sDbHelper.deleteSchedules(params);
124             return null;
125         }
126     }
127 
128     /**
129      * Returns all {@link ScheduledRecording}s.
130      */
131     public abstract static class AsyncDvrQueryScheduleTask
132             extends AsyncDvrDbTask<Void, Void, List<ScheduledRecording>> {
AsyncDvrQueryScheduleTask(Context context)133         public AsyncDvrQueryScheduleTask(Context context) {
134             super(context);
135         }
136 
137         @Override
138         @Nullable
doInDvrBackground(Void... params)139         protected final List<ScheduledRecording> doInDvrBackground(Void... params) {
140             if (isCancelled()) {
141                 return null;
142             }
143             List<ScheduledRecording> scheduledRecordings = new ArrayList<>();
144             try (Cursor c = sDbHelper.query(Schedules.TABLE_NAME, ScheduledRecording.PROJECTION)) {
145                 while (c.moveToNext() && !isCancelled()) {
146                     scheduledRecordings.add(ScheduledRecording.fromCursor(c));
147                 }
148             }
149             return scheduledRecordings;
150         }
151     }
152 
153     /**
154      * Inserts series recordings.
155      */
156     public static class AsyncAddSeriesRecordingTask
157             extends AsyncDvrDbTask<SeriesRecording, Void, Void> {
AsyncAddSeriesRecordingTask(Context context)158         public AsyncAddSeriesRecordingTask(Context context) {
159             super(context);
160         }
161 
162         @Override
doInDvrBackground(SeriesRecording... params)163         protected final Void doInDvrBackground(SeriesRecording... params) {
164             sDbHelper.insertSeriesRecordings(params);
165             return null;
166         }
167     }
168 
169     /**
170      * Update series recordings.
171      */
172     public static class AsyncUpdateSeriesRecordingTask
173             extends AsyncDvrDbTask<SeriesRecording, Void, Void> {
AsyncUpdateSeriesRecordingTask(Context context)174         public AsyncUpdateSeriesRecordingTask(Context context) {
175             super(context);
176         }
177 
178         @Override
doInDvrBackground(SeriesRecording... params)179         protected final Void doInDvrBackground(SeriesRecording... params) {
180             sDbHelper.updateSeriesRecordings(params);
181             return null;
182         }
183     }
184 
185     /**
186      * Delete series recordings.
187      */
188     public static class AsyncDeleteSeriesRecordingTask
189             extends AsyncDvrDbTask<SeriesRecording, Void, Void> {
AsyncDeleteSeriesRecordingTask(Context context)190         public AsyncDeleteSeriesRecordingTask(Context context) {
191             super(context);
192         }
193 
194         @Override
doInDvrBackground(SeriesRecording... params)195         protected final Void doInDvrBackground(SeriesRecording... params) {
196             sDbHelper.deleteSeriesRecordings(params);
197             return null;
198         }
199     }
200 
201     /**
202      * Returns all {@link SeriesRecording}s.
203      */
204     public abstract static class AsyncDvrQuerySeriesRecordingTask
205             extends AsyncDvrDbTask<Void, Void, List<SeriesRecording>> {
AsyncDvrQuerySeriesRecordingTask(Context context)206         public AsyncDvrQuerySeriesRecordingTask(Context context) {
207             super(context);
208         }
209 
210         @Override
211         @Nullable
doInDvrBackground(Void... params)212         protected final List<SeriesRecording> doInDvrBackground(Void... params) {
213             if (isCancelled()) {
214                 return null;
215             }
216             List<SeriesRecording> scheduledRecordings = new ArrayList<>();
217             try (Cursor c = sDbHelper.query(SeriesRecordings.TABLE_NAME,
218                     SeriesRecording.PROJECTION)) {
219                 while (c.moveToNext() && !isCancelled()) {
220                     scheduledRecordings.add(SeriesRecording.fromCursor(c));
221                 }
222             }
223             return scheduledRecordings;
224         }
225     }
226 }
227