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
17package com.android.usbtuner;
18
19import android.content.ContentProvider;
20import android.content.ContentValues;
21import android.content.Context;
22import android.content.UriMatcher;
23import android.database.Cursor;
24import android.database.sqlite.SQLiteDatabase;
25import android.database.sqlite.SQLiteException;
26import android.database.sqlite.SQLiteOpenHelper;
27import 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 */
32public 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);
53        sUriMatcher.addURI(AUTHORITY, "preferences", MATCH_PREFERENCE);
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     */
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 {
113        public DatabaseOpenHelper(Context context) {
114            super(context, DATABASE_NAME, null, DATABASE_VERSION);
115        }
116
117        @Override
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
132        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
133            // No-op
134        }
135    }
136
137    @Override
138    public boolean onCreate() {
139        mDatabaseOpenHelper = new DatabaseOpenHelper(getContext());
140        return true;
141    }
142
143    @Override
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
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
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
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
202    public int delete(Uri uri, String selection, String[] selectionArgs) {
203        throw new UnsupportedOperationException();
204    }
205
206    @Override
207    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
208        throw new UnsupportedOperationException();
209    }
210}
211