summaryrefslogtreecommitdiffstats
path: root/packages/SettingsProvider
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commit54b6cfa9a9e5b861a9930af873580d6dc20f773c (patch)
tree35051494d2af230dce54d6b31c6af8fc24091316 /packages/SettingsProvider
downloadframeworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.zip
frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.gz
frameworks_base-54b6cfa9a9e5b861a9930af873580d6dc20f773c.tar.bz2
Initial Contribution
Diffstat (limited to 'packages/SettingsProvider')
-rw-r--r--packages/SettingsProvider/Android.mk16
-rw-r--r--packages/SettingsProvider/AndroidManifest.xml12
-rw-r--r--packages/SettingsProvider/MODULE_LICENSE_APACHE20
-rw-r--r--packages/SettingsProvider/NOTICE190
-rw-r--r--packages/SettingsProvider/etc/Android.mk47
-rw-r--r--packages/SettingsProvider/etc/bookmarks.xml28
-rw-r--r--packages/SettingsProvider/etc/favorites.xml22
-rwxr-xr-xpackages/SettingsProvider/res/drawable/ic_launcher_settings.pngbin0 -> 3285 bytes
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java572
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java295
10 files changed, 1182 insertions, 0 deletions
diff --git a/packages/SettingsProvider/Android.mk b/packages/SettingsProvider/Android.mk
new file mode 100644
index 0000000..330a673
--- /dev/null
+++ b/packages/SettingsProvider/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := user development
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES :=
+
+LOCAL_PACKAGE_NAME := SettingsProvider
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
+########################
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
new file mode 100644
index 0000000..fe188ce
--- /dev/null
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -0,0 +1,12 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.providers.settings"
+ android:sharedUserId="android.uid.system">
+ <application android:allowClearUserData="false"
+ android:label="Settings Storage"
+ android:icon="@drawable/ic_launcher_settings">
+ <provider android:name="SettingsProvider" android:authorities="settings"
+ android:process="system" android:multiprocess="false"
+ android:writePermission="android.permission.WRITE_SETTINGS"
+ android:initOrder="100" />
+ </application>
+</manifest>
diff --git a/packages/SettingsProvider/MODULE_LICENSE_APACHE2 b/packages/SettingsProvider/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/packages/SettingsProvider/MODULE_LICENSE_APACHE2
diff --git a/packages/SettingsProvider/NOTICE b/packages/SettingsProvider/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/packages/SettingsProvider/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2005-2008, The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/packages/SettingsProvider/etc/Android.mk b/packages/SettingsProvider/etc/Android.mk
new file mode 100644
index 0000000..e3f958c
--- /dev/null
+++ b/packages/SettingsProvider/etc/Android.mk
@@ -0,0 +1,47 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(my-dir)
+
+########################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := bookmarks.xml
+
+LOCAL_MODULE_TAGS := user development
+
+# This will install the file in /system/etc
+#
+LOCAL_MODULE_CLASS := ETC
+
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+
+include $(BUILD_PREBUILT)
+
+########################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := favorites.xml
+
+LOCAL_MODULE_TAGS := user development
+
+# This will install the file in /system/etc
+#
+LOCAL_MODULE_CLASS := ETC
+
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+
+include $(BUILD_PREBUILT)
diff --git a/packages/SettingsProvider/etc/bookmarks.xml b/packages/SettingsProvider/etc/bookmarks.xml
new file mode 100644
index 0000000..235e2ed
--- /dev/null
+++ b/packages/SettingsProvider/etc/bookmarks.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<bookmarks>
+ <bookmark package="com.android.browser" class="com.android.browser.BrowserActivity" shortcut="b" />
+ <bookmark package="com.android.calendar" class="com.android.calendar.LaunchActivity" shortcut="l" />
+ <bookmark package="com.android.contacts" class="com.android.contacts.DialtactsContactsEntryActivity" shortcut="c" />
+ <bookmark package="com.google.android.gm" class="com.google.android.gm.ConversationListActivityGmail" shortcut="g" />
+ <bookmark package="com.android.email" class="com.android.email.activity.Welcome" shortcut="e" />
+ <bookmark package="com.android.im" class="com.android.im.app.ChooseAccountActivity" shortcut="i" />
+ <bookmark package="com.google.android.apps.maps" class="com.google.android.maps.MapsActivity" shortcut="m" />
+ <bookmark package="com.android.music" class="com.android.music.MusicBrowserActivity" shortcut="p" />
+ <bookmark package="com.android.mms" class="com.android.mms.ui.ConversationList" shortcut="s" />
+ <bookmark package="com.google.android.youtube" class="com.google.android.youtube.HomePage" shortcut="y" />
+</bookmarks>
diff --git a/packages/SettingsProvider/etc/favorites.xml b/packages/SettingsProvider/etc/favorites.xml
new file mode 100644
index 0000000..0ecf8a6
--- /dev/null
+++ b/packages/SettingsProvider/etc/favorites.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<favorites>
+ <favorite package="com.android.contacts" class="com.android.contacts.DialtactsActivity" screen="1" x="0" y="3"/>
+ <favorite package="com.android.contacts" class="com.android.contacts.DialtactsContactsEntryActivity" screen="1" x="1" y="3" />
+ <favorite package="com.android.browser" class="com.android.browser.BrowserActivity" screen="1" x="2" y="3" />
+ <favorite package="com.google.android.apps.maps" class="com.google.android.maps.MapsActivity" screen="1" x="3" y="3" />
+</favorites>
diff --git a/packages/SettingsProvider/res/drawable/ic_launcher_settings.png b/packages/SettingsProvider/res/drawable/ic_launcher_settings.png
new file mode 100755
index 0000000..16db056
--- /dev/null
+++ b/packages/SettingsProvider/res/drawable/ic_launcher_settings.png
Binary files differ
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
new file mode 100644
index 0000000..b69d3c7
--- /dev/null
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -0,0 +1,572 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.settings;
+
+import android.content.ComponentName;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteStatement;
+import android.location.LocationManager;
+import android.media.AudioManager;
+import android.media.AudioService;
+import android.net.ConnectivityManager;
+import android.os.Environment;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Config;
+import android.util.Log;
+import android.util.Xml;
+import com.android.internal.util.XmlUtils;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Database helper class for {@link SettingsProvider}.
+ * Mostly just has a bit {@link #onCreate} to initialize the database.
+ */
+class DatabaseHelper extends SQLiteOpenHelper {
+ /**
+ * Path to file containing default favorite packages, relative to ANDROID_ROOT.
+ */
+ private static final String DEFAULT_FAVORITES_PATH = "etc/favorites.xml";
+
+ /**
+ * Path to file containing default bookmarks, relative to ANDROID_ROOT.
+ */
+ private static final String DEFAULT_BOOKMARKS_PATH = "etc/bookmarks.xml";
+
+ private static final String TAG = "SettingsProvider";
+ private static final String DATABASE_NAME = "settings.db";
+ private static final int DATABASE_VERSION = 25;
+
+ private Context mContext;
+
+ public DatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ mContext = context;
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL("CREATE TABLE system (" +
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
+ "name TEXT UNIQUE ON CONFLICT REPLACE," +
+ "value TEXT" +
+ ");");
+ db.execSQL("CREATE INDEX systemIndex1 ON system (name);");
+
+ db.execSQL("CREATE TABLE gservices (" +
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
+ "name TEXT UNIQUE ON CONFLICT REPLACE," +
+ "value TEXT" +
+ ");");
+ db.execSQL("CREATE INDEX gservicesIndex1 ON gservices (name);");
+
+ db.execSQL("CREATE TABLE bluetooth_devices (" +
+ "_id INTEGER PRIMARY KEY," +
+ "name TEXT," +
+ "addr TEXT," +
+ "channel INTEGER," +
+ "type INTEGER" +
+ ");");
+
+ db.execSQL("CREATE TABLE bookmarks (" +
+ "_id INTEGER PRIMARY KEY," +
+ "title TEXT," +
+ "folder TEXT," +
+ "intent TEXT," +
+ "shortcut INTEGER," +
+ "ordering INTEGER" +
+ ");");
+
+ db.execSQL("CREATE INDEX bookmarksIndex1 ON bookmarks (folder);");
+ db.execSQL("CREATE INDEX bookmarksIndex2 ON bookmarks (shortcut);");
+
+ db.execSQL("CREATE TABLE favorites (" +
+ "_id INTEGER PRIMARY KEY," +
+ "title TEXT," +
+ "intent TEXT," +
+ "container INTEGER," +
+ "screen INTEGER," +
+ "cellX INTEGER," +
+ "cellY INTEGER," +
+ "spanX INTEGER," +
+ "spanY INTEGER," +
+ "itemType INTEGER," +
+ "isShortcut INTEGER," +
+ "iconType INTEGER," +
+ "iconPackage TEXT," +
+ "iconResource TEXT," +
+ "icon BLOB" +
+ ");");
+
+ // Populate favorites table with initial favorites
+ loadFavorites(db);
+
+ // Populate bookmarks table with initial bookmarks
+ loadBookmarks(db);
+
+ // Load initial volume levels into DB
+ loadVolumeLevels(db);
+
+ // Load inital settings values
+ loadSettings(db);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
+
+ Log.w(TAG, "Upgrading settings database from version " + oldVersion + " to "
+ + currentVersion);
+
+ int upgradeVersion = oldVersion;
+
+ // Pattern for upgrade blocks:
+ //
+ // if (upgradeVersion == [the DATABASE_VERSION you set] - 1) {
+ // .. your upgrade logic..
+ // upgradeVersion = [the DATABASE_VERSION you set]
+ // }
+
+ if (upgradeVersion == 20) {
+ /*
+ * Version 21 is part of the volume control refresh. There is no
+ * longer a UI-visible for setting notification vibrate on/off (in
+ * our design), but the functionality still exists. Force the
+ * notification vibrate to on.
+ */
+ loadVibrateSetting(db, true);
+ if (Config.LOGD) Log.d(TAG, "Reset system vibrate setting");
+
+ upgradeVersion = 21;
+ }
+
+ if (upgradeVersion < 22) {
+ upgradeVersion = 22;
+ // Upgrade the lock gesture storage location and format
+ upgradeLockPatternLocation(db);
+ }
+
+ if (upgradeVersion < 23) {
+ db.execSQL("UPDATE favorites SET iconResource=0 WHERE iconType=0");
+ upgradeVersion = 23;
+ }
+
+ if (upgradeVersion == 23) {
+ db.beginTransaction();
+ try {
+ db.execSQL("ALTER TABLE favorites ADD spanX INTEGER");
+ db.execSQL("ALTER TABLE favorites ADD spanY INTEGER");
+ // Shortcuts, applications, folders
+ db.execSQL("UPDATE favorites SET spanX=1, spanY=1 WHERE itemType<=0");
+ // Photo frames, clocks
+ db.execSQL("UPDATE favorites SET spanX=2, spanY=2 WHERE itemType=1000 or itemType=1002");
+ // Search boxes
+ db.execSQL("UPDATE favorites SET spanX=4, spanY=1 WHERE itemType=1001");
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ upgradeVersion = 24;
+ }
+
+ if (upgradeVersion == 24) {
+ db.beginTransaction();
+ try {
+ // The value of the constants for preferring wifi or preferring mobile have been
+ // swapped, so reload the default.
+ db.execSQL("DELETE FROM system WHERE name='network_preference'");
+ db.execSQL("INSERT INTO system ('name', 'value') values ('network_preference', '" +
+ ConnectivityManager.DEFAULT_NETWORK_PREFERENCE + "')");
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ upgradeVersion = 25;
+ }
+
+ if (upgradeVersion != currentVersion) {
+ Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion
+ + ", must wipe the settings provider");
+ db.execSQL("DROP TABLE IF EXISTS system");
+ db.execSQL("DROP INDEX IF EXISTS systemIndex1");
+ db.execSQL("DROP TABLE IF EXISTS gservices");
+ db.execSQL("DROP INDEX IF EXISTS gservicesIndex1");
+ db.execSQL("DROP TABLE IF EXISTS bluetooth_devices");
+ db.execSQL("DROP TABLE IF EXISTS bookmarks");
+ db.execSQL("DROP INDEX IF EXISTS bookmarksIndex1");
+ db.execSQL("DROP INDEX IF EXISTS bookmarksIndex2");
+ db.execSQL("DROP TABLE IF EXISTS favorites");
+ onCreate(db);
+ }
+ }
+
+ private void upgradeLockPatternLocation(SQLiteDatabase db) {
+ Cursor c = db.query("system", new String[] {"_id", "value"}, "name='lock_pattern'",
+ null, null, null, null);
+ if (c.getCount() > 0) {
+ c.moveToFirst();
+ String lockPattern = c.getString(1);
+ if (!TextUtils.isEmpty(lockPattern)) {
+ // Convert lock pattern
+ try {
+ LockPatternUtils lpu = new LockPatternUtils(mContext.getContentResolver());
+ List<LockPatternView.Cell> cellPattern =
+ LockPatternUtils.stringToPattern(lockPattern);
+ lpu.saveLockPattern(cellPattern);
+ } catch (IllegalArgumentException e) {
+ // Don't want corrupted lock pattern to hang the reboot process
+ }
+ }
+ c.close();
+ db.delete("system", "name='lock_pattern'", null);
+ } else {
+ c.close();
+ }
+ }
+
+ /**
+ * Loads the default set of favorite packages from an xml file.
+ *
+ * @param db The database to write the values into
+ * @param startingIndex The zero-based position at which favorites in this file should begin
+ * @param subPath The relative path from ANDROID_ROOT to the file to read
+ * @param quiet If true, do no complain if the file is missing
+ */
+ private int loadFavorites(SQLiteDatabase db, int startingIndex, String subPath, boolean quiet) {
+ FileReader favReader;
+
+ // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
+ final File favFile = new File(Environment.getRootDirectory(), subPath);
+ try {
+ favReader = new FileReader(favFile);
+ } catch (FileNotFoundException e) {
+ if (!quiet) {
+ Log.e(TAG, "Couldn't find or open favorites file " + favFile);
+ }
+ return 0;
+ }
+
+ Intent intent = new Intent(Intent.ACTION_MAIN, null);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ ContentValues values = new ContentValues();
+
+ PackageManager packageManager = mContext.getPackageManager();
+ ActivityInfo info;
+ int i = startingIndex;
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(favReader);
+
+ XmlUtils.beginDocument(parser, "favorites");
+
+ while (true) {
+ XmlUtils.nextElement(parser);
+
+ String name = parser.getName();
+ if (!"favorite".equals(name)) {
+ break;
+ }
+
+ String pkg = parser.getAttributeValue(null, "package");
+ String cls = parser.getAttributeValue(null, "class");
+ try {
+ ComponentName cn = new ComponentName(pkg, cls);
+ info = packageManager.getActivityInfo(cn, 0);
+ intent.setComponent(cn);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ values.put(com.android.internal.provider.Settings.Favorites.INTENT,
+ intent.toURI());
+ values.put(com.android.internal.provider.Settings.Favorites.TITLE,
+ info.loadLabel(packageManager).toString());
+ values.put(com.android.internal.provider.Settings.Favorites.CONTAINER,
+ com.android.internal.provider.Settings.Favorites.CONTAINER_DESKTOP);
+ values.put(com.android.internal.provider.Settings.Favorites.ITEM_TYPE,
+ com.android.internal.provider.Settings.Favorites.ITEM_TYPE_APPLICATION);
+ values.put(com.android.internal.provider.Settings.Favorites.SCREEN,
+ parser.getAttributeValue(null, "screen"));
+ values.put(com.android.internal.provider.Settings.Favorites.CELLX,
+ parser.getAttributeValue(null, "x"));
+ values.put(com.android.internal.provider.Settings.Favorites.CELLY,
+ parser.getAttributeValue(null, "y"));
+ values.put(com.android.internal.provider.Settings.Favorites.SPANX, 1);
+ values.put(com.android.internal.provider.Settings.Favorites.SPANY, 1);
+ db.insert("favorites", null, values);
+ i++;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Unable to add favorite: " + pkg + "/" + cls, e);
+ }
+ }
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "Got execption parsing favorites.", e);
+ } catch (IOException e) {
+ Log.w(TAG, "Got execption parsing favorites.", e);
+ }
+
+ // Add a clock
+ values.clear();
+ values.put(com.android.internal.provider.Settings.Favorites.CONTAINER,
+ com.android.internal.provider.Settings.Favorites.CONTAINER_DESKTOP);
+ values.put(com.android.internal.provider.Settings.Favorites.ITEM_TYPE,
+ com.android.internal.provider.Settings.Favorites.ITEM_TYPE_WIDGET_CLOCK);
+ values.put(com.android.internal.provider.Settings.Favorites.SCREEN, 1);
+ values.put(com.android.internal.provider.Settings.Favorites.CELLX, 1);
+ values.put(com.android.internal.provider.Settings.Favorites.CELLY, 0);
+ values.put(com.android.internal.provider.Settings.Favorites.SPANX, 2);
+ values.put(com.android.internal.provider.Settings.Favorites.SPANY, 2);
+ db.insert("favorites", null, values);
+
+ // Add a search box
+ values.clear();
+ values.put(com.android.internal.provider.Settings.Favorites.CONTAINER,
+ com.android.internal.provider.Settings.Favorites.CONTAINER_DESKTOP);
+ values.put(com.android.internal.provider.Settings.Favorites.ITEM_TYPE,
+ com.android.internal.provider.Settings.Favorites.ITEM_TYPE_WIDGET_SEARCH);
+ values.put(com.android.internal.provider.Settings.Favorites.SCREEN, 2);
+ values.put(com.android.internal.provider.Settings.Favorites.CELLX, 0);
+ values.put(com.android.internal.provider.Settings.Favorites.CELLY, 0);
+ values.put(com.android.internal.provider.Settings.Favorites.SPANX, 4);
+ values.put(com.android.internal.provider.Settings.Favorites.SPANY, 1);
+ db.insert("favorites", null, values);
+
+ return i;
+ }
+
+ /**
+ * Loads the default set of favorite packages.
+ *
+ * @param db The database to write the values into
+ */
+ private void loadFavorites(SQLiteDatabase db) {
+ loadFavorites(db, 0, DEFAULT_FAVORITES_PATH, false);
+ }
+
+ /**
+ * Loads the default set of bookmarked shortcuts from an xml file.
+ *
+ * @param db The database to write the values into
+ * @param startingIndex The zero-based position at which bookmarks in this file should begin
+ * @param subPath The relative path from ANDROID_ROOT to the file to read
+ * @param quiet If true, do no complain if the file is missing
+ */
+ private int loadBookmarks(SQLiteDatabase db, int startingIndex, String subPath,
+ boolean quiet) {
+ FileReader bookmarksReader;
+
+ // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
+ final File favFile = new File(Environment.getRootDirectory(), subPath);
+ try {
+ bookmarksReader = new FileReader(favFile);
+ } catch (FileNotFoundException e) {
+ if (!quiet) {
+ Log.e(TAG, "Couldn't find or open bookmarks file " + favFile);
+ }
+ return 0;
+ }
+
+ Intent intent = new Intent(Intent.ACTION_MAIN, null);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ ContentValues values = new ContentValues();
+
+ PackageManager packageManager = mContext.getPackageManager();
+ ActivityInfo info;
+ int i = startingIndex;
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(bookmarksReader);
+
+ XmlUtils.beginDocument(parser, "bookmarks");
+
+ while (true) {
+ XmlUtils.nextElement(parser);
+
+ String name = parser.getName();
+ if (!"bookmark".equals(name)) {
+ break;
+ }
+
+ String pkg = parser.getAttributeValue(null, "package");
+ String cls = parser.getAttributeValue(null, "class");
+ String shortcutStr = parser.getAttributeValue(null, "shortcut");
+ int shortcutValue = (int) shortcutStr.charAt(0);
+ if (TextUtils.isEmpty(shortcutStr)) {
+ Log.w(TAG, "Unable to get shortcut for: " + pkg + "/" + cls);
+ }
+ try {
+ ComponentName cn = new ComponentName(pkg, cls);
+ info = packageManager.getActivityInfo(cn, 0);
+ intent.setComponent(cn);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ values.put(Settings.Bookmarks.INTENT, intent.toURI());
+ values.put(Settings.Bookmarks.TITLE,
+ info.loadLabel(packageManager).toString());
+ values.put(Settings.Bookmarks.SHORTCUT, shortcutValue);
+ db.insert("bookmarks", null, values);
+ i++;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Unable to add bookmark: " + pkg + "/" + cls, e);
+ }
+ }
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "Got execption parsing bookmarks.", e);
+ } catch (IOException e) {
+ Log.w(TAG, "Got execption parsing bookmarks.", e);
+ }
+
+ return i;
+ }
+
+ /**
+ * Loads the default set of bookmark packages.
+ *
+ * @param db The database to write the values into
+ */
+ private void loadBookmarks(SQLiteDatabase db) {
+ loadBookmarks(db, 0, DEFAULT_BOOKMARKS_PATH, false);
+ }
+
+ /**
+ * Loads the default volume levels. It is actually inserting the index of
+ * the volume array for each of the volume controls.
+ *
+ * @param db the database to insert the volume levels into
+ */
+ private void loadVolumeLevels(SQLiteDatabase db) {
+ SQLiteStatement stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
+ + " VALUES(?,?);");
+
+ // Music has double the number of levels
+ loadSetting(stmt, Settings.System.VOLUME_MUSIC, AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_MUSIC]);
+ loadSetting(stmt, Settings.System.VOLUME_RING, AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_RING]);
+ loadSetting(stmt, Settings.System.VOLUME_SYSTEM, AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_SYSTEM]);
+ loadSetting(stmt, Settings.System.VOLUME_VOICE, AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_VOICE_CALL]);
+ loadSetting(stmt, Settings.System.VOLUME_ALARM, AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_ALARM]);
+ loadSetting(stmt, Settings.System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
+
+ loadVibrateSetting(db, false);
+
+ // By default, only the ring/notification and system streams are affected
+ loadSetting(stmt, Settings.System.MODE_RINGER_STREAMS_AFFECTED,
+ (1 << AudioManager.STREAM_RING) | (1 << AudioManager.STREAM_SYSTEM));
+
+ loadSetting(stmt, Settings.System.MUTE_STREAMS_AFFECTED,
+ ((1 << AudioManager.STREAM_MUSIC) |
+ (1 << AudioManager.STREAM_RING) |
+ (1 << AudioManager.STREAM_SYSTEM)));
+
+ stmt.close();
+ }
+
+ private void loadVibrateSetting(SQLiteDatabase db, boolean deleteOld) {
+ if (deleteOld) {
+ db.execSQL("DELETE FROM system WHERE name='" + Settings.System.VIBRATE_ON + "'");
+ }
+
+ SQLiteStatement stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
+ + " VALUES(?,?);");
+
+ // Vibrate off by default for ringer, on for notification
+ int vibrate = 0;
+ vibrate = AudioService.getValueForVibrateSetting(vibrate,
+ AudioManager.VIBRATE_TYPE_NOTIFICATION, AudioManager.VIBRATE_SETTING_ON);
+ vibrate = AudioService.getValueForVibrateSetting(vibrate,
+ AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_OFF);
+ loadSetting(stmt, Settings.System.VIBRATE_ON, vibrate);
+ }
+
+ private void loadSettings(SQLiteDatabase db) {
+
+ SQLiteStatement stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
+ + " VALUES(?,?);");
+
+ loadSetting(stmt, Settings.System.DIM_SCREEN, 1);
+ loadSetting(stmt, Settings.System.STAY_ON_WHILE_PLUGGED_IN,
+ "1".equals(SystemProperties.get("ro.kernel.qemu")) ? 1 : 0);
+ loadSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT, 60000);
+ // Allow airplane mode to turn off cell radio
+ loadSetting(stmt, Settings.System.AIRPLANE_MODE_RADIOS,
+ Settings.System.RADIO_CELL + ","
+ + Settings.System.RADIO_BLUETOOTH + "," + Settings.System.RADIO_WIFI);
+
+ loadSetting(stmt, Settings.System.AIRPLANE_MODE_ON, 0);
+ loadSetting(stmt, Settings.System.BLUETOOTH_ON, 0);
+
+ // USB mass storage on by default
+ loadSetting(stmt, Settings.System.USB_MASS_STORAGE_ENABLED, 1);
+
+ loadSetting(stmt, Settings.System.WIFI_ON, 0);
+ loadSetting(stmt, Settings.System.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 1);
+ loadSetting(stmt, Settings.System.NETWORK_PREFERENCE,
+ ConnectivityManager.DEFAULT_NETWORK_PREFERENCE);
+
+ loadSetting(stmt, Settings.System.AUTO_TIME, 1); // Sync time to NITZ
+
+ // Set default brightness to 40%
+ loadSetting(stmt, Settings.System.SCREEN_BRIGHTNESS,
+ (int) (android.os.Power.BRIGHTNESS_ON * 0.4f));
+
+ // Don't allow non-market apps to be installed
+ loadSetting(stmt, Settings.System.INSTALL_NON_MARKET_APPS, 0);
+
+ // Enable normal window animations (menus, toasts); disable
+ // activity transition animations.
+ loadSetting(stmt, Settings.System.WINDOW_ANIMATION_SCALE, "1");
+ loadSetting(stmt, Settings.System.TRANSITION_ANIMATION_SCALE, "0");
+
+ // Set the default location providers to network based (cell-id)
+ loadSetting(stmt, Settings.System.LOCATION_PROVIDERS_ALLOWED,
+ LocationManager.NETWORK_PROVIDER);
+
+ // Data roaming default, based on build
+ loadSetting(stmt, Settings.System.DATA_ROAMING,
+ "true".equalsIgnoreCase(
+ SystemProperties.get("ro.com.android.dataroaming",
+ "false")) ? 1 : 0);
+ // Default date format based on build
+ loadSetting(stmt, Settings.System.DATE_FORMAT,
+ SystemProperties.get("ro.com.android.dateformat",
+ "MM-dd-yyyy"));
+
+ // Don't do this. The SystemServer will initialize ADB_ENABLED from a
+ // persistent system property instead.
+ //loadSetting(stmt, Settings.System.ADB_ENABLED, 0);
+ stmt.close();
+ }
+
+ private void loadSetting(SQLiteStatement stmt, String key, Object value) {
+ stmt.bindString(1, key);
+ stmt.bindString(2, value.toString());
+ stmt.execute();
+ }
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
new file mode 100644
index 0000000..c8a3cce
--- /dev/null
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.settings;
+
+import android.content.ContentProvider;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.os.SystemProperties;
+import android.provider.DrmStore;
+import android.provider.MediaStore;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.FileNotFoundException;
+
+public class SettingsProvider extends ContentProvider {
+ private static final String TAG = "SettingsProvider";
+ private static final boolean LOCAL_LOGV = false;
+
+ private static final String WRITE_GSERVICES_PERMISSION = "android.permission.WRITE_GSERVICES";
+
+ private DatabaseHelper mOpenHelper;
+
+ /**
+ * Decode a content URL into the table, projection, and arguments
+ * used to access the corresponding database rows.
+ */
+ private static class SqlArguments {
+ public final String table;
+ public final String where;
+ public final String[] args;
+
+ /** Operate on existing rows. */
+ SqlArguments(Uri url, String where, String[] args) {
+ if (url.getPathSegments().size() == 1) {
+ this.table = url.getPathSegments().get(0);
+ this.where = where;
+ this.args = args;
+ } else if (url.getPathSegments().size() != 2) {
+ throw new IllegalArgumentException("Invalid URI: " + url);
+ } else if (!TextUtils.isEmpty(where)) {
+ throw new UnsupportedOperationException("WHERE clause not supported: " + url);
+ } else {
+ this.table = url.getPathSegments().get(0);
+ if ("gservices".equals(this.table) || "system".equals(this.table)) {
+ this.where = Settings.NameValueTable.NAME + "=?";
+ this.args = new String[] { url.getPathSegments().get(1) };
+ } else {
+ this.where = "_id=" + ContentUris.parseId(url);
+ this.args = null;
+ }
+ }
+ }
+
+ /** Insert new rows (no where clause allowed). */
+ SqlArguments(Uri url) {
+ if (url.getPathSegments().size() == 1) {
+ this.table = url.getPathSegments().get(0);
+ this.where = null;
+ this.args = null;
+ } else {
+ throw new IllegalArgumentException("Invalid URI: " + url);
+ }
+ }
+ }
+
+ /**
+ * Get the content URI of a row added to a table.
+ * @param tableUri of the entire table
+ * @param values found in the row
+ * @param rowId of the row
+ * @return the content URI for this particular row
+ */
+ private Uri getUriFor(Uri tableUri, ContentValues values, long rowId) {
+ if (tableUri.getPathSegments().size() != 1) {
+ throw new IllegalArgumentException("Invalid URI: " + tableUri);
+ }
+ String table = tableUri.getPathSegments().get(0);
+ if ("gservices".equals(table) || "system".equals(table)) {
+ String name = values.getAsString(Settings.NameValueTable.NAME);
+ return Uri.withAppendedPath(tableUri, name);
+ } else {
+ return ContentUris.withAppendedId(tableUri, rowId);
+ }
+ }
+
+ /**
+ * Send a notification when a particular content URI changes.
+ * Modify the system property used to communicate the version of
+ * this table, for tables which have such a property. (The Settings
+ * contract class uses these to provide client-side caches.)
+ * @param uri to send notifications for
+ */
+ private void sendNotify(Uri uri) {
+ // Update the system property *first*, so if someone is listening for
+ // a notification and then using the contract class to get their data,
+ // the system property will be updated and they'll get the new data.
+
+ String property = null, table = uri.getPathSegments().get(0);
+ if (table.equals("system")) {
+ property = Settings.System.SYS_PROP_SETTING_VERSION;
+ } else if (table.equals("gservices")) {
+ property = Settings.Gservices.SYS_PROP_SETTING_VERSION;
+ }
+
+ if (property != null) {
+ long version = SystemProperties.getLong(property, 0) + 1;
+ if (LOCAL_LOGV) Log.v(TAG, "property: " + property + "=" + version);
+ SystemProperties.set(property, Long.toString(version));
+ }
+
+ // Now send the notification through the content framework.
+
+ String notify = uri.getQueryParameter("notify");
+ if (notify == null || "true".equals(notify)) {
+ getContext().getContentResolver().notifyChange(uri, null);
+ if (LOCAL_LOGV) Log.v(TAG, "notifying: " + uri);
+ } else {
+ if (LOCAL_LOGV) Log.v(TAG, "notification suppressed: " + uri);
+ }
+ }
+
+ /**
+ * Make sure the caller has permission to write this data.
+ * @param args supplied by the caller
+ * @throws SecurityException if the caller is forbidden to write.
+ */
+ private void checkWritePermissions(SqlArguments args) {
+ // TODO: Move gservices into its own provider so we don't need this nonsense.
+ if ("gservices".equals(args.table) &&
+ getContext().checkCallingOrSelfPermission(WRITE_GSERVICES_PERMISSION) !=
+ PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Cannot write gservices table");
+ }
+ }
+
+ @Override
+ public boolean onCreate() {
+ mOpenHelper = new DatabaseHelper(getContext());
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri url, String[] select, String where, String[] whereArgs, String sort) {
+ SqlArguments args = new SqlArguments(url, where, whereArgs);
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+ qb.setTables(args.table);
+
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ Cursor ret = qb.query(db, select, args.where, args.args, null, null, sort);
+ ret.setNotificationUri(getContext().getContentResolver(), url);
+ return ret;
+ }
+
+ @Override
+ public String getType(Uri url) {
+ // If SqlArguments supplies a where clause, then it must be an item
+ // (because we aren't supplying our own where clause).
+ SqlArguments args = new SqlArguments(url, null, null);
+ if (TextUtils.isEmpty(args.where)) {
+ return "vnd.android.cursor.dir/" + args.table;
+ } else {
+ return "vnd.android.cursor.item/" + args.table;
+ }
+ }
+
+ @Override
+ public int bulkInsert(Uri uri, ContentValues[] values) {
+ SqlArguments args = new SqlArguments(uri);
+ checkWritePermissions(args);
+
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ int numValues = values.length;
+ for (int i = 0; i < numValues; i++) {
+ if (db.insert(args.table, null, values[i]) < 0) return 0;
+ if (LOCAL_LOGV) Log.v(TAG, args.table + " <- " + values[i]);
+ }
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+
+ sendNotify(uri);
+ return values.length;
+ }
+
+ @Override
+ public Uri insert(Uri url, ContentValues initialValues) {
+ SqlArguments args = new SqlArguments(url);
+ checkWritePermissions(args);
+
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ final long rowId = db.insert(args.table, null, initialValues);
+ if (rowId <= 0) return null;
+
+ if (LOCAL_LOGV) Log.v(TAG, args.table + " <- " + initialValues);
+ url = getUriFor(url, initialValues, rowId);
+ sendNotify(url);
+ return url;
+ }
+
+ @Override
+ public int delete(Uri url, String where, String[] whereArgs) {
+ SqlArguments args = new SqlArguments(url, where, whereArgs);
+ checkWritePermissions(args);
+
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ int count = db.delete(args.table, args.where, args.args);
+ if (count > 0) sendNotify(url);
+ if (LOCAL_LOGV) Log.v(TAG, args.table + ": " + count + " row(s) deleted");
+ return count;
+ }
+
+ @Override
+ public int update(Uri url, ContentValues initialValues, String where, String[] whereArgs) {
+ SqlArguments args = new SqlArguments(url, where, whereArgs);
+ checkWritePermissions(args);
+
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ int count = db.update(args.table, initialValues, args.where, args.args);
+ if (count > 0) sendNotify(url);
+ if (LOCAL_LOGV) Log.v(TAG, args.table + ": " + count + " row(s) <- " + initialValues);
+ return count;
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+
+ /*
+ * When a client attempts to openFile the default ringtone or
+ * notification setting Uri, we will proxy the call to the current
+ * default ringtone's Uri (if it is in the DRM or media provider).
+ */
+ int ringtoneType = RingtoneManager.getDefaultType(uri);
+ // Above call returns -1 if the Uri doesn't match a default type
+ if (ringtoneType != -1) {
+ Context context = getContext();
+
+ // Get the current value for the default sound
+ Uri soundUri = RingtoneManager.getActualDefaultRingtoneUri(context, ringtoneType);
+ if (soundUri == null) {
+ // Fallback on any valid ringtone Uri
+ soundUri = RingtoneManager.getValidRingtoneUri(context);
+ }
+
+ if (soundUri != null) {
+ // Only proxy the openFile call to drm or media providers
+ String authority = soundUri.getAuthority();
+ boolean isDrmAuthority = authority.equals(DrmStore.AUTHORITY);
+ if (isDrmAuthority || authority.equals(MediaStore.AUTHORITY)) {
+
+ if (isDrmAuthority) {
+ try {
+ // Check DRM access permission here, since once we
+ // do the below call the DRM will be checking our
+ // permission, not our caller's permission
+ DrmStore.enforceAccessDrmPermission(context);
+ } catch (SecurityException e) {
+ throw new FileNotFoundException(e.getMessage());
+ }
+ }
+
+ return context.getContentResolver().openFileDescriptor(soundUri, mode);
+ }
+ }
+ }
+
+ return super.openFile(uri, mode);
+ }
+}