SettingsProvider.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.providers.settings; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentProvider; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentUris; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentValues; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteQueryBuilder; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.RingtoneManager; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ParcelFileDescriptor; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemProperties; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.DrmStore; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.MediaStore; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileNotFoundException; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SettingsProvider extends ContentProvider { 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "SettingsProvider"; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean LOCAL_LOGV = false; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TABLE_FAVORITES = "favorites"; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TABLE_OLD_FAVORITES = "old_favorites"; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private DatabaseHelper mOpenHelper; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Decode a content URL into the table, projection, and arguments 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * used to access the corresponding database rows. 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class SqlArguments { 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String table; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final String where; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final String[] args; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Operate on existing rows. */ 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SqlArguments(Uri url, String where, String[] args) { 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (url.getPathSegments().size() == 1) { 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.table = url.getPathSegments().get(0); 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.where = where; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.args = args; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (url.getPathSegments().size() != 2) { 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Invalid URI: " + url); 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!TextUtils.isEmpty(where)) { 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new UnsupportedOperationException("WHERE clause not supported: " + url); 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.table = url.getPathSegments().get(0); 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ("gservices".equals(this.table) || "system".equals(this.table) 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || "secure".equals(this.table)) { 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.where = Settings.NameValueTable.NAME + "=?"; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.args = new String[] { url.getPathSegments().get(1) }; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.where = "_id=" + ContentUris.parseId(url); 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.args = null; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Insert new rows (no where clause allowed). */ 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SqlArguments(Uri url) { 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (url.getPathSegments().size() == 1) { 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.table = url.getPathSegments().get(0); 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.where = null; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.args = null; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Invalid URI: " + url); 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Get the content URI of a row added to a table. 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param tableUri of the entire table 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values found in the row 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param rowId of the row 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the content URI for this particular row 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Uri getUriFor(Uri tableUri, ContentValues values, long rowId) { 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tableUri.getPathSegments().size() != 1) { 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Invalid URI: " + tableUri); 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String table = tableUri.getPathSegments().get(0); 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ("gservices".equals(table) || "system".equals(table) 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || "secure".equals(table)) { 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String name = values.getAsString(Settings.NameValueTable.NAME); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Uri.withAppendedPath(tableUri, name); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ContentUris.withAppendedId(tableUri, rowId); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Send a notification when a particular content URI changes. 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Modify the system property used to communicate the version of 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this table, for tables which have such a property. (The Settings 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * contract class uses these to provide client-side caches.) 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param uri to send notifications for 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendNotify(Uri uri) { 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Update the system property *first*, so if someone is listening for 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // a notification and then using the contract class to get their data, 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the system property will be updated and they'll get the new data. 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String property = null, table = uri.getPathSegments().get(0); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (table.equals("system")) { 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project property = Settings.System.SYS_PROP_SETTING_VERSION; 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (table.equals("secure")) { 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project property = Settings.Secure.SYS_PROP_SETTING_VERSION; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (table.equals("gservices")) { 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project property = Settings.Gservices.SYS_PROP_SETTING_VERSION; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (property != null) { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long version = SystemProperties.getLong(property, 0) + 1; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOCAL_LOGV) Log.v(TAG, "property: " + property + "=" + version); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SystemProperties.set(property, Long.toString(version)); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Now send the notification through the content framework. 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String notify = uri.getQueryParameter("notify"); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (notify == null || "true".equals(notify)) { 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getContext().getContentResolver().notifyChange(uri, null); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOCAL_LOGV) Log.v(TAG, "notifying: " + uri); 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOCAL_LOGV) Log.v(TAG, "notification suppressed: " + uri); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Make sure the caller has permission to write this data. 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param args supplied by the caller 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws SecurityException if the caller is forbidden to write. 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void checkWritePermissions(SqlArguments args) { 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ("secure".equals(args.table) && 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getContext().checkCallingOrSelfPermission( 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.WRITE_SECURE_SETTINGS) != 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PackageManager.PERMISSION_GRANTED) { 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Cannot write secure settings table"); 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: Move gservices into its own provider so we don't need this nonsense. 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if ("gservices".equals(args.table) && 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getContext().checkCallingOrSelfPermission( 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.WRITE_GSERVICES) != 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PackageManager.PERMISSION_GRANTED) { 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Cannot write gservices table"); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onCreate() { 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOpenHelper = new DatabaseHelper(getContext()); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Cursor query(Uri url, String[] select, String where, String[] whereArgs, String sort) { 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SqlArguments args = new SqlArguments(url, where, whereArgs); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The favorites table was moved from this provider to a provider inside Home 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Home still need to query this table to upgrade from pre-cupcake builds 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // However, a cupcake+ build with no data does not contain this table which will 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // cause an exception in the SQL stack. The following line is a special case to 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // let the caller of the query have a chance to recover and avoid the exception 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (TABLE_FAVORITES.equals(args.table)) { 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (TABLE_OLD_FAVORITES.equals(args.table)) { 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project args.table = TABLE_FAVORITES; 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cursor cursor = db.rawQuery("PRAGMA table_info(favorites);", null); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cursor != null) { 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean exists = cursor.getCount() > 0; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cursor.close(); 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!exists) return null; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project qb.setTables(args.table); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Cursor ret = qb.query(db, select, args.where, args.args, null, null, sort); 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret.setNotificationUri(getContext().getContentResolver(), url); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getType(Uri url) { 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If SqlArguments supplies a where clause, then it must be an item 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (because we aren't supplying our own where clause). 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SqlArguments args = new SqlArguments(url, null, null); 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (TextUtils.isEmpty(args.where)) { 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "vnd.android.cursor.dir/" + args.table; 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "vnd.android.cursor.item/" + args.table; 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int bulkInsert(Uri uri, ContentValues[] values) { 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SqlArguments args = new SqlArguments(uri); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (TABLE_FAVORITES.equals(args.table)) { 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkWritePermissions(args); 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project db.beginTransaction(); 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numValues = values.length; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numValues; i++) { 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (db.insert(args.table, null, values[i]) < 0) return 0; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOCAL_LOGV) Log.v(TAG, args.table + " <- " + values[i]); 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project db.setTransactionSuccessful(); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project db.endTransaction(); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendNotify(uri); 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return values.length; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Uri insert(Uri url, ContentValues initialValues) { 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SqlArguments args = new SqlArguments(url); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (TABLE_FAVORITES.equals(args.table)) { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkWritePermissions(args); 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final long rowId = db.insert(args.table, null, initialValues); 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rowId <= 0) return null; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOCAL_LOGV) Log.v(TAG, args.table + " <- " + initialValues); 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project url = getUriFor(url, initialValues, rowId); 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendNotify(url); 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return url; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int delete(Uri url, String where, String[] whereArgs) { 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SqlArguments args = new SqlArguments(url, where, whereArgs); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (TABLE_FAVORITES.equals(args.table)) { 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (TABLE_OLD_FAVORITES.equals(args.table)) { 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project args.table = TABLE_FAVORITES; 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkWritePermissions(args); 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = db.delete(args.table, args.where, args.args); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count > 0) sendNotify(url); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOCAL_LOGV) Log.v(TAG, args.table + ": " + count + " row(s) deleted"); 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return count; 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int update(Uri url, ContentValues initialValues, String where, String[] whereArgs) { 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SqlArguments args = new SqlArguments(url, where, whereArgs); 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (TABLE_FAVORITES.equals(args.table)) { 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkWritePermissions(args); 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = db.update(args.table, initialValues, args.where, args.args); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count > 0) sendNotify(url); 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOCAL_LOGV) Log.v(TAG, args.table + ": " + count + " row(s) <- " + initialValues); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return count; 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When a client attempts to openFile the default ringtone or 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * notification setting Uri, we will proxy the call to the current 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * default ringtone's Uri (if it is in the DRM or media provider). 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ringtoneType = RingtoneManager.getDefaultType(uri); 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Above call returns -1 if the Uri doesn't match a default type 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ringtoneType != -1) { 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Context context = getContext(); 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the current value for the default sound 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Uri soundUri = RingtoneManager.getActualDefaultRingtoneUri(context, ringtoneType); 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (soundUri == null) { 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fallback on any valid ringtone Uri 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project soundUri = RingtoneManager.getValidRingtoneUri(context); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (soundUri != null) { 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Only proxy the openFile call to drm or media providers 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String authority = soundUri.getAuthority(); 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isDrmAuthority = authority.equals(DrmStore.AUTHORITY); 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isDrmAuthority || authority.equals(MediaStore.AUTHORITY)) { 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isDrmAuthority) { 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check DRM access permission here, since once we 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // do the below call the DRM will be checking our 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // permission, not our caller's permission 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DrmStore.enforceAccessDrmPermission(context); 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (SecurityException e) { 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new FileNotFoundException(e.getMessage()); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return context.getContentResolver().openFileDescriptor(soundUri, mode); 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.openFile(uri, mode); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 342