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.common;
18 
19 import android.content.ContentProvider;
20 import android.content.ContentValues;
21 import android.content.Context;
22 import android.content.UriMatcher;
23 import android.database.Cursor;
24 import android.database.sqlite.SQLiteDatabase;
25 import android.database.sqlite.SQLiteException;
26 import android.database.sqlite.SQLiteOpenHelper;
27 import android.net.Uri;
28 
29 /**
30  * A content provider for storing common preferences. It's used across TV app and tuner TV inputs.
31  */
32 public class CommonPreferenceProvider extends ContentProvider {
33     /** The authority of the provider */
34     public static final String AUTHORITY = CommonConstants.BASE_PACKAGE + ".common.preferences";
35 
36     private static final String PATH_PREFERENCES = "preferences";
37 
38     private static final int DATABASE_VERSION = 1;
39     private static final String DATABASE_NAME = "usbtuner_preferences.db";
40     private static final String PREFERENCES_TABLE = "preferences";
41 
42     private static final int MATCH_PREFERENCE = 1;
43     private static final int MATCH_PREFERENCE_KEY = 2;
44 
45     private static final UriMatcher sUriMatcher;
46 
47     private DatabaseOpenHelper mDatabaseOpenHelper;
48 
49     static {
50         sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(AUTHORITY, "preferences", MATCH_PREFERENCE)51         sUriMatcher.addURI(AUTHORITY, "preferences", MATCH_PREFERENCE);
sUriMatcher.addURI(AUTHORITY, "preferences/*", MATCH_PREFERENCE_KEY)52         sUriMatcher.addURI(AUTHORITY, "preferences/*", MATCH_PREFERENCE_KEY);
53     }
54 
55     /**
56      * Builds a Uri that points to a specific preference.
57      *
58      * @param key a key of the preference to point to
59      */
buildPreferenceUri(String key)60     public static Uri buildPreferenceUri(String key) {
61         return Preferences.CONTENT_URI.buildUpon().appendPath(key).build();
62     }
63 
64     /** Columns definitions for the preferences table. */
65     public interface Preferences {
66 
67         /** The content:// style for the preferences table. */
68         Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + PATH_PREFERENCES);
69 
70         /** The MIME type of a directory of preferences. */
71         String CONTENT_TYPE = "vnd.android.cursor.dir/preferences";
72 
73         /** The MIME type of a single preference. */
74         String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/preferences";
75 
76         /**
77          * The ID of this preference.
78          *
79          * <p>This is auto-incremented.
80          *
81          * <p>Type: INTEGER
82          */
83         String _ID = "_id";
84 
85         /**
86          * The key of this preference.
87          *
88          * <p>Should be unique.
89          *
90          * <p>Type: TEXT
91          */
92         String COLUMN_KEY = "key";
93 
94         /**
95          * The value of this preference.
96          *
97          * <p>Type: TEXT
98          */
99         String COLUMN_VALUE = "value";
100     }
101 
102     private static class DatabaseOpenHelper extends SQLiteOpenHelper {
DatabaseOpenHelper(Context context)103         public DatabaseOpenHelper(Context context) {
104             super(context, DATABASE_NAME, null, DATABASE_VERSION);
105         }
106 
107         @Override
onCreate(SQLiteDatabase db)108         public void onCreate(SQLiteDatabase db) {
109             db.execSQL(
110                     "CREATE TABLE "
111                             + PREFERENCES_TABLE
112                             + " ("
113                             + Preferences._ID
114                             + " INTEGER PRIMARY KEY AUTOINCREMENT,"
115                             + Preferences.COLUMN_KEY
116                             + " TEXT NOT NULL,"
117                             + Preferences.COLUMN_VALUE
118                             + " TEXT);");
119         }
120 
121         @Override
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)122         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
123             // No-op
124         }
125     }
126 
127     @Override
onCreate()128     public boolean onCreate() {
129         mDatabaseOpenHelper = new DatabaseOpenHelper(getContext());
130         return true;
131     }
132 
133     @Override
query( Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)134     public Cursor query(
135             Uri uri,
136             String[] projection,
137             String selection,
138             String[] selectionArgs,
139             String sortOrder) {
140         int match = sUriMatcher.match(uri);
141         if (match != MATCH_PREFERENCE && match != MATCH_PREFERENCE_KEY) {
142             throw new UnsupportedOperationException();
143         }
144         SQLiteDatabase db = mDatabaseOpenHelper.getReadableDatabase();
145         Cursor cursor =
146                 db.query(
147                         PREFERENCES_TABLE,
148                         projection,
149                         selection,
150                         selectionArgs,
151                         null,
152                         null,
153                         sortOrder);
154         cursor.setNotificationUri(getContext().getContentResolver(), uri);
155         return cursor;
156     }
157 
158     @Override
getType(Uri uri)159     public String getType(Uri uri) {
160         switch (sUriMatcher.match(uri)) {
161             case MATCH_PREFERENCE:
162                 return Preferences.CONTENT_TYPE;
163             case MATCH_PREFERENCE_KEY:
164                 return Preferences.CONTENT_ITEM_TYPE;
165             default:
166                 throw new IllegalArgumentException("Unknown URI " + uri);
167         }
168     }
169 
170     /**
171      * Inserts a preference row into the preference table.
172      *
173      * <p>If a key is already exists in the table, it removes the old row and inserts a new row.
174      *
175      * @param uri the URL of the table to insert into
176      * @param values the initial values for the newly inserted row
177      * @return the URL of the newly created row
178      */
179     @Override
insert(Uri uri, ContentValues values)180     public Uri insert(Uri uri, ContentValues values) {
181         if (sUriMatcher.match(uri) != MATCH_PREFERENCE) {
182             throw new UnsupportedOperationException();
183         }
184         return insertRow(uri, values);
185     }
186 
insertRow(Uri uri, ContentValues values)187     private Uri insertRow(Uri uri, ContentValues values) {
188         SQLiteDatabase db = mDatabaseOpenHelper.getWritableDatabase();
189 
190         // Remove the old row.
191         db.delete(
192                 PREFERENCES_TABLE,
193                 Preferences.COLUMN_KEY + " like ?",
194                 new String[] {values.getAsString(Preferences.COLUMN_KEY)});
195 
196         long rowId = db.insert(PREFERENCES_TABLE, null, values);
197         if (rowId > 0) {
198             Uri rowUri = buildPreferenceUri(values.getAsString(Preferences.COLUMN_KEY));
199             getContext().getContentResolver().notifyChange(rowUri, null);
200             return rowUri;
201         }
202 
203         throw new SQLiteException("Failed to insert row into " + uri);
204     }
205 
206     @Override
delete(Uri uri, String selection, String[] selectionArgs)207     public int delete(Uri uri, String selection, String[] selectionArgs) {
208         throw new UnsupportedOperationException();
209     }
210 
211     @Override
update(Uri uri, ContentValues values, String selection, String[] selectionArgs)212     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
213         throw new UnsupportedOperationException();
214     }
215 }
216