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.ContentValues; 20 import android.content.Context; 21 import android.database.Cursor; 22 import android.database.sqlite.SQLiteDatabase; 23 import android.database.sqlite.SQLiteOpenHelper; 24 import android.database.sqlite.SQLiteQueryBuilder; 25 import android.util.Log; 26 27 import com.android.tv.dvr.ScheduledRecording; 28 import com.android.tv.dvr.provider.DvrContract.Recordings; 29 30 import java.util.ArrayList; 31 import java.util.List; 32 33 /** 34 * A data class for one recorded contents. 35 */ 36 public class DvrDatabaseHelper extends SQLiteOpenHelper { 37 private static final String TAG = "DvrDatabaseHelper"; 38 private static final boolean DEBUG = true; 39 40 private static final int DATABASE_VERSION = 4; 41 private static final String DB_NAME = "dvr.db"; 42 43 private static final String SQL_CREATE_RECORDINGS = 44 "CREATE TABLE " + Recordings.TABLE_NAME + "(" 45 + Recordings._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," 46 + Recordings.COLUMN_PRIORITY + " INTEGER DEFAULT " + Long.MAX_VALUE + "," 47 + Recordings.COLUMN_TYPE + " TEXT NOT NULL," 48 + Recordings.COLUMN_CHANNEL_ID + " INTEGER NOT NULL," 49 + Recordings.COLUMN_PROGRAM_ID + " INTEGER ," 50 + Recordings.COLUMN_START_TIME_UTC_MILLIS + " INTEGER NOT NULL," 51 + Recordings.COLUMN_END_TIME_UTC_MILLIS + " INTEGER NOT NULL," 52 + Recordings.COLUMN_STATE + " TEXT NOT NULL)"; 53 54 private static final String SQL_DROP_RECORDINGS = "DROP TABLE IF EXISTS " 55 + Recordings.TABLE_NAME; 56 public static final String WHERE_RECORDING_ID_EQUALS = Recordings._ID + " = ?"; 57 58 public DvrDatabaseHelper(Context context) { 59 super(context.getApplicationContext(), DB_NAME, null, DATABASE_VERSION); 60 } 61 62 @Override 63 public void onConfigure(SQLiteDatabase db) { 64 db.setForeignKeyConstraintsEnabled(true); 65 } 66 67 @Override 68 public void onCreate(SQLiteDatabase db) { 69 if (DEBUG) Log.d(TAG, "Executing SQL: " + SQL_CREATE_RECORDINGS); 70 db.execSQL(SQL_CREATE_RECORDINGS); 71 } 72 73 @Override 74 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 75 if (DEBUG) Log.d(TAG, "Executing SQL: " + SQL_DROP_RECORDINGS); 76 db.execSQL(SQL_DROP_RECORDINGS); 77 onCreate(db); 78 } 79 80 /** 81 * Handles the query request and returns a {@link Cursor}. 82 */ 83 public Cursor query(String tableName, String[] projections) { 84 SQLiteDatabase db = getReadableDatabase(); 85 SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); 86 builder.setTables(tableName); 87 return builder.query(db, projections, null, null, null, null, null); 88 } 89 90 /** 91 * Inserts recordings. 92 * 93 * @return The list of recordings with id set. The id will be -1 if there was an error. 94 */ 95 public List<ScheduledRecording> insertRecordings(ScheduledRecording... scheduledRecordings) { 96 updateChannelsFromRecordings(scheduledRecordings); 97 98 SQLiteDatabase db = getReadableDatabase(); 99 List<ScheduledRecording> results = new ArrayList<>(); 100 for (ScheduledRecording r : scheduledRecordings) { 101 ContentValues values = ScheduledRecording.toContentValues(r); 102 long id = db.insert(Recordings.TABLE_NAME, null, values); 103 results.add(ScheduledRecording.buildFrom(r).setId(id).build()); 104 } 105 return results; 106 } 107 108 /** 109 * Update recordings. 110 * 111 * @return The list of row update counts. The count will be -1 if there was an error or 0 112 * if no match was found. The count is expected to be exactly 1 for each recording. 113 */ 114 public List<Integer> updateRecordings(ScheduledRecording[] scheduledRecordings) { 115 updateChannelsFromRecordings(scheduledRecordings); 116 SQLiteDatabase db = getWritableDatabase(); 117 List<Integer> results = new ArrayList<>(); 118 for (ScheduledRecording r : scheduledRecordings) { 119 ContentValues values = ScheduledRecording.toContentValues(r); 120 int updated = db.update(Recordings.TABLE_NAME, values, Recordings._ID + " = ?", 121 new String[] {String.valueOf(r.getId())}); 122 results.add(updated); 123 } 124 return results; 125 } 126 127 private void updateChannelsFromRecordings(ScheduledRecording[] scheduledRecordings) { 128 // TODO(DVR) implement/ 129 // TODO(DVR) consider not deleting channels instead of keeping a separate table. 130 } 131 132 /** 133 * Delete recordings. 134 * 135 * @return The list of row update counts. The count will be -1 if there was an error or 0 136 * if no match was found. The count is expected to be exactly 1 for each recording. 137 */ 138 public List<Integer> deleteRecordings(ScheduledRecording[] scheduledRecordings) { 139 SQLiteDatabase db = getWritableDatabase(); 140 List<Integer> results = new ArrayList<>(); 141 for (ScheduledRecording r : scheduledRecordings) { 142 int deleted = db.delete(Recordings.TABLE_NAME, WHERE_RECORDING_ID_EQUALS, 143 new String[] {String.valueOf(r.getId())}); 144 results.add(deleted); 145 } 146 return results; 147 } 148 } 149