1/*
2 * Copyright (C) 2007 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.providers.settings;
18
19import android.content.ComponentName;
20import android.content.ContentValues;
21import android.content.Context;
22import android.content.Intent;
23import android.content.pm.ActivityInfo;
24import android.content.pm.IPackageManager;
25import android.content.pm.PackageManager;
26import android.content.res.XmlResourceParser;
27import android.database.Cursor;
28import android.database.sqlite.SQLiteDatabase;
29import android.database.sqlite.SQLiteOpenHelper;
30import android.database.sqlite.SQLiteStatement;
31import android.media.AudioManager;
32import android.media.AudioService;
33import android.net.ConnectivityManager;
34import android.os.Environment;
35import android.os.RemoteException;
36import android.os.ServiceManager;
37import android.os.SystemProperties;
38import android.os.UserHandle;
39import android.provider.Settings;
40import android.provider.Settings.Global;
41import android.provider.Settings.Secure;
42import android.telephony.TelephonyManager;
43import android.text.TextUtils;
44import android.util.Log;
45
46import com.android.internal.content.PackageHelper;
47import com.android.internal.telephony.Phone;
48import com.android.internal.telephony.PhoneConstants;
49import com.android.internal.telephony.RILConstants;
50import com.android.internal.util.XmlUtils;
51import com.android.internal.widget.LockPatternUtils;
52import com.android.internal.widget.LockPatternView;
53
54import org.xmlpull.v1.XmlPullParser;
55import org.xmlpull.v1.XmlPullParserException;
56
57import java.io.File;
58import java.io.IOException;
59import java.util.HashSet;
60import java.util.List;
61
62/**
63 * Database helper class for {@link SettingsProvider}.
64 * Mostly just has a bit {@link #onCreate} to initialize the database.
65 */
66public class DatabaseHelper extends SQLiteOpenHelper {
67    private static final String TAG = "SettingsProvider";
68    private static final String DATABASE_NAME = "settings.db";
69
70    // Please, please please. If you update the database version, check to make sure the
71    // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
72    // is properly propagated through your change.  Not doing so will result in a loss of user
73    // settings.
74    private static final int DATABASE_VERSION = 95;
75
76    private Context mContext;
77    private int mUserHandle;
78
79    private static final HashSet<String> mValidTables = new HashSet<String>();
80
81    private static final String TABLE_SYSTEM = "system";
82    private static final String TABLE_SECURE = "secure";
83    private static final String TABLE_GLOBAL = "global";
84
85    static {
86        mValidTables.add(TABLE_SYSTEM);
87        mValidTables.add(TABLE_SECURE);
88        mValidTables.add(TABLE_GLOBAL);
89        mValidTables.add("bluetooth_devices");
90        mValidTables.add("bookmarks");
91
92        // These are old.
93        mValidTables.add("favorites");
94        mValidTables.add("gservices");
95        mValidTables.add("old_favorites");
96    }
97
98    static String dbNameForUser(final int userHandle) {
99        // The owner gets the unadorned db name;
100        if (userHandle == UserHandle.USER_OWNER) {
101            return DATABASE_NAME;
102        } else {
103            // Place the database in the user-specific data tree so that it's
104            // cleaned up automatically when the user is deleted.
105            File databaseFile = new File(
106                    Environment.getUserSystemDirectory(userHandle), DATABASE_NAME);
107            return databaseFile.getPath();
108        }
109    }
110
111    public DatabaseHelper(Context context, int userHandle) {
112        super(context, dbNameForUser(userHandle), null, DATABASE_VERSION);
113        mContext = context;
114        mUserHandle = userHandle;
115        setWriteAheadLoggingEnabled(true);
116    }
117
118    public static boolean isValidTable(String name) {
119        return mValidTables.contains(name);
120    }
121
122    private void createSecureTable(SQLiteDatabase db) {
123        db.execSQL("CREATE TABLE secure (" +
124                "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
125                "name TEXT UNIQUE ON CONFLICT REPLACE," +
126                "value TEXT" +
127                ");");
128        db.execSQL("CREATE INDEX secureIndex1 ON secure (name);");
129    }
130
131    private void createGlobalTable(SQLiteDatabase db) {
132        db.execSQL("CREATE TABLE global (" +
133                "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
134                "name TEXT UNIQUE ON CONFLICT REPLACE," +
135                "value TEXT" +
136                ");");
137        db.execSQL("CREATE INDEX globalIndex1 ON global (name);");
138    }
139
140    @Override
141    public void onCreate(SQLiteDatabase db) {
142        db.execSQL("CREATE TABLE system (" +
143                    "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
144                    "name TEXT UNIQUE ON CONFLICT REPLACE," +
145                    "value TEXT" +
146                    ");");
147        db.execSQL("CREATE INDEX systemIndex1 ON system (name);");
148
149        createSecureTable(db);
150
151        // Only create the global table for the singleton 'owner' user
152        if (mUserHandle == UserHandle.USER_OWNER) {
153            createGlobalTable(db);
154        }
155
156        db.execSQL("CREATE TABLE bluetooth_devices (" +
157                    "_id INTEGER PRIMARY KEY," +
158                    "name TEXT," +
159                    "addr TEXT," +
160                    "channel INTEGER," +
161                    "type INTEGER" +
162                    ");");
163
164        db.execSQL("CREATE TABLE bookmarks (" +
165                    "_id INTEGER PRIMARY KEY," +
166                    "title TEXT," +
167                    "folder TEXT," +
168                    "intent TEXT," +
169                    "shortcut INTEGER," +
170                    "ordering INTEGER" +
171                    ");");
172
173        db.execSQL("CREATE INDEX bookmarksIndex1 ON bookmarks (folder);");
174        db.execSQL("CREATE INDEX bookmarksIndex2 ON bookmarks (shortcut);");
175
176        // Populate bookmarks table with initial bookmarks
177        boolean onlyCore = false;
178        try {
179            onlyCore = IPackageManager.Stub.asInterface(ServiceManager.getService(
180                    "package")).isOnlyCoreApps();
181        } catch (RemoteException e) {
182        }
183        if (!onlyCore) {
184            loadBookmarks(db);
185        }
186
187        // Load initial volume levels into DB
188        loadVolumeLevels(db);
189
190        // Load inital settings values
191        loadSettings(db);
192    }
193
194    @Override
195    public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
196        Log.w(TAG, "Upgrading settings database from version " + oldVersion + " to "
197                + currentVersion);
198
199        int upgradeVersion = oldVersion;
200
201        // Pattern for upgrade blocks:
202        //
203        //    if (upgradeVersion == [the DATABASE_VERSION you set] - 1) {
204        //        .. your upgrade logic..
205        //        upgradeVersion = [the DATABASE_VERSION you set]
206        //    }
207
208        if (upgradeVersion == 20) {
209            /*
210             * Version 21 is part of the volume control refresh. There is no
211             * longer a UI-visible for setting notification vibrate on/off (in
212             * our design), but the functionality still exists. Force the
213             * notification vibrate to on.
214             */
215            loadVibrateSetting(db, true);
216
217            upgradeVersion = 21;
218        }
219
220        if (upgradeVersion < 22) {
221            upgradeVersion = 22;
222            // Upgrade the lock gesture storage location and format
223            upgradeLockPatternLocation(db);
224        }
225
226        if (upgradeVersion < 23) {
227            db.execSQL("UPDATE favorites SET iconResource=0 WHERE iconType=0");
228            upgradeVersion = 23;
229        }
230
231        if (upgradeVersion == 23) {
232            db.beginTransaction();
233            try {
234                db.execSQL("ALTER TABLE favorites ADD spanX INTEGER");
235                db.execSQL("ALTER TABLE favorites ADD spanY INTEGER");
236                // Shortcuts, applications, folders
237                db.execSQL("UPDATE favorites SET spanX=1, spanY=1 WHERE itemType<=0");
238                // Photo frames, clocks
239                db.execSQL(
240                    "UPDATE favorites SET spanX=2, spanY=2 WHERE itemType=1000 or itemType=1002");
241                // Search boxes
242                db.execSQL("UPDATE favorites SET spanX=4, spanY=1 WHERE itemType=1001");
243                db.setTransactionSuccessful();
244            } finally {
245                db.endTransaction();
246            }
247            upgradeVersion = 24;
248        }
249
250        if (upgradeVersion == 24) {
251            db.beginTransaction();
252            try {
253                // The value of the constants for preferring wifi or preferring mobile have been
254                // swapped, so reload the default.
255                db.execSQL("DELETE FROM system WHERE name='network_preference'");
256                db.execSQL("INSERT INTO system ('name', 'value') values ('network_preference', '" +
257                        ConnectivityManager.DEFAULT_NETWORK_PREFERENCE + "')");
258                db.setTransactionSuccessful();
259            } finally {
260                db.endTransaction();
261            }
262            upgradeVersion = 25;
263        }
264
265        if (upgradeVersion == 25) {
266            db.beginTransaction();
267            try {
268                db.execSQL("ALTER TABLE favorites ADD uri TEXT");
269                db.execSQL("ALTER TABLE favorites ADD displayMode INTEGER");
270                db.setTransactionSuccessful();
271            } finally {
272                db.endTransaction();
273            }
274            upgradeVersion = 26;
275        }
276
277        if (upgradeVersion == 26) {
278            // This introduces the new secure settings table.
279            db.beginTransaction();
280            try {
281                createSecureTable(db);
282                db.setTransactionSuccessful();
283            } finally {
284                db.endTransaction();
285            }
286            upgradeVersion = 27;
287        }
288
289        if (upgradeVersion == 27) {
290            String[] settingsToMove = {
291                    Settings.Secure.ADB_ENABLED,
292                    Settings.Secure.ANDROID_ID,
293                    Settings.Secure.BLUETOOTH_ON,
294                    Settings.Secure.DATA_ROAMING,
295                    Settings.Secure.DEVICE_PROVISIONED,
296                    Settings.Secure.HTTP_PROXY,
297                    Settings.Secure.INSTALL_NON_MARKET_APPS,
298                    Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
299                    Settings.Secure.LOGGING_ID,
300                    Settings.Secure.NETWORK_PREFERENCE,
301                    Settings.Secure.PARENTAL_CONTROL_ENABLED,
302                    Settings.Secure.PARENTAL_CONTROL_LAST_UPDATE,
303                    Settings.Secure.PARENTAL_CONTROL_REDIRECT_URL,
304                    Settings.Secure.SETTINGS_CLASSNAME,
305                    Settings.Secure.USB_MASS_STORAGE_ENABLED,
306                    Settings.Secure.USE_GOOGLE_MAIL,
307                    Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
308                    Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
309                    Settings.Secure.WIFI_NUM_OPEN_NETWORKS_KEPT,
310                    Settings.Secure.WIFI_ON,
311                    Settings.Secure.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE,
312                    Settings.Secure.WIFI_WATCHDOG_AP_COUNT,
313                    Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS,
314                    Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED,
315                    Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS,
316                    Settings.Secure.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT,
317                    Settings.Secure.WIFI_WATCHDOG_MAX_AP_CHECKS,
318                    Settings.Secure.WIFI_WATCHDOG_ON,
319                    Settings.Secure.WIFI_WATCHDOG_PING_COUNT,
320                    Settings.Secure.WIFI_WATCHDOG_PING_DELAY_MS,
321                    Settings.Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS,
322                };
323            moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_SECURE, settingsToMove, false);
324            upgradeVersion = 28;
325        }
326
327        if (upgradeVersion == 28 || upgradeVersion == 29) {
328            // Note: The upgrade to 28 was flawed since it didn't delete the old
329            // setting first before inserting. Combining 28 and 29 with the
330            // fixed version.
331
332            // This upgrade adds the STREAM_NOTIFICATION type to the list of
333            // types affected by ringer modes (silent, vibrate, etc.)
334            db.beginTransaction();
335            try {
336                db.execSQL("DELETE FROM system WHERE name='"
337                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'");
338                int newValue = (1 << AudioManager.STREAM_RING)
339                        | (1 << AudioManager.STREAM_NOTIFICATION)
340                        | (1 << AudioManager.STREAM_SYSTEM);
341                db.execSQL("INSERT INTO system ('name', 'value') values ('"
342                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '"
343                        + String.valueOf(newValue) + "')");
344                db.setTransactionSuccessful();
345            } finally {
346                db.endTransaction();
347            }
348
349            upgradeVersion = 30;
350        }
351
352        if (upgradeVersion == 30) {
353            /*
354             * Upgrade 31 clears the title for all quick launch shortcuts so the
355             * activities' titles will be resolved at display time. Also, the
356             * folder is changed to '@quicklaunch'.
357             */
358            db.beginTransaction();
359            try {
360                db.execSQL("UPDATE bookmarks SET folder = '@quicklaunch'");
361                db.execSQL("UPDATE bookmarks SET title = ''");
362                db.setTransactionSuccessful();
363            } finally {
364                db.endTransaction();
365            }
366            upgradeVersion = 31;
367        }
368
369        if (upgradeVersion == 31) {
370            /*
371             * Animations are now managed in preferences, and may be
372             * enabled or disabled based on product resources.
373             */
374            db.beginTransaction();
375            SQLiteStatement stmt = null;
376            try {
377                db.execSQL("DELETE FROM system WHERE name='"
378                        + Settings.System.WINDOW_ANIMATION_SCALE + "'");
379                db.execSQL("DELETE FROM system WHERE name='"
380                        + Settings.System.TRANSITION_ANIMATION_SCALE + "'");
381                stmt = db.compileStatement("INSERT INTO system(name,value)"
382                        + " VALUES(?,?);");
383                loadDefaultAnimationSettings(stmt);
384                db.setTransactionSuccessful();
385            } finally {
386                db.endTransaction();
387                if (stmt != null) stmt.close();
388            }
389            upgradeVersion = 32;
390        }
391
392        if (upgradeVersion == 32) {
393            // The Wi-Fi watchdog SSID list is now seeded with the value of
394            // the property ro.com.android.wifi-watchlist
395            String wifiWatchList = SystemProperties.get("ro.com.android.wifi-watchlist");
396            if (!TextUtils.isEmpty(wifiWatchList)) {
397                db.beginTransaction();
398                try {
399                    db.execSQL("INSERT OR IGNORE INTO secure(name,value) values('" +
400                            Settings.Secure.WIFI_WATCHDOG_WATCH_LIST + "','" +
401                            wifiWatchList + "');");
402                    db.setTransactionSuccessful();
403                } finally {
404                    db.endTransaction();
405                }
406            }
407            upgradeVersion = 33;
408        }
409
410        if (upgradeVersion == 33) {
411            // Set the default zoom controls to: tap-twice to bring up +/-
412            db.beginTransaction();
413            try {
414                db.execSQL("INSERT INTO system(name,value) values('zoom','2');");
415                db.setTransactionSuccessful();
416            } finally {
417                db.endTransaction();
418            }
419            upgradeVersion = 34;
420        }
421
422        if (upgradeVersion == 34) {
423            db.beginTransaction();
424            SQLiteStatement stmt = null;
425            try {
426                stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
427                        + " VALUES(?,?);");
428                loadSecure35Settings(stmt);
429                db.setTransactionSuccessful();
430            } finally {
431                db.endTransaction();
432                if (stmt != null) stmt.close();
433            }
434            upgradeVersion = 35;
435        }
436            // due to a botched merge from donut to eclair, the initialization of ASSISTED_GPS_ENABLED
437            // was accidentally done out of order here.
438            // to fix this, ASSISTED_GPS_ENABLED is now initialized while upgrading from 38 to 39,
439            // and we intentionally do nothing from 35 to 36 now.
440        if (upgradeVersion == 35) {
441            upgradeVersion = 36;
442        }
443
444        if (upgradeVersion == 36) {
445           // This upgrade adds the STREAM_SYSTEM_ENFORCED type to the list of
446            // types affected by ringer modes (silent, vibrate, etc.)
447            db.beginTransaction();
448            try {
449                db.execSQL("DELETE FROM system WHERE name='"
450                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'");
451                int newValue = (1 << AudioManager.STREAM_RING)
452                        | (1 << AudioManager.STREAM_NOTIFICATION)
453                        | (1 << AudioManager.STREAM_SYSTEM)
454                        | (1 << AudioManager.STREAM_SYSTEM_ENFORCED);
455                db.execSQL("INSERT INTO system ('name', 'value') values ('"
456                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '"
457                        + String.valueOf(newValue) + "')");
458                db.setTransactionSuccessful();
459            } finally {
460                db.endTransaction();
461            }
462            upgradeVersion = 37;
463        }
464
465        if (upgradeVersion == 37) {
466            db.beginTransaction();
467            SQLiteStatement stmt = null;
468            try {
469                stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
470                        + " VALUES(?,?);");
471                loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
472                        R.string.airplane_mode_toggleable_radios);
473                db.setTransactionSuccessful();
474            } finally {
475                db.endTransaction();
476                if (stmt != null) stmt.close();
477            }
478            upgradeVersion = 38;
479        }
480
481        if (upgradeVersion == 38) {
482            db.beginTransaction();
483            try {
484                String value =
485                        mContext.getResources().getBoolean(R.bool.assisted_gps_enabled) ? "1" : "0";
486                db.execSQL("INSERT OR IGNORE INTO secure(name,value) values('" +
487                        Settings.Global.ASSISTED_GPS_ENABLED + "','" + value + "');");
488                db.setTransactionSuccessful();
489            } finally {
490                db.endTransaction();
491            }
492
493            upgradeVersion = 39;
494        }
495
496        if (upgradeVersion == 39) {
497            upgradeAutoBrightness(db);
498            upgradeVersion = 40;
499        }
500
501        if (upgradeVersion == 40) {
502            /*
503             * All animations are now turned on by default!
504             */
505            db.beginTransaction();
506            SQLiteStatement stmt = null;
507            try {
508                db.execSQL("DELETE FROM system WHERE name='"
509                        + Settings.System.WINDOW_ANIMATION_SCALE + "'");
510                db.execSQL("DELETE FROM system WHERE name='"
511                        + Settings.System.TRANSITION_ANIMATION_SCALE + "'");
512                stmt = db.compileStatement("INSERT INTO system(name,value)"
513                        + " VALUES(?,?);");
514                loadDefaultAnimationSettings(stmt);
515                db.setTransactionSuccessful();
516            } finally {
517                db.endTransaction();
518                if (stmt != null) stmt.close();
519            }
520            upgradeVersion = 41;
521        }
522
523        if (upgradeVersion == 41) {
524            /*
525             * Initialize newly public haptic feedback setting
526             */
527            db.beginTransaction();
528            SQLiteStatement stmt = null;
529            try {
530                db.execSQL("DELETE FROM system WHERE name='"
531                        + Settings.System.HAPTIC_FEEDBACK_ENABLED + "'");
532                stmt = db.compileStatement("INSERT INTO system(name,value)"
533                        + " VALUES(?,?);");
534                loadDefaultHapticSettings(stmt);
535                db.setTransactionSuccessful();
536            } finally {
537                db.endTransaction();
538                if (stmt != null) stmt.close();
539            }
540            upgradeVersion = 42;
541        }
542
543        if (upgradeVersion == 42) {
544            /*
545             * Initialize new notification pulse setting
546             */
547            db.beginTransaction();
548            SQLiteStatement stmt = null;
549            try {
550                stmt = db.compileStatement("INSERT INTO system(name,value)"
551                        + " VALUES(?,?);");
552                loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
553                        R.bool.def_notification_pulse);
554                db.setTransactionSuccessful();
555            } finally {
556                db.endTransaction();
557                if (stmt != null) stmt.close();
558            }
559            upgradeVersion = 43;
560        }
561
562        if (upgradeVersion == 43) {
563            /*
564             * This upgrade stores bluetooth volume separately from voice volume
565             */
566            db.beginTransaction();
567            SQLiteStatement stmt = null;
568            try {
569                stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
570                        + " VALUES(?,?);");
571                loadSetting(stmt, Settings.System.VOLUME_BLUETOOTH_SCO,
572                        AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_BLUETOOTH_SCO]);
573                db.setTransactionSuccessful();
574            } finally {
575                db.endTransaction();
576                if (stmt != null) stmt.close();
577            }
578            upgradeVersion = 44;
579        }
580
581        if (upgradeVersion == 44) {
582            /*
583             * Gservices was moved into vendor/google.
584             */
585            db.execSQL("DROP TABLE IF EXISTS gservices");
586            db.execSQL("DROP INDEX IF EXISTS gservicesIndex1");
587            upgradeVersion = 45;
588        }
589
590        if (upgradeVersion == 45) {
591             /*
592              * New settings for MountService
593              */
594            db.beginTransaction();
595            try {
596                db.execSQL("INSERT INTO secure(name,value) values('" +
597                        Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND + "','1');");
598                db.execSQL("INSERT INTO secure(name,value) values('" +
599                        Settings.Secure.MOUNT_UMS_AUTOSTART + "','0');");
600                db.execSQL("INSERT INTO secure(name,value) values('" +
601                        Settings.Secure.MOUNT_UMS_PROMPT + "','1');");
602                db.execSQL("INSERT INTO secure(name,value) values('" +
603                        Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED + "','1');");
604                db.setTransactionSuccessful();
605            } finally {
606                db.endTransaction();
607            }
608            upgradeVersion = 46;
609        }
610
611        if (upgradeVersion == 46) {
612            /*
613             * The password mode constants have changed; reset back to no
614             * password.
615             */
616            db.beginTransaction();
617            try {
618                db.execSQL("DELETE FROM system WHERE name='lockscreen.password_type';");
619                db.setTransactionSuccessful();
620            } finally {
621                db.endTransaction();
622            }
623           upgradeVersion = 47;
624       }
625
626
627        if (upgradeVersion == 47) {
628            /*
629             * The password mode constants have changed again; reset back to no
630             * password.
631             */
632            db.beginTransaction();
633            try {
634                db.execSQL("DELETE FROM system WHERE name='lockscreen.password_type';");
635                db.setTransactionSuccessful();
636            } finally {
637                db.endTransaction();
638            }
639           upgradeVersion = 48;
640       }
641
642       if (upgradeVersion == 48) {
643           /*
644            * Default recognition service no longer initialized here,
645            * moved to RecognitionManagerService.
646            */
647           upgradeVersion = 49;
648       }
649
650       if (upgradeVersion == 49) {
651           /*
652            * New settings for new user interface noises.
653            */
654           db.beginTransaction();
655           SQLiteStatement stmt = null;
656           try {
657                stmt = db.compileStatement("INSERT INTO system(name,value)"
658                        + " VALUES(?,?);");
659                loadUISoundEffectsSettings(stmt);
660                db.setTransactionSuccessful();
661            } finally {
662                db.endTransaction();
663                if (stmt != null) stmt.close();
664            }
665
666           upgradeVersion = 50;
667       }
668
669       if (upgradeVersion == 50) {
670           /*
671            * Install location no longer initiated here.
672            */
673           upgradeVersion = 51;
674       }
675
676       if (upgradeVersion == 51) {
677           /* Move the lockscreen related settings to Secure, including some private ones. */
678           String[] settingsToMove = {
679                   Secure.LOCK_PATTERN_ENABLED,
680                   Secure.LOCK_PATTERN_VISIBLE,
681                   Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED,
682                   "lockscreen.password_type",
683                   "lockscreen.lockoutattemptdeadline",
684                   "lockscreen.patterneverchosen",
685                   "lock_pattern_autolock",
686                   "lockscreen.lockedoutpermanently",
687                   "lockscreen.password_salt"
688           };
689           moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_SECURE, settingsToMove, false);
690           upgradeVersion = 52;
691       }
692
693        if (upgradeVersion == 52) {
694            // new vibration/silent mode settings
695            db.beginTransaction();
696            SQLiteStatement stmt = null;
697            try {
698                stmt = db.compileStatement("INSERT INTO system(name,value)"
699                        + " VALUES(?,?);");
700                loadBooleanSetting(stmt, Settings.System.VIBRATE_IN_SILENT,
701                        R.bool.def_vibrate_in_silent);
702                db.setTransactionSuccessful();
703            } finally {
704                db.endTransaction();
705                if (stmt != null) stmt.close();
706            }
707
708            upgradeVersion = 53;
709        }
710
711        if (upgradeVersion == 53) {
712            /*
713             * New settings for set install location UI no longer initiated here.
714             */
715            upgradeVersion = 54;
716        }
717
718        if (upgradeVersion == 54) {
719            /*
720             * Update the screen timeout value if set to never
721             */
722            db.beginTransaction();
723            try {
724                upgradeScreenTimeoutFromNever(db);
725                db.setTransactionSuccessful();
726            } finally {
727                db.endTransaction();
728            }
729
730            upgradeVersion = 55;
731        }
732
733        if (upgradeVersion == 55) {
734            /* Move the install location settings. */
735            String[] settingsToMove = {
736                    Global.SET_INSTALL_LOCATION,
737                    Global.DEFAULT_INSTALL_LOCATION
738            };
739            moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_SECURE, settingsToMove, false);
740            db.beginTransaction();
741            SQLiteStatement stmt = null;
742            try {
743                stmt = db.compileStatement("INSERT INTO system(name,value)"
744                        + " VALUES(?,?);");
745                loadSetting(stmt, Global.SET_INSTALL_LOCATION, 0);
746                loadSetting(stmt, Global.DEFAULT_INSTALL_LOCATION,
747                        PackageHelper.APP_INSTALL_AUTO);
748                db.setTransactionSuccessful();
749             } finally {
750                 db.endTransaction();
751                 if (stmt != null) stmt.close();
752             }
753            upgradeVersion = 56;
754        }
755
756        if (upgradeVersion == 56) {
757            /*
758             * Add Bluetooth to list of toggleable radios in airplane mode
759             */
760            db.beginTransaction();
761            SQLiteStatement stmt = null;
762            try {
763                db.execSQL("DELETE FROM system WHERE name='"
764                        + Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS + "'");
765                stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
766                        + " VALUES(?,?);");
767                loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
768                        R.string.airplane_mode_toggleable_radios);
769                db.setTransactionSuccessful();
770            } finally {
771                db.endTransaction();
772                if (stmt != null) stmt.close();
773            }
774            upgradeVersion = 57;
775        }
776
777        /************* The following are Honeycomb changes ************/
778
779        if (upgradeVersion == 57) {
780            /*
781             * New settings to:
782             *  1. Enable injection of accessibility scripts in WebViews.
783             *  2. Define the key bindings for traversing web content in WebViews.
784             */
785            db.beginTransaction();
786            SQLiteStatement stmt = null;
787            try {
788                stmt = db.compileStatement("INSERT INTO secure(name,value)"
789                        + " VALUES(?,?);");
790                loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION,
791                        R.bool.def_accessibility_script_injection);
792                stmt.close();
793                stmt = db.compileStatement("INSERT INTO secure(name,value)"
794                        + " VALUES(?,?);");
795                loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS,
796                        R.string.def_accessibility_web_content_key_bindings);
797                db.setTransactionSuccessful();
798            } finally {
799                db.endTransaction();
800                if (stmt != null) stmt.close();
801            }
802            upgradeVersion = 58;
803        }
804
805        if (upgradeVersion == 58) {
806            /* Add default for new Auto Time Zone */
807            int autoTimeValue = getIntValueFromSystem(db, Settings.System.AUTO_TIME, 0);
808            db.beginTransaction();
809            SQLiteStatement stmt = null;
810            try {
811                stmt = db.compileStatement("INSERT INTO system(name,value)" + " VALUES(?,?);");
812                loadSetting(stmt, Settings.System.AUTO_TIME_ZONE,
813                        autoTimeValue); // Sync timezone to NITZ if auto_time was enabled
814                db.setTransactionSuccessful();
815            } finally {
816                db.endTransaction();
817                if (stmt != null) stmt.close();
818            }
819            upgradeVersion = 59;
820        }
821
822        if (upgradeVersion == 59) {
823            // Persistence for the rotation lock feature.
824            db.beginTransaction();
825            SQLiteStatement stmt = null;
826            try {
827                stmt = db.compileStatement("INSERT INTO system(name,value)"
828                        + " VALUES(?,?);");
829                loadBooleanSetting(stmt, Settings.System.USER_ROTATION,
830                        R.integer.def_user_rotation); // should be zero degrees
831                db.setTransactionSuccessful();
832            } finally {
833                db.endTransaction();
834                if (stmt != null) stmt.close();
835            }
836            upgradeVersion = 60;
837        }
838
839        if (upgradeVersion == 60) {
840            // Don't do this for upgrades from Gingerbread
841            // Were only required for intra-Honeycomb upgrades for testing
842            // upgradeScreenTimeout(db);
843            upgradeVersion = 61;
844        }
845
846        if (upgradeVersion == 61) {
847            // Don't do this for upgrades from Gingerbread
848            // Were only required for intra-Honeycomb upgrades for testing
849            // upgradeScreenTimeout(db);
850            upgradeVersion = 62;
851        }
852
853        // Change the default for screen auto-brightness mode
854        if (upgradeVersion == 62) {
855            // Don't do this for upgrades from Gingerbread
856            // Were only required for intra-Honeycomb upgrades for testing
857            // upgradeAutoBrightness(db);
858            upgradeVersion = 63;
859        }
860
861        if (upgradeVersion == 63) {
862            // This upgrade adds the STREAM_MUSIC type to the list of
863             // types affected by ringer modes (silent, vibrate, etc.)
864             db.beginTransaction();
865             try {
866                 db.execSQL("DELETE FROM system WHERE name='"
867                         + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'");
868                 int newValue = (1 << AudioManager.STREAM_RING)
869                         | (1 << AudioManager.STREAM_NOTIFICATION)
870                         | (1 << AudioManager.STREAM_SYSTEM)
871                         | (1 << AudioManager.STREAM_SYSTEM_ENFORCED)
872                         | (1 << AudioManager.STREAM_MUSIC);
873                 db.execSQL("INSERT INTO system ('name', 'value') values ('"
874                         + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '"
875                         + String.valueOf(newValue) + "')");
876                 db.setTransactionSuccessful();
877             } finally {
878                 db.endTransaction();
879             }
880             upgradeVersion = 64;
881         }
882
883        if (upgradeVersion == 64) {
884            // New setting to configure the long press timeout.
885            db.beginTransaction();
886            SQLiteStatement stmt = null;
887            try {
888                stmt = db.compileStatement("INSERT INTO secure(name,value)"
889                        + " VALUES(?,?);");
890                loadIntegerSetting(stmt, Settings.Secure.LONG_PRESS_TIMEOUT,
891                        R.integer.def_long_press_timeout_millis);
892                stmt.close();
893                db.setTransactionSuccessful();
894            } finally {
895                db.endTransaction();
896                if (stmt != null) stmt.close();
897            }
898            upgradeVersion = 65;
899        }
900
901        /************* The following are Ice Cream Sandwich changes ************/
902
903        if (upgradeVersion == 65) {
904            /*
905             * Animations are removed from Settings. Turned on by default
906             */
907            db.beginTransaction();
908            SQLiteStatement stmt = null;
909            try {
910                db.execSQL("DELETE FROM system WHERE name='"
911                        + Settings.System.WINDOW_ANIMATION_SCALE + "'");
912                db.execSQL("DELETE FROM system WHERE name='"
913                        + Settings.System.TRANSITION_ANIMATION_SCALE + "'");
914                stmt = db.compileStatement("INSERT INTO system(name,value)"
915                        + " VALUES(?,?);");
916                loadDefaultAnimationSettings(stmt);
917                db.setTransactionSuccessful();
918            } finally {
919                db.endTransaction();
920                if (stmt != null) stmt.close();
921            }
922            upgradeVersion = 66;
923        }
924
925        if (upgradeVersion == 66) {
926            // This upgrade makes sure that MODE_RINGER_STREAMS_AFFECTED is set
927            // according to device voice capability
928            db.beginTransaction();
929            try {
930                int ringerModeAffectedStreams = (1 << AudioManager.STREAM_RING) |
931                                                (1 << AudioManager.STREAM_NOTIFICATION) |
932                                                (1 << AudioManager.STREAM_SYSTEM) |
933                                                (1 << AudioManager.STREAM_SYSTEM_ENFORCED);
934                if (!mContext.getResources().getBoolean(
935                        com.android.internal.R.bool.config_voice_capable)) {
936                    ringerModeAffectedStreams |= (1 << AudioManager.STREAM_MUSIC);
937                }
938                db.execSQL("DELETE FROM system WHERE name='"
939                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'");
940                db.execSQL("INSERT INTO system ('name', 'value') values ('"
941                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '"
942                        + String.valueOf(ringerModeAffectedStreams) + "')");
943                db.setTransactionSuccessful();
944            } finally {
945                db.endTransaction();
946            }
947            upgradeVersion = 67;
948        }
949
950        if (upgradeVersion == 67) {
951            // New setting to enable touch exploration.
952            db.beginTransaction();
953            SQLiteStatement stmt = null;
954            try {
955                stmt = db.compileStatement("INSERT INTO secure(name,value)"
956                        + " VALUES(?,?);");
957                loadBooleanSetting(stmt, Settings.Secure.TOUCH_EXPLORATION_ENABLED,
958                        R.bool.def_touch_exploration_enabled);
959                stmt.close();
960                db.setTransactionSuccessful();
961            } finally {
962                db.endTransaction();
963                if (stmt != null) stmt.close();
964            }
965            upgradeVersion = 68;
966        }
967
968        if (upgradeVersion == 68) {
969            // Enable all system sounds by default
970            db.beginTransaction();
971            try {
972                db.execSQL("DELETE FROM system WHERE name='"
973                        + Settings.System.NOTIFICATIONS_USE_RING_VOLUME + "'");
974                db.setTransactionSuccessful();
975            } finally {
976                db.endTransaction();
977            }
978            upgradeVersion = 69;
979        }
980
981        if (upgradeVersion == 69) {
982            // Add RADIO_NFC to AIRPLANE_MODE_RADIO and AIRPLANE_MODE_TOGGLEABLE_RADIOS
983            String airplaneRadios = mContext.getResources().getString(
984                    R.string.def_airplane_mode_radios);
985            String toggleableRadios = mContext.getResources().getString(
986                    R.string.airplane_mode_toggleable_radios);
987            db.beginTransaction();
988            try {
989                db.execSQL("UPDATE system SET value='" + airplaneRadios + "' " +
990                        "WHERE name='" + Settings.System.AIRPLANE_MODE_RADIOS + "'");
991                db.execSQL("UPDATE system SET value='" + toggleableRadios + "' " +
992                        "WHERE name='" + Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS + "'");
993                db.setTransactionSuccessful();
994            } finally {
995                db.endTransaction();
996            }
997            upgradeVersion = 70;
998        }
999
1000        if (upgradeVersion == 70) {
1001            // Update all built-in bookmarks.  Some of the package names have changed.
1002            loadBookmarks(db);
1003            upgradeVersion = 71;
1004        }
1005
1006        if (upgradeVersion == 71) {
1007             // New setting to specify whether to speak passwords in accessibility mode.
1008            db.beginTransaction();
1009            SQLiteStatement stmt = null;
1010            try {
1011                stmt = db.compileStatement("INSERT INTO secure(name,value)"
1012                        + " VALUES(?,?);");
1013                loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD,
1014                        R.bool.def_accessibility_speak_password);
1015                db.setTransactionSuccessful();
1016            } finally {
1017                db.endTransaction();
1018                if (stmt != null) stmt.close();
1019            }
1020            upgradeVersion = 72;
1021        }
1022
1023        if (upgradeVersion == 72) {
1024            // update vibration settings
1025            db.beginTransaction();
1026            SQLiteStatement stmt = null;
1027            try {
1028                stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)"
1029                        + " VALUES(?,?);");
1030                loadBooleanSetting(stmt, Settings.System.VIBRATE_IN_SILENT,
1031                        R.bool.def_vibrate_in_silent);
1032                db.setTransactionSuccessful();
1033            } finally {
1034                db.endTransaction();
1035                if (stmt != null) stmt.close();
1036            }
1037            upgradeVersion = 73;
1038        }
1039
1040        if (upgradeVersion == 73) {
1041            upgradeVibrateSettingFromNone(db);
1042            upgradeVersion = 74;
1043        }
1044
1045        if (upgradeVersion == 74) {
1046            // URL from which WebView loads a JavaScript based screen-reader.
1047            db.beginTransaction();
1048            SQLiteStatement stmt = null;
1049            try {
1050                stmt = db.compileStatement("INSERT INTO secure(name,value) VALUES(?,?);");
1051                loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_SCREEN_READER_URL,
1052                        R.string.def_accessibility_screen_reader_url);
1053                db.setTransactionSuccessful();
1054            } finally {
1055                db.endTransaction();
1056                if (stmt != null) stmt.close();
1057            }
1058            upgradeVersion = 75;
1059        }
1060        if (upgradeVersion == 75) {
1061            db.beginTransaction();
1062            SQLiteStatement stmt = null;
1063            Cursor c = null;
1064            try {
1065                c = db.query(TABLE_SECURE, new String[] {"_id", "value"},
1066                        "name='lockscreen.disabled'",
1067                        null, null, null, null);
1068                // only set default if it has not yet been set
1069                if (c == null || c.getCount() == 0) {
1070                    stmt = db.compileStatement("INSERT INTO system(name,value)"
1071                            + " VALUES(?,?);");
1072                    loadBooleanSetting(stmt, Settings.System.LOCKSCREEN_DISABLED,
1073                            R.bool.def_lockscreen_disabled);
1074                }
1075                db.setTransactionSuccessful();
1076            } finally {
1077                db.endTransaction();
1078                if (c != null) c.close();
1079                if (stmt != null) stmt.close();
1080            }
1081            upgradeVersion = 76;
1082        }
1083
1084        /************* The following are Jelly Bean changes ************/
1085
1086        if (upgradeVersion == 76) {
1087            // Removed VIBRATE_IN_SILENT setting
1088            db.beginTransaction();
1089            try {
1090                db.execSQL("DELETE FROM system WHERE name='"
1091                                + Settings.System.VIBRATE_IN_SILENT + "'");
1092                db.setTransactionSuccessful();
1093            } finally {
1094                db.endTransaction();
1095            }
1096
1097            upgradeVersion = 77;
1098        }
1099
1100        if (upgradeVersion == 77) {
1101            // Introduce "vibrate when ringing" setting
1102            loadVibrateWhenRingingSetting(db);
1103
1104            upgradeVersion = 78;
1105        }
1106
1107        if (upgradeVersion == 78) {
1108            // The JavaScript based screen-reader URL changes in JellyBean.
1109            db.beginTransaction();
1110            SQLiteStatement stmt = null;
1111            try {
1112                stmt = db.compileStatement("INSERT OR REPLACE INTO secure(name,value)"
1113                        + " VALUES(?,?);");
1114                loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_SCREEN_READER_URL,
1115                        R.string.def_accessibility_screen_reader_url);
1116                db.setTransactionSuccessful();
1117            } finally {
1118                db.endTransaction();
1119                if (stmt != null) stmt.close();
1120            }
1121            upgradeVersion = 79;
1122        }
1123
1124        if (upgradeVersion == 79) {
1125            // Before touch exploration was a global setting controlled by the user
1126            // via the UI. However, if the enabled accessibility services do not
1127            // handle touch exploration mode, enabling it makes no sense. Therefore,
1128            // now the services request touch exploration mode and the user is
1129            // presented with a dialog to allow that and if she does we store that
1130            // in the database. As a result of this change a user that has enabled
1131            // accessibility, touch exploration, and some accessibility services
1132            // may lose touch exploration state, thus rendering the device useless
1133            // unless sighted help is provided, since the enabled service(s) are
1134            // not in the list of services to which the user granted a permission
1135            // to put the device in touch explore mode. Here we are allowing all
1136            // enabled accessibility services to toggle touch exploration provided
1137            // accessibility and touch exploration are enabled and no services can
1138            // toggle touch exploration. Note that the user has already manually
1139            // enabled the services and touch exploration which means the she has
1140            // given consent to have these services work in touch exploration mode.
1141            final boolean accessibilityEnabled = getIntValueFromTable(db, TABLE_SECURE,
1142                    Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
1143            final boolean touchExplorationEnabled = getIntValueFromTable(db, TABLE_SECURE,
1144                    Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1;
1145            if (accessibilityEnabled && touchExplorationEnabled) {
1146                String enabledServices = getStringValueFromTable(db, TABLE_SECURE,
1147                        Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "");
1148                String touchExplorationGrantedServices = getStringValueFromTable(db, TABLE_SECURE,
1149                        Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, "");
1150                if (TextUtils.isEmpty(touchExplorationGrantedServices)
1151                        && !TextUtils.isEmpty(enabledServices)) {
1152                    SQLiteStatement stmt = null;
1153                    try {
1154                        db.beginTransaction();
1155                        stmt = db.compileStatement("INSERT OR REPLACE INTO secure(name,value)"
1156                                + " VALUES(?,?);");
1157                        loadSetting(stmt,
1158                                Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
1159                                enabledServices);
1160                        db.setTransactionSuccessful();
1161                    } finally {
1162                        db.endTransaction();
1163                        if (stmt != null) stmt.close();
1164                    }
1165                }
1166            }
1167            upgradeVersion = 80;
1168        }
1169
1170        // vvv Jelly Bean MR1 changes begin here vvv
1171
1172        if (upgradeVersion == 80) {
1173            // update screensaver settings
1174            db.beginTransaction();
1175            SQLiteStatement stmt = null;
1176            try {
1177                stmt = db.compileStatement("INSERT OR REPLACE INTO secure(name,value)"
1178                        + " VALUES(?,?);");
1179                loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ENABLED,
1180                        com.android.internal.R.bool.config_dreamsEnabledByDefault);
1181                loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
1182                        com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
1183                loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
1184                        com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
1185                loadStringSetting(stmt, Settings.Secure.SCREENSAVER_COMPONENTS,
1186                        com.android.internal.R.string.config_dreamsDefaultComponent);
1187                loadStringSetting(stmt, Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
1188                        com.android.internal.R.string.config_dreamsDefaultComponent);
1189
1190                db.setTransactionSuccessful();
1191            } finally {
1192                db.endTransaction();
1193                if (stmt != null) stmt.close();
1194            }
1195            upgradeVersion = 81;
1196        }
1197
1198        if (upgradeVersion == 81) {
1199            // Add package verification setting
1200            db.beginTransaction();
1201            SQLiteStatement stmt = null;
1202            try {
1203                stmt = db.compileStatement("INSERT OR REPLACE INTO secure(name,value)"
1204                        + " VALUES(?,?);");
1205                loadBooleanSetting(stmt, Settings.Global.PACKAGE_VERIFIER_ENABLE,
1206                        R.bool.def_package_verifier_enable);
1207                db.setTransactionSuccessful();
1208            } finally {
1209                db.endTransaction();
1210                if (stmt != null) stmt.close();
1211            }
1212            upgradeVersion = 82;
1213        }
1214
1215        if (upgradeVersion == 82) {
1216            // Move to per-user settings dbs
1217            if (mUserHandle == UserHandle.USER_OWNER) {
1218
1219                db.beginTransaction();
1220                SQLiteStatement stmt = null;
1221                try {
1222                    // Migrate now-global settings. Note that this happens before
1223                    // new users can be created.
1224                    createGlobalTable(db);
1225                    String[] settingsToMove = hashsetToStringArray(SettingsProvider.sSystemGlobalKeys);
1226                    moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, settingsToMove, false);
1227                    settingsToMove = hashsetToStringArray(SettingsProvider.sSecureGlobalKeys);
1228                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, false);
1229
1230                    db.setTransactionSuccessful();
1231                } finally {
1232                    db.endTransaction();
1233                    if (stmt != null) stmt.close();
1234                }
1235            }
1236            upgradeVersion = 83;
1237        }
1238
1239        if (upgradeVersion == 83) {
1240            // 1. Setting whether screen magnification is enabled.
1241            // 2. Setting for screen magnification scale.
1242            // 3. Setting for screen magnification auto update.
1243            db.beginTransaction();
1244            SQLiteStatement stmt = null;
1245            try {
1246                stmt = db.compileStatement("INSERT INTO secure(name,value) VALUES(?,?);");
1247                loadBooleanSetting(stmt,
1248                        Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
1249                        R.bool.def_accessibility_display_magnification_enabled);
1250                stmt.close();
1251                stmt = db.compileStatement("INSERT INTO secure(name,value) VALUES(?,?);");
1252                loadFractionSetting(stmt, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
1253                        R.fraction.def_accessibility_display_magnification_scale, 1);
1254                stmt.close();
1255                stmt = db.compileStatement("INSERT INTO secure(name,value) VALUES(?,?);");
1256                loadBooleanSetting(stmt,
1257                        Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE,
1258                        R.bool.def_accessibility_display_magnification_auto_update);
1259
1260                db.setTransactionSuccessful();
1261            } finally {
1262                db.endTransaction();
1263                if (stmt != null) stmt.close();
1264            }
1265            upgradeVersion = 84;
1266        }
1267
1268        if (upgradeVersion == 84) {
1269            if (mUserHandle == UserHandle.USER_OWNER) {
1270                db.beginTransaction();
1271                SQLiteStatement stmt = null;
1272                try {
1273                    // Patch up the slightly-wrong key migration from 82 -> 83 for those
1274                    // devices that missed it, ignoring if the move is redundant
1275                    String[] settingsToMove = {
1276                            Settings.Secure.ADB_ENABLED,
1277                            Settings.Secure.BLUETOOTH_ON,
1278                            Settings.Secure.DATA_ROAMING,
1279                            Settings.Secure.DEVICE_PROVISIONED,
1280                            Settings.Secure.INSTALL_NON_MARKET_APPS,
1281                            Settings.Secure.USB_MASS_STORAGE_ENABLED
1282                    };
1283                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true);
1284                    db.setTransactionSuccessful();
1285                } finally {
1286                    db.endTransaction();
1287                    if (stmt != null) stmt.close();
1288                }
1289            }
1290            upgradeVersion = 85;
1291        }
1292
1293        if (upgradeVersion == 85) {
1294            if (mUserHandle == UserHandle.USER_OWNER) {
1295                db.beginTransaction();
1296                try {
1297                    // Fix up the migration, ignoring already-migrated elements, to snap up to
1298                    // date with new changes to the set of global versus system/secure settings
1299                    String[] settingsToMove = { Settings.System.STAY_ON_WHILE_PLUGGED_IN };
1300                    moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, settingsToMove, true);
1301
1302                    db.setTransactionSuccessful();
1303                } finally {
1304                    db.endTransaction();
1305                }
1306            }
1307            upgradeVersion = 86;
1308        }
1309
1310        if (upgradeVersion == 86) {
1311            if (mUserHandle == UserHandle.USER_OWNER) {
1312                db.beginTransaction();
1313                try {
1314                    String[] settingsToMove = {
1315                            Settings.Global.PACKAGE_VERIFIER_ENABLE,
1316                            Settings.Global.PACKAGE_VERIFIER_TIMEOUT,
1317                            Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE
1318                    };
1319                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true);
1320
1321                    db.setTransactionSuccessful();
1322                } finally {
1323                    db.endTransaction();
1324                }
1325            }
1326            upgradeVersion = 87;
1327        }
1328
1329        if (upgradeVersion == 87) {
1330            if (mUserHandle == UserHandle.USER_OWNER) {
1331                db.beginTransaction();
1332                try {
1333                    String[] settingsToMove = {
1334                            Settings.Global.DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS,
1335                            Settings.Global.DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS,
1336                            Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS
1337                    };
1338                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true);
1339
1340                    db.setTransactionSuccessful();
1341                } finally {
1342                    db.endTransaction();
1343                }
1344            }
1345            upgradeVersion = 88;
1346        }
1347
1348        if (upgradeVersion == 88) {
1349            if (mUserHandle == UserHandle.USER_OWNER) {
1350                db.beginTransaction();
1351                try {
1352                    String[] settingsToMove = {
1353                            Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD,
1354                            Settings.Global.BATTERY_DISCHARGE_THRESHOLD,
1355                            Settings.Global.SEND_ACTION_APP_ERROR,
1356                            Settings.Global.DROPBOX_AGE_SECONDS,
1357                            Settings.Global.DROPBOX_MAX_FILES,
1358                            Settings.Global.DROPBOX_QUOTA_KB,
1359                            Settings.Global.DROPBOX_QUOTA_PERCENT,
1360                            Settings.Global.DROPBOX_RESERVE_PERCENT,
1361                            Settings.Global.DROPBOX_TAG_PREFIX,
1362                            Settings.Global.ERROR_LOGCAT_PREFIX,
1363                            Settings.Global.SYS_FREE_STORAGE_LOG_INTERVAL,
1364                            Settings.Global.DISK_FREE_CHANGE_REPORTING_THRESHOLD,
1365                            Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE,
1366                            Settings.Global.SYS_STORAGE_THRESHOLD_MAX_BYTES,
1367                            Settings.Global.SYS_STORAGE_FULL_THRESHOLD_BYTES,
1368                            Settings.Global.SYNC_MAX_RETRY_DELAY_IN_SECONDS,
1369                            Settings.Global.CONNECTIVITY_CHANGE_DELAY,
1370                            Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED,
1371                            Settings.Global.CAPTIVE_PORTAL_SERVER,
1372                            Settings.Global.NSD_ON,
1373                            Settings.Global.SET_INSTALL_LOCATION,
1374                            Settings.Global.DEFAULT_INSTALL_LOCATION,
1375                            Settings.Global.INET_CONDITION_DEBOUNCE_UP_DELAY,
1376                            Settings.Global.INET_CONDITION_DEBOUNCE_DOWN_DELAY,
1377                            Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT,
1378                            Settings.Global.HTTP_PROXY,
1379                            Settings.Global.GLOBAL_HTTP_PROXY_HOST,
1380                            Settings.Global.GLOBAL_HTTP_PROXY_PORT,
1381                            Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
1382                            Settings.Global.SET_GLOBAL_HTTP_PROXY,
1383                            Settings.Global.DEFAULT_DNS_SERVER,
1384                    };
1385                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true);
1386                    db.setTransactionSuccessful();
1387                } finally {
1388                    db.endTransaction();
1389                }
1390            }
1391            upgradeVersion = 89;
1392        }
1393
1394        if (upgradeVersion == 89) {
1395            if (mUserHandle == UserHandle.USER_OWNER) {
1396                db.beginTransaction();
1397                try {
1398                    String[] prefixesToMove = {
1399                            Settings.Global.BLUETOOTH_HEADSET_PRIORITY_PREFIX,
1400                            Settings.Global.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX,
1401                            Settings.Global.BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX,
1402                    };
1403
1404                    movePrefixedSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, prefixesToMove);
1405
1406                    db.setTransactionSuccessful();
1407                } finally {
1408                    db.endTransaction();
1409                }
1410            }
1411            upgradeVersion = 90;
1412        }
1413
1414        if (upgradeVersion == 90) {
1415            if (mUserHandle == UserHandle.USER_OWNER) {
1416                db.beginTransaction();
1417                try {
1418                    String[] systemToGlobal = {
1419                            Settings.Global.WINDOW_ANIMATION_SCALE,
1420                            Settings.Global.TRANSITION_ANIMATION_SCALE,
1421                            Settings.Global.ANIMATOR_DURATION_SCALE,
1422                            Settings.Global.FANCY_IME_ANIMATIONS,
1423                            Settings.Global.COMPATIBILITY_MODE,
1424                            Settings.Global.EMERGENCY_TONE,
1425                            Settings.Global.CALL_AUTO_RETRY,
1426                            Settings.Global.DEBUG_APP,
1427                            Settings.Global.WAIT_FOR_DEBUGGER,
1428                            Settings.Global.SHOW_PROCESSES,
1429                            Settings.Global.ALWAYS_FINISH_ACTIVITIES,
1430                    };
1431                    String[] secureToGlobal = {
1432                            Settings.Global.PREFERRED_NETWORK_MODE,
1433                            Settings.Global.PREFERRED_CDMA_SUBSCRIPTION,
1434                    };
1435
1436                    moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, systemToGlobal, true);
1437                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, secureToGlobal, true);
1438
1439                    db.setTransactionSuccessful();
1440                } finally {
1441                    db.endTransaction();
1442                }
1443            }
1444            upgradeVersion = 91;
1445        }
1446
1447        if (upgradeVersion == 91) {
1448            if (mUserHandle == UserHandle.USER_OWNER) {
1449                db.beginTransaction();
1450                try {
1451                    // Move ringer mode from system to global settings
1452                    String[] settingsToMove = { Settings.Global.MODE_RINGER };
1453                    moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, settingsToMove, true);
1454
1455                    db.setTransactionSuccessful();
1456                } finally {
1457                    db.endTransaction();
1458                }
1459            }
1460            upgradeVersion = 92;
1461        }
1462
1463        if (upgradeVersion == 92) {
1464            SQLiteStatement stmt = null;
1465            try {
1466                stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
1467                        + " VALUES(?,?);");
1468                if (mUserHandle == UserHandle.USER_OWNER) {
1469                    // consider existing primary users to have made it through user setup
1470                    // if the globally-scoped device-provisioned bit is set
1471                    // (indicating they already made it through setup as primary)
1472                    int deviceProvisioned = getIntValueFromTable(db, TABLE_GLOBAL,
1473                            Settings.Global.DEVICE_PROVISIONED, 0);
1474                    loadSetting(stmt, Settings.Secure.USER_SETUP_COMPLETE,
1475                            deviceProvisioned);
1476                } else {
1477                    // otherwise use the default
1478                    loadBooleanSetting(stmt, Settings.Secure.USER_SETUP_COMPLETE,
1479                            R.bool.def_user_setup_complete);
1480                }
1481            } finally {
1482                if (stmt != null) stmt.close();
1483            }
1484            upgradeVersion = 93;
1485        }
1486
1487        if (upgradeVersion == 93) {
1488            // Redo this step, since somehow it didn't work the first time for some users
1489            if (mUserHandle == UserHandle.USER_OWNER) {
1490                db.beginTransaction();
1491                SQLiteStatement stmt = null;
1492                try {
1493                    // Migrate now-global settings
1494                    String[] settingsToMove = hashsetToStringArray(SettingsProvider.sSystemGlobalKeys);
1495                    moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, settingsToMove, true);
1496                    settingsToMove = hashsetToStringArray(SettingsProvider.sSecureGlobalKeys);
1497                    moveSettingsToNewTable(db, TABLE_SECURE, TABLE_GLOBAL, settingsToMove, true);
1498
1499                    db.setTransactionSuccessful();
1500                } finally {
1501                    db.endTransaction();
1502                    if (stmt != null) stmt.close();
1503                }
1504            }
1505            upgradeVersion = 94;
1506        }
1507
1508        if (upgradeVersion == 94) {
1509            // Add wireless charging started sound setting
1510            if (mUserHandle == UserHandle.USER_OWNER) {
1511                db.beginTransaction();
1512                SQLiteStatement stmt = null;
1513                try {
1514                    stmt = db.compileStatement("INSERT OR REPLACE INTO global(name,value)"
1515                            + " VALUES(?,?);");
1516                    loadStringSetting(stmt, Settings.Global.WIRELESS_CHARGING_STARTED_SOUND,
1517                            R.string.def_wireless_charging_started_sound);
1518                    db.setTransactionSuccessful();
1519                } finally {
1520                    db.endTransaction();
1521                    if (stmt != null) stmt.close();
1522                }
1523            }
1524            upgradeVersion = 95;
1525        }
1526
1527        // *** Remember to update DATABASE_VERSION above!
1528
1529        if (upgradeVersion != currentVersion) {
1530            Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion
1531                    + ", must wipe the settings provider");
1532            db.execSQL("DROP TABLE IF EXISTS global");
1533            db.execSQL("DROP TABLE IF EXISTS globalIndex1");
1534            db.execSQL("DROP TABLE IF EXISTS system");
1535            db.execSQL("DROP INDEX IF EXISTS systemIndex1");
1536            db.execSQL("DROP TABLE IF EXISTS secure");
1537            db.execSQL("DROP INDEX IF EXISTS secureIndex1");
1538            db.execSQL("DROP TABLE IF EXISTS gservices");
1539            db.execSQL("DROP INDEX IF EXISTS gservicesIndex1");
1540            db.execSQL("DROP TABLE IF EXISTS bluetooth_devices");
1541            db.execSQL("DROP TABLE IF EXISTS bookmarks");
1542            db.execSQL("DROP INDEX IF EXISTS bookmarksIndex1");
1543            db.execSQL("DROP INDEX IF EXISTS bookmarksIndex2");
1544            db.execSQL("DROP TABLE IF EXISTS favorites");
1545            onCreate(db);
1546
1547            // Added for diagnosing settings.db wipes after the fact
1548            String wipeReason = oldVersion + "/" + upgradeVersion + "/" + currentVersion;
1549            db.execSQL("INSERT INTO secure(name,value) values('" +
1550                    "wiped_db_reason" + "','" + wipeReason + "');");
1551        }
1552    }
1553
1554    private String[] hashsetToStringArray(HashSet<String> set) {
1555        String[] array = new String[set.size()];
1556        return set.toArray(array);
1557    }
1558
1559    private void moveSettingsToNewTable(SQLiteDatabase db,
1560            String sourceTable, String destTable,
1561            String[] settingsToMove, boolean doIgnore) {
1562        // Copy settings values from the source table to the dest, and remove from the source
1563        SQLiteStatement insertStmt = null;
1564        SQLiteStatement deleteStmt = null;
1565
1566        db.beginTransaction();
1567        try {
1568            insertStmt = db.compileStatement("INSERT "
1569                    + (doIgnore ? " OR IGNORE " : "")
1570                    + " INTO " + destTable + " (name,value) SELECT name,value FROM "
1571                    + sourceTable + " WHERE name=?");
1572            deleteStmt = db.compileStatement("DELETE FROM " + sourceTable + " WHERE name=?");
1573
1574            for (String setting : settingsToMove) {
1575                insertStmt.bindString(1, setting);
1576                insertStmt.execute();
1577
1578                deleteStmt.bindString(1, setting);
1579                deleteStmt.execute();
1580            }
1581            db.setTransactionSuccessful();
1582        } finally {
1583            db.endTransaction();
1584            if (insertStmt != null) {
1585                insertStmt.close();
1586            }
1587            if (deleteStmt != null) {
1588                deleteStmt.close();
1589            }
1590        }
1591    }
1592
1593    /**
1594     * Move any settings with the given prefixes from the source table to the
1595     * destination table.
1596     */
1597    private void movePrefixedSettingsToNewTable(
1598            SQLiteDatabase db, String sourceTable, String destTable, String[] prefixesToMove) {
1599        SQLiteStatement insertStmt = null;
1600        SQLiteStatement deleteStmt = null;
1601
1602        db.beginTransaction();
1603        try {
1604            insertStmt = db.compileStatement("INSERT INTO " + destTable
1605                    + " (name,value) SELECT name,value FROM " + sourceTable
1606                    + " WHERE substr(name,0,?)=?");
1607            deleteStmt = db.compileStatement(
1608                    "DELETE FROM " + sourceTable + " WHERE substr(name,0,?)=?");
1609
1610            for (String prefix : prefixesToMove) {
1611                insertStmt.bindLong(1, prefix.length() + 1);
1612                insertStmt.bindString(2, prefix);
1613                insertStmt.execute();
1614
1615                deleteStmt.bindLong(1, prefix.length() + 1);
1616                deleteStmt.bindString(2, prefix);
1617                deleteStmt.execute();
1618            }
1619            db.setTransactionSuccessful();
1620        } finally {
1621            db.endTransaction();
1622            if (insertStmt != null) {
1623                insertStmt.close();
1624            }
1625            if (deleteStmt != null) {
1626                deleteStmt.close();
1627            }
1628        }
1629    }
1630
1631    private void upgradeLockPatternLocation(SQLiteDatabase db) {
1632        Cursor c = db.query(TABLE_SYSTEM, new String[] {"_id", "value"}, "name='lock_pattern'",
1633                null, null, null, null);
1634        if (c.getCount() > 0) {
1635            c.moveToFirst();
1636            String lockPattern = c.getString(1);
1637            if (!TextUtils.isEmpty(lockPattern)) {
1638                // Convert lock pattern
1639                try {
1640                    LockPatternUtils lpu = new LockPatternUtils(mContext);
1641                    List<LockPatternView.Cell> cellPattern =
1642                            LockPatternUtils.stringToPattern(lockPattern);
1643                    lpu.saveLockPattern(cellPattern);
1644                } catch (IllegalArgumentException e) {
1645                    // Don't want corrupted lock pattern to hang the reboot process
1646                }
1647            }
1648            c.close();
1649            db.delete(TABLE_SYSTEM, "name='lock_pattern'", null);
1650        } else {
1651            c.close();
1652        }
1653    }
1654
1655    private void upgradeScreenTimeoutFromNever(SQLiteDatabase db) {
1656        // See if the timeout is -1 (for "Never").
1657        Cursor c = db.query(TABLE_SYSTEM, new String[] { "_id", "value" }, "name=? AND value=?",
1658                new String[] { Settings.System.SCREEN_OFF_TIMEOUT, "-1" },
1659                null, null, null);
1660
1661        SQLiteStatement stmt = null;
1662        if (c.getCount() > 0) {
1663            c.close();
1664            try {
1665                stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)"
1666                        + " VALUES(?,?);");
1667
1668                // Set the timeout to 30 minutes in milliseconds
1669                loadSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
1670                        Integer.toString(30 * 60 * 1000));
1671            } finally {
1672                if (stmt != null) stmt.close();
1673            }
1674        } else {
1675            c.close();
1676        }
1677    }
1678
1679    private void upgradeVibrateSettingFromNone(SQLiteDatabase db) {
1680        int vibrateSetting = getIntValueFromSystem(db, Settings.System.VIBRATE_ON, 0);
1681        // If the ringer vibrate value is invalid, set it to the default
1682        if ((vibrateSetting & 3) == AudioManager.VIBRATE_SETTING_OFF) {
1683            vibrateSetting = AudioService.getValueForVibrateSetting(0,
1684                    AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_ONLY_SILENT);
1685        }
1686        // Apply the same setting to the notification vibrate value
1687        vibrateSetting = AudioService.getValueForVibrateSetting(vibrateSetting,
1688                AudioManager.VIBRATE_TYPE_NOTIFICATION, vibrateSetting);
1689
1690        SQLiteStatement stmt = null;
1691        try {
1692            stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)"
1693                    + " VALUES(?,?);");
1694            loadSetting(stmt, Settings.System.VIBRATE_ON, vibrateSetting);
1695        } finally {
1696            if (stmt != null)
1697                stmt.close();
1698        }
1699    }
1700
1701    private void upgradeScreenTimeout(SQLiteDatabase db) {
1702        // Change screen timeout to current default
1703        db.beginTransaction();
1704        SQLiteStatement stmt = null;
1705        try {
1706            stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)"
1707                    + " VALUES(?,?);");
1708            loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
1709                    R.integer.def_screen_off_timeout);
1710            db.setTransactionSuccessful();
1711        } finally {
1712            db.endTransaction();
1713            if (stmt != null)
1714                stmt.close();
1715        }
1716    }
1717
1718    private void upgradeAutoBrightness(SQLiteDatabase db) {
1719        db.beginTransaction();
1720        try {
1721            String value =
1722                    mContext.getResources().getBoolean(
1723                    R.bool.def_screen_brightness_automatic_mode) ? "1" : "0";
1724            db.execSQL("INSERT OR REPLACE INTO system(name,value) values('" +
1725                    Settings.System.SCREEN_BRIGHTNESS_MODE + "','" + value + "');");
1726            db.setTransactionSuccessful();
1727        } finally {
1728            db.endTransaction();
1729        }
1730    }
1731
1732    /**
1733     * Loads the default set of bookmarked shortcuts from an xml file.
1734     *
1735     * @param db The database to write the values into
1736     */
1737    private void loadBookmarks(SQLiteDatabase db) {
1738        ContentValues values = new ContentValues();
1739
1740        PackageManager packageManager = mContext.getPackageManager();
1741        try {
1742            XmlResourceParser parser = mContext.getResources().getXml(R.xml.bookmarks);
1743            XmlUtils.beginDocument(parser, "bookmarks");
1744
1745            final int depth = parser.getDepth();
1746            int type;
1747
1748            while (((type = parser.next()) != XmlPullParser.END_TAG ||
1749                    parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
1750
1751                if (type != XmlPullParser.START_TAG) {
1752                    continue;
1753                }
1754
1755                String name = parser.getName();
1756                if (!"bookmark".equals(name)) {
1757                    break;
1758                }
1759
1760                String pkg = parser.getAttributeValue(null, "package");
1761                String cls = parser.getAttributeValue(null, "class");
1762                String shortcutStr = parser.getAttributeValue(null, "shortcut");
1763                String category = parser.getAttributeValue(null, "category");
1764
1765                int shortcutValue = shortcutStr.charAt(0);
1766                if (TextUtils.isEmpty(shortcutStr)) {
1767                    Log.w(TAG, "Unable to get shortcut for: " + pkg + "/" + cls);
1768                    continue;
1769                }
1770
1771                final Intent intent;
1772                final String title;
1773                if (pkg != null && cls != null) {
1774                    ActivityInfo info = null;
1775                    ComponentName cn = new ComponentName(pkg, cls);
1776                    try {
1777                        info = packageManager.getActivityInfo(cn, 0);
1778                    } catch (PackageManager.NameNotFoundException e) {
1779                        String[] packages = packageManager.canonicalToCurrentPackageNames(
1780                                new String[] { pkg });
1781                        cn = new ComponentName(packages[0], cls);
1782                        try {
1783                            info = packageManager.getActivityInfo(cn, 0);
1784                        } catch (PackageManager.NameNotFoundException e1) {
1785                            Log.w(TAG, "Unable to add bookmark: " + pkg + "/" + cls, e);
1786                            continue;
1787                        }
1788                    }
1789
1790                    intent = new Intent(Intent.ACTION_MAIN, null);
1791                    intent.addCategory(Intent.CATEGORY_LAUNCHER);
1792                    intent.setComponent(cn);
1793                    title = info.loadLabel(packageManager).toString();
1794                } else if (category != null) {
1795                    intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
1796                    title = "";
1797                } else {
1798                    Log.w(TAG, "Unable to add bookmark for shortcut " + shortcutStr
1799                            + ": missing package/class or category attributes");
1800                    continue;
1801                }
1802
1803                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1804                values.put(Settings.Bookmarks.INTENT, intent.toUri(0));
1805                values.put(Settings.Bookmarks.TITLE, title);
1806                values.put(Settings.Bookmarks.SHORTCUT, shortcutValue);
1807                db.delete("bookmarks", "shortcut = ?",
1808                        new String[] { Integer.toString(shortcutValue) });
1809                db.insert("bookmarks", null, values);
1810            }
1811        } catch (XmlPullParserException e) {
1812            Log.w(TAG, "Got execption parsing bookmarks.", e);
1813        } catch (IOException e) {
1814            Log.w(TAG, "Got execption parsing bookmarks.", e);
1815        }
1816    }
1817
1818    /**
1819     * Loads the default volume levels. It is actually inserting the index of
1820     * the volume array for each of the volume controls.
1821     *
1822     * @param db the database to insert the volume levels into
1823     */
1824    private void loadVolumeLevels(SQLiteDatabase db) {
1825        SQLiteStatement stmt = null;
1826        try {
1827            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
1828                    + " VALUES(?,?);");
1829
1830            loadSetting(stmt, Settings.System.VOLUME_MUSIC,
1831                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_MUSIC]);
1832            loadSetting(stmt, Settings.System.VOLUME_RING,
1833                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_RING]);
1834            loadSetting(stmt, Settings.System.VOLUME_SYSTEM,
1835                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_SYSTEM]);
1836            loadSetting(
1837                    stmt,
1838                    Settings.System.VOLUME_VOICE,
1839                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_VOICE_CALL]);
1840            loadSetting(stmt, Settings.System.VOLUME_ALARM,
1841                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_ALARM]);
1842            loadSetting(
1843                    stmt,
1844                    Settings.System.VOLUME_NOTIFICATION,
1845                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_NOTIFICATION]);
1846            loadSetting(
1847                    stmt,
1848                    Settings.System.VOLUME_BLUETOOTH_SCO,
1849                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_BLUETOOTH_SCO]);
1850
1851            // By default:
1852            // - ringtones, notification, system and music streams are affected by ringer mode
1853            // on non voice capable devices (tablets)
1854            // - ringtones, notification and system streams are affected by ringer mode
1855            // on voice capable devices (phones)
1856            int ringerModeAffectedStreams = (1 << AudioManager.STREAM_RING) |
1857                                            (1 << AudioManager.STREAM_NOTIFICATION) |
1858                                            (1 << AudioManager.STREAM_SYSTEM) |
1859                                            (1 << AudioManager.STREAM_SYSTEM_ENFORCED);
1860            if (!mContext.getResources().getBoolean(
1861                    com.android.internal.R.bool.config_voice_capable)) {
1862                ringerModeAffectedStreams |= (1 << AudioManager.STREAM_MUSIC);
1863            }
1864            loadSetting(stmt, Settings.System.MODE_RINGER_STREAMS_AFFECTED,
1865                    ringerModeAffectedStreams);
1866
1867            loadSetting(stmt, Settings.System.MUTE_STREAMS_AFFECTED,
1868                    ((1 << AudioManager.STREAM_MUSIC) |
1869                     (1 << AudioManager.STREAM_RING) |
1870                     (1 << AudioManager.STREAM_NOTIFICATION) |
1871                     (1 << AudioManager.STREAM_SYSTEM)));
1872        } finally {
1873            if (stmt != null) stmt.close();
1874        }
1875
1876        loadVibrateWhenRingingSetting(db);
1877    }
1878
1879    private void loadVibrateSetting(SQLiteDatabase db, boolean deleteOld) {
1880        if (deleteOld) {
1881            db.execSQL("DELETE FROM system WHERE name='" + Settings.System.VIBRATE_ON + "'");
1882        }
1883
1884        SQLiteStatement stmt = null;
1885        try {
1886            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
1887                    + " VALUES(?,?);");
1888
1889            // Vibrate on by default for ringer, on for notification
1890            int vibrate = 0;
1891            vibrate = AudioService.getValueForVibrateSetting(vibrate,
1892                    AudioManager.VIBRATE_TYPE_NOTIFICATION,
1893                    AudioManager.VIBRATE_SETTING_ONLY_SILENT);
1894            vibrate |= AudioService.getValueForVibrateSetting(vibrate,
1895                    AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_ONLY_SILENT);
1896            loadSetting(stmt, Settings.System.VIBRATE_ON, vibrate);
1897        } finally {
1898            if (stmt != null) stmt.close();
1899        }
1900    }
1901
1902    private void loadVibrateWhenRingingSetting(SQLiteDatabase db) {
1903        // The default should be off. VIBRATE_SETTING_ONLY_SILENT should also be ignored here.
1904        // Phone app should separately check whether AudioManager#getRingerMode() returns
1905        // RINGER_MODE_VIBRATE, with which the device should vibrate anyway.
1906        int vibrateSetting = getIntValueFromSystem(db, Settings.System.VIBRATE_ON,
1907                AudioManager.VIBRATE_SETTING_OFF);
1908        boolean vibrateWhenRinging = ((vibrateSetting & 3) == AudioManager.VIBRATE_SETTING_ON);
1909
1910        SQLiteStatement stmt = null;
1911        try {
1912            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
1913                    + " VALUES(?,?);");
1914            loadSetting(stmt, Settings.System.VIBRATE_WHEN_RINGING, vibrateWhenRinging ? 1 : 0);
1915        } finally {
1916            if (stmt != null) stmt.close();
1917        }
1918    }
1919
1920    private void loadSettings(SQLiteDatabase db) {
1921        loadSystemSettings(db);
1922        loadSecureSettings(db);
1923        // The global table only exists for the 'owner' user
1924        if (mUserHandle == UserHandle.USER_OWNER) {
1925            loadGlobalSettings(db);
1926        }
1927    }
1928
1929    private void loadSystemSettings(SQLiteDatabase db) {
1930        SQLiteStatement stmt = null;
1931        try {
1932            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
1933                    + " VALUES(?,?);");
1934
1935            loadBooleanSetting(stmt, Settings.System.DIM_SCREEN,
1936                    R.bool.def_dim_screen);
1937            loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
1938                    R.integer.def_screen_off_timeout);
1939
1940            // Set default cdma DTMF type
1941            loadSetting(stmt, Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, 0);
1942
1943            // Set default hearing aid
1944            loadSetting(stmt, Settings.System.HEARING_AID, 0);
1945
1946            // Set default tty mode
1947            loadSetting(stmt, Settings.System.TTY_MODE, 0);
1948
1949            loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS,
1950                    R.integer.def_screen_brightness);
1951
1952            loadBooleanSetting(stmt, Settings.System.SCREEN_BRIGHTNESS_MODE,
1953                    R.bool.def_screen_brightness_automatic_mode);
1954
1955            loadDefaultAnimationSettings(stmt);
1956
1957            loadBooleanSetting(stmt, Settings.System.ACCELEROMETER_ROTATION,
1958                    R.bool.def_accelerometer_rotation);
1959
1960            loadDefaultHapticSettings(stmt);
1961
1962            loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
1963                    R.bool.def_notification_pulse);
1964
1965            loadUISoundEffectsSettings(stmt);
1966
1967            loadIntegerSetting(stmt, Settings.System.POINTER_SPEED,
1968                    R.integer.def_pointer_speed);
1969        } finally {
1970            if (stmt != null) stmt.close();
1971        }
1972    }
1973
1974    private void loadUISoundEffectsSettings(SQLiteStatement stmt) {
1975        loadBooleanSetting(stmt, Settings.System.DTMF_TONE_WHEN_DIALING,
1976                R.bool.def_dtmf_tones_enabled);
1977        loadBooleanSetting(stmt, Settings.System.SOUND_EFFECTS_ENABLED,
1978                R.bool.def_sound_effects_enabled);
1979        loadBooleanSetting(stmt, Settings.System.HAPTIC_FEEDBACK_ENABLED,
1980                R.bool.def_haptic_feedback);
1981
1982        loadIntegerSetting(stmt, Settings.System.LOCKSCREEN_SOUNDS_ENABLED,
1983            R.integer.def_lockscreen_sounds_enabled);
1984    }
1985
1986    private void loadDefaultAnimationSettings(SQLiteStatement stmt) {
1987        loadFractionSetting(stmt, Settings.System.WINDOW_ANIMATION_SCALE,
1988                R.fraction.def_window_animation_scale, 1);
1989        loadFractionSetting(stmt, Settings.System.TRANSITION_ANIMATION_SCALE,
1990                R.fraction.def_window_transition_scale, 1);
1991    }
1992
1993    private void loadDefaultHapticSettings(SQLiteStatement stmt) {
1994        loadBooleanSetting(stmt, Settings.System.HAPTIC_FEEDBACK_ENABLED,
1995                R.bool.def_haptic_feedback);
1996    }
1997
1998    private void loadSecureSettings(SQLiteDatabase db) {
1999        SQLiteStatement stmt = null;
2000        try {
2001            stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
2002                    + " VALUES(?,?);");
2003
2004            loadStringSetting(stmt, Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
2005                    R.string.def_location_providers_allowed);
2006
2007            String wifiWatchList = SystemProperties.get("ro.com.android.wifi-watchlist");
2008            if (!TextUtils.isEmpty(wifiWatchList)) {
2009                loadSetting(stmt, Settings.Secure.WIFI_WATCHDOG_WATCH_LIST, wifiWatchList);
2010            }
2011
2012            // Don't do this.  The SystemServer will initialize ADB_ENABLED from a
2013            // persistent system property instead.
2014            //loadSetting(stmt, Settings.Secure.ADB_ENABLED, 0);
2015
2016            // Allow mock locations default, based on build
2017            loadSetting(stmt, Settings.Secure.ALLOW_MOCK_LOCATION,
2018                    "1".equals(SystemProperties.get("ro.allow.mock.location")) ? 1 : 0);
2019
2020            loadSecure35Settings(stmt);
2021
2022            loadBooleanSetting(stmt, Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND,
2023                    R.bool.def_mount_play_notification_snd);
2024
2025            loadBooleanSetting(stmt, Settings.Secure.MOUNT_UMS_AUTOSTART,
2026                    R.bool.def_mount_ums_autostart);
2027
2028            loadBooleanSetting(stmt, Settings.Secure.MOUNT_UMS_PROMPT,
2029                    R.bool.def_mount_ums_prompt);
2030
2031            loadBooleanSetting(stmt, Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED,
2032                    R.bool.def_mount_ums_notify_enabled);
2033
2034            loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION,
2035                    R.bool.def_accessibility_script_injection);
2036
2037            loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS,
2038                    R.string.def_accessibility_web_content_key_bindings);
2039
2040            loadIntegerSetting(stmt, Settings.Secure.LONG_PRESS_TIMEOUT,
2041                    R.integer.def_long_press_timeout_millis);
2042
2043            loadBooleanSetting(stmt, Settings.Secure.TOUCH_EXPLORATION_ENABLED,
2044                    R.bool.def_touch_exploration_enabled);
2045
2046            loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD,
2047                    R.bool.def_accessibility_speak_password);
2048
2049            loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_SCREEN_READER_URL,
2050                    R.string.def_accessibility_screen_reader_url);
2051
2052            if (SystemProperties.getBoolean("ro.lockscreen.disable.default", false) == true) {
2053                loadSetting(stmt, Settings.System.LOCKSCREEN_DISABLED, "1");
2054            } else {
2055                loadBooleanSetting(stmt, Settings.System.LOCKSCREEN_DISABLED,
2056                        R.bool.def_lockscreen_disabled);
2057            }
2058
2059            loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ENABLED,
2060                    com.android.internal.R.bool.config_dreamsEnabledByDefault);
2061            loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
2062                    com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
2063            loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP,
2064                    com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault);
2065            loadStringSetting(stmt, Settings.Secure.SCREENSAVER_COMPONENTS,
2066                    com.android.internal.R.string.config_dreamsDefaultComponent);
2067            loadStringSetting(stmt, Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT,
2068                    com.android.internal.R.string.config_dreamsDefaultComponent);
2069
2070            loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
2071                    R.bool.def_accessibility_display_magnification_enabled);
2072
2073            loadFractionSetting(stmt, Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
2074                    R.fraction.def_accessibility_display_magnification_scale, 1);
2075
2076            loadBooleanSetting(stmt,
2077                    Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_AUTO_UPDATE,
2078                    R.bool.def_accessibility_display_magnification_auto_update);
2079
2080            loadBooleanSetting(stmt, Settings.Secure.USER_SETUP_COMPLETE,
2081                    R.bool.def_user_setup_complete);
2082        } finally {
2083            if (stmt != null) stmt.close();
2084        }
2085    }
2086
2087    private void loadSecure35Settings(SQLiteStatement stmt) {
2088        loadBooleanSetting(stmt, Settings.Secure.BACKUP_ENABLED,
2089                R.bool.def_backup_enabled);
2090
2091        loadStringSetting(stmt, Settings.Secure.BACKUP_TRANSPORT,
2092                R.string.def_backup_transport);
2093    }
2094
2095    private void loadGlobalSettings(SQLiteDatabase db) {
2096        SQLiteStatement stmt = null;
2097        try {
2098            stmt = db.compileStatement("INSERT OR IGNORE INTO global(name,value)"
2099                    + " VALUES(?,?);");
2100
2101            // --- Previously in 'system'
2102            loadBooleanSetting(stmt, Settings.Global.AIRPLANE_MODE_ON,
2103                    R.bool.def_airplane_mode_on);
2104
2105            loadStringSetting(stmt, Settings.Global.AIRPLANE_MODE_RADIOS,
2106                    R.string.def_airplane_mode_radios);
2107
2108            loadStringSetting(stmt, Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
2109                    R.string.airplane_mode_toggleable_radios);
2110
2111            loadBooleanSetting(stmt, Settings.Global.ASSISTED_GPS_ENABLED,
2112                    R.bool.assisted_gps_enabled);
2113
2114            loadBooleanSetting(stmt, Settings.Global.AUTO_TIME,
2115                    R.bool.def_auto_time); // Sync time to NITZ
2116
2117            loadBooleanSetting(stmt, Settings.Global.AUTO_TIME_ZONE,
2118                    R.bool.def_auto_time_zone); // Sync timezone to NITZ
2119
2120            loadSetting(stmt, Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
2121                    ("1".equals(SystemProperties.get("ro.kernel.qemu")) ||
2122                        mContext.getResources().getBoolean(R.bool.def_stay_on_while_plugged_in))
2123                     ? 1 : 0);
2124
2125            loadIntegerSetting(stmt, Settings.Global.WIFI_SLEEP_POLICY,
2126                    R.integer.def_wifi_sleep_policy);
2127
2128            loadSetting(stmt, Settings.Global.MODE_RINGER,
2129                    AudioManager.RINGER_MODE_NORMAL);
2130
2131            // --- Previously in 'secure'
2132            loadBooleanSetting(stmt, Settings.Global.PACKAGE_VERIFIER_ENABLE,
2133                    R.bool.def_package_verifier_enable);
2134
2135            loadBooleanSetting(stmt, Settings.Global.WIFI_ON,
2136                    R.bool.def_wifi_on);
2137
2138            loadBooleanSetting(stmt, Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
2139                    R.bool.def_networks_available_notification_on);
2140
2141            loadBooleanSetting(stmt, Settings.Global.BLUETOOTH_ON,
2142                    R.bool.def_bluetooth_on);
2143
2144            // Enable or disable Cell Broadcast SMS
2145            loadSetting(stmt, Settings.Global.CDMA_CELL_BROADCAST_SMS,
2146                    RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED);
2147
2148            // Data roaming default, based on build
2149            loadSetting(stmt, Settings.Global.DATA_ROAMING,
2150                    "true".equalsIgnoreCase(
2151                            SystemProperties.get("ro.com.android.dataroaming",
2152                                    "false")) ? 1 : 0);
2153
2154            loadBooleanSetting(stmt, Settings.Global.DEVICE_PROVISIONED,
2155                    R.bool.def_device_provisioned);
2156
2157            final int maxBytes = mContext.getResources().getInteger(
2158                    R.integer.def_download_manager_max_bytes_over_mobile);
2159            if (maxBytes > 0) {
2160                loadSetting(stmt, Settings.Global.DOWNLOAD_MAX_BYTES_OVER_MOBILE,
2161                        Integer.toString(maxBytes));
2162            }
2163
2164            final int recommendedMaxBytes = mContext.getResources().getInteger(
2165                    R.integer.def_download_manager_recommended_max_bytes_over_mobile);
2166            if (recommendedMaxBytes > 0) {
2167                loadSetting(stmt, Settings.Global.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE,
2168                        Integer.toString(recommendedMaxBytes));
2169            }
2170
2171            // Mobile Data default, based on build
2172            loadSetting(stmt, Settings.Global.MOBILE_DATA,
2173                    "true".equalsIgnoreCase(
2174                            SystemProperties.get("ro.com.android.mobiledata",
2175                                    "true")) ? 1 : 0);
2176
2177            loadBooleanSetting(stmt, Settings.Global.NETSTATS_ENABLED,
2178                    R.bool.def_netstats_enabled);
2179
2180            loadBooleanSetting(stmt, Settings.Global.INSTALL_NON_MARKET_APPS,
2181                    R.bool.def_install_non_market_apps);
2182
2183            loadIntegerSetting(stmt, Settings.Global.NETWORK_PREFERENCE,
2184                    R.integer.def_network_preference);
2185
2186            loadBooleanSetting(stmt, Settings.Global.USB_MASS_STORAGE_ENABLED,
2187                    R.bool.def_usb_mass_storage_enabled);
2188
2189            loadIntegerSetting(stmt, Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
2190                    R.integer.def_max_dhcp_retries);
2191
2192            loadBooleanSetting(stmt, Settings.Global.WIFI_DISPLAY_ON,
2193                    R.bool.def_wifi_display_on);
2194
2195            loadStringSetting(stmt, Settings.Global.LOCK_SOUND,
2196                    R.string.def_lock_sound);
2197            loadStringSetting(stmt, Settings.Global.UNLOCK_SOUND,
2198                    R.string.def_unlock_sound);
2199            loadIntegerSetting(stmt, Settings.Global.POWER_SOUNDS_ENABLED,
2200                    R.integer.def_power_sounds_enabled);
2201            loadStringSetting(stmt, Settings.Global.LOW_BATTERY_SOUND,
2202                    R.string.def_low_battery_sound);
2203            loadIntegerSetting(stmt, Settings.Global.DOCK_SOUNDS_ENABLED,
2204                    R.integer.def_dock_sounds_enabled);
2205            loadStringSetting(stmt, Settings.Global.DESK_DOCK_SOUND,
2206                    R.string.def_desk_dock_sound);
2207            loadStringSetting(stmt, Settings.Global.DESK_UNDOCK_SOUND,
2208                    R.string.def_desk_undock_sound);
2209            loadStringSetting(stmt, Settings.Global.CAR_DOCK_SOUND,
2210                    R.string.def_car_dock_sound);
2211            loadStringSetting(stmt, Settings.Global.CAR_UNDOCK_SOUND,
2212                    R.string.def_car_undock_sound);
2213            loadStringSetting(stmt, Settings.Global.WIRELESS_CHARGING_STARTED_SOUND,
2214                    R.string.def_wireless_charging_started_sound);
2215
2216            loadSetting(stmt, Settings.Global.SET_INSTALL_LOCATION, 0);
2217            loadSetting(stmt, Settings.Global.DEFAULT_INSTALL_LOCATION,
2218                    PackageHelper.APP_INSTALL_AUTO);
2219
2220            // Set default cdma emergency tone
2221            loadSetting(stmt, Settings.Global.EMERGENCY_TONE, 0);
2222
2223            // Set default cdma call auto retry
2224            loadSetting(stmt, Settings.Global.CALL_AUTO_RETRY, 0);
2225
2226            // Set the preferred network mode to 0 = Global, CDMA default
2227            int type;
2228            if (TelephonyManager.getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) {
2229                type = Phone.NT_MODE_GLOBAL;
2230            } else {
2231                type = SystemProperties.getInt("ro.telephony.default_network",
2232                        RILConstants.PREFERRED_NETWORK_MODE);
2233            }
2234            loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, type);
2235
2236            // --- New global settings start here
2237        } finally {
2238            if (stmt != null) stmt.close();
2239        }
2240    }
2241
2242    private void loadSetting(SQLiteStatement stmt, String key, Object value) {
2243        stmt.bindString(1, key);
2244        stmt.bindString(2, value.toString());
2245        stmt.execute();
2246    }
2247
2248    private void loadStringSetting(SQLiteStatement stmt, String key, int resid) {
2249        loadSetting(stmt, key, mContext.getResources().getString(resid));
2250    }
2251
2252    private void loadBooleanSetting(SQLiteStatement stmt, String key, int resid) {
2253        loadSetting(stmt, key,
2254                mContext.getResources().getBoolean(resid) ? "1" : "0");
2255    }
2256
2257    private void loadIntegerSetting(SQLiteStatement stmt, String key, int resid) {
2258        loadSetting(stmt, key,
2259                Integer.toString(mContext.getResources().getInteger(resid)));
2260    }
2261
2262    private void loadFractionSetting(SQLiteStatement stmt, String key, int resid, int base) {
2263        loadSetting(stmt, key,
2264                Float.toString(mContext.getResources().getFraction(resid, base, base)));
2265    }
2266
2267    private int getIntValueFromSystem(SQLiteDatabase db, String name, int defaultValue) {
2268        return getIntValueFromTable(db, TABLE_SYSTEM, name, defaultValue);
2269    }
2270
2271    private int getIntValueFromTable(SQLiteDatabase db, String table, String name,
2272            int defaultValue) {
2273        String value = getStringValueFromTable(db, table, name, null);
2274        return (value != null) ? Integer.parseInt(value) : defaultValue;
2275    }
2276
2277    private String getStringValueFromTable(SQLiteDatabase db, String table, String name,
2278            String defaultValue) {
2279        Cursor c = null;
2280        try {
2281            c = db.query(table, new String[] { Settings.System.VALUE }, "name='" + name + "'",
2282                    null, null, null, null);
2283            if (c != null && c.moveToFirst()) {
2284                String val = c.getString(0);
2285                return val == null ? defaultValue : val;
2286            }
2287        } finally {
2288            if (c != null) c.close();
2289        }
2290        return defaultValue;
2291    }
2292}
2293