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