DatabaseHelper.java revision fdb7c36a108e6a7887de6611b3f1541e3009f2d5
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.PackageManager;
25import android.content.res.XmlResourceParser;
26import android.database.Cursor;
27import android.database.sqlite.SQLiteDatabase;
28import android.database.sqlite.SQLiteOpenHelper;
29import android.database.sqlite.SQLiteStatement;
30import android.media.AudioManager;
31import android.media.AudioService;
32import android.net.ConnectivityManager;
33import android.os.SystemProperties;
34import android.provider.Settings;
35import android.provider.Settings.Secure;
36import android.telephony.TelephonyManager;
37import android.text.TextUtils;
38import android.util.Log;
39
40import com.android.internal.content.PackageHelper;
41import com.android.internal.telephony.BaseCommands;
42import com.android.internal.telephony.Phone;
43import com.android.internal.telephony.PhoneConstants;
44import com.android.internal.telephony.RILConstants;
45import com.android.internal.util.XmlUtils;
46import com.android.internal.widget.LockPatternUtils;
47import com.android.internal.widget.LockPatternView;
48
49import org.xmlpull.v1.XmlPullParser;
50import org.xmlpull.v1.XmlPullParserException;
51
52import java.io.IOException;
53import java.util.HashSet;
54import java.util.List;
55
56/**
57 * Database helper class for {@link SettingsProvider}.
58 * Mostly just has a bit {@link #onCreate} to initialize the database.
59 */
60public class DatabaseHelper extends SQLiteOpenHelper {
61    private static final String TAG = "SettingsProvider";
62    private static final String DATABASE_NAME = "settings.db";
63
64    // Please, please please. If you update the database version, check to make sure the
65    // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
66    // is properly propagated through your change.  Not doing so will result in a loss of user
67    // settings.
68    private static final int DATABASE_VERSION = 80;
69
70    private Context mContext;
71
72    private static final HashSet<String> mValidTables = new HashSet<String>();
73
74    static {
75        mValidTables.add("system");
76        mValidTables.add("secure");
77        mValidTables.add("bluetooth_devices");
78        mValidTables.add("bookmarks");
79
80        // These are old.
81        mValidTables.add("favorites");
82        mValidTables.add("gservices");
83        mValidTables.add("old_favorites");
84    }
85
86    public DatabaseHelper(Context context) {
87        super(context, DATABASE_NAME, null, DATABASE_VERSION);
88        mContext = context;
89        setWriteAheadLoggingEnabled(true);
90    }
91
92    public static boolean isValidTable(String name) {
93        return mValidTables.contains(name);
94    }
95
96    private void createSecureTable(SQLiteDatabase db) {
97        db.execSQL("CREATE TABLE secure (" +
98                "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
99                "name TEXT UNIQUE ON CONFLICT REPLACE," +
100                "value TEXT" +
101                ");");
102        db.execSQL("CREATE INDEX secureIndex1 ON secure (name);");
103    }
104
105    @Override
106    public void onCreate(SQLiteDatabase db) {
107        db.execSQL("CREATE TABLE system (" +
108                    "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
109                    "name TEXT UNIQUE ON CONFLICT REPLACE," +
110                    "value TEXT" +
111                    ");");
112        db.execSQL("CREATE INDEX systemIndex1 ON system (name);");
113
114        createSecureTable(db);
115
116        db.execSQL("CREATE TABLE bluetooth_devices (" +
117                    "_id INTEGER PRIMARY KEY," +
118                    "name TEXT," +
119                    "addr TEXT," +
120                    "channel INTEGER," +
121                    "type INTEGER" +
122                    ");");
123
124        db.execSQL("CREATE TABLE bookmarks (" +
125                    "_id INTEGER PRIMARY KEY," +
126                    "title TEXT," +
127                    "folder TEXT," +
128                    "intent TEXT," +
129                    "shortcut INTEGER," +
130                    "ordering INTEGER" +
131                    ");");
132
133        db.execSQL("CREATE INDEX bookmarksIndex1 ON bookmarks (folder);");
134        db.execSQL("CREATE INDEX bookmarksIndex2 ON bookmarks (shortcut);");
135
136        // Populate bookmarks table with initial bookmarks
137        loadBookmarks(db);
138
139        // Load initial volume levels into DB
140        loadVolumeLevels(db);
141
142        // Load inital settings values
143        loadSettings(db);
144    }
145
146    @Override
147    public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
148        Log.w(TAG, "Upgrading settings database from version " + oldVersion + " to "
149                + currentVersion);
150
151        int upgradeVersion = oldVersion;
152
153        // Pattern for upgrade blocks:
154        //
155        //    if (upgradeVersion == [the DATABASE_VERSION you set] - 1) {
156        //        .. your upgrade logic..
157        //        upgradeVersion = [the DATABASE_VERSION you set]
158        //    }
159
160        if (upgradeVersion == 20) {
161            /*
162             * Version 21 is part of the volume control refresh. There is no
163             * longer a UI-visible for setting notification vibrate on/off (in
164             * our design), but the functionality still exists. Force the
165             * notification vibrate to on.
166             */
167            loadVibrateSetting(db, true);
168
169            upgradeVersion = 21;
170        }
171
172        if (upgradeVersion < 22) {
173            upgradeVersion = 22;
174            // Upgrade the lock gesture storage location and format
175            upgradeLockPatternLocation(db);
176        }
177
178        if (upgradeVersion < 23) {
179            db.execSQL("UPDATE favorites SET iconResource=0 WHERE iconType=0");
180            upgradeVersion = 23;
181        }
182
183        if (upgradeVersion == 23) {
184            db.beginTransaction();
185            try {
186                db.execSQL("ALTER TABLE favorites ADD spanX INTEGER");
187                db.execSQL("ALTER TABLE favorites ADD spanY INTEGER");
188                // Shortcuts, applications, folders
189                db.execSQL("UPDATE favorites SET spanX=1, spanY=1 WHERE itemType<=0");
190                // Photo frames, clocks
191                db.execSQL(
192                    "UPDATE favorites SET spanX=2, spanY=2 WHERE itemType=1000 or itemType=1002");
193                // Search boxes
194                db.execSQL("UPDATE favorites SET spanX=4, spanY=1 WHERE itemType=1001");
195                db.setTransactionSuccessful();
196            } finally {
197                db.endTransaction();
198            }
199            upgradeVersion = 24;
200        }
201
202        if (upgradeVersion == 24) {
203            db.beginTransaction();
204            try {
205                // The value of the constants for preferring wifi or preferring mobile have been
206                // swapped, so reload the default.
207                db.execSQL("DELETE FROM system WHERE name='network_preference'");
208                db.execSQL("INSERT INTO system ('name', 'value') values ('network_preference', '" +
209                        ConnectivityManager.DEFAULT_NETWORK_PREFERENCE + "')");
210                db.setTransactionSuccessful();
211            } finally {
212                db.endTransaction();
213            }
214            upgradeVersion = 25;
215        }
216
217        if (upgradeVersion == 25) {
218            db.beginTransaction();
219            try {
220                db.execSQL("ALTER TABLE favorites ADD uri TEXT");
221                db.execSQL("ALTER TABLE favorites ADD displayMode INTEGER");
222                db.setTransactionSuccessful();
223            } finally {
224                db.endTransaction();
225            }
226            upgradeVersion = 26;
227        }
228
229        if (upgradeVersion == 26) {
230            // This introduces the new secure settings table.
231            db.beginTransaction();
232            try {
233                createSecureTable(db);
234                db.setTransactionSuccessful();
235            } finally {
236                db.endTransaction();
237            }
238            upgradeVersion = 27;
239        }
240
241        if (upgradeVersion == 27) {
242            String[] settingsToMove = {
243                    Settings.Secure.ADB_ENABLED,
244                    Settings.Secure.ANDROID_ID,
245                    Settings.Secure.BLUETOOTH_ON,
246                    Settings.Secure.DATA_ROAMING,
247                    Settings.Secure.DEVICE_PROVISIONED,
248                    Settings.Secure.HTTP_PROXY,
249                    Settings.Secure.INSTALL_NON_MARKET_APPS,
250                    Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
251                    Settings.Secure.LOGGING_ID,
252                    Settings.Secure.NETWORK_PREFERENCE,
253                    Settings.Secure.PARENTAL_CONTROL_ENABLED,
254                    Settings.Secure.PARENTAL_CONTROL_LAST_UPDATE,
255                    Settings.Secure.PARENTAL_CONTROL_REDIRECT_URL,
256                    Settings.Secure.SETTINGS_CLASSNAME,
257                    Settings.Secure.USB_MASS_STORAGE_ENABLED,
258                    Settings.Secure.USE_GOOGLE_MAIL,
259                    Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
260                    Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
261                    Settings.Secure.WIFI_NUM_OPEN_NETWORKS_KEPT,
262                    Settings.Secure.WIFI_ON,
263                    Settings.Secure.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE,
264                    Settings.Secure.WIFI_WATCHDOG_AP_COUNT,
265                    Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS,
266                    Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED,
267                    Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS,
268                    Settings.Secure.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT,
269                    Settings.Secure.WIFI_WATCHDOG_MAX_AP_CHECKS,
270                    Settings.Secure.WIFI_WATCHDOG_ON,
271                    Settings.Secure.WIFI_WATCHDOG_PING_COUNT,
272                    Settings.Secure.WIFI_WATCHDOG_PING_DELAY_MS,
273                    Settings.Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS,
274                };
275            moveFromSystemToSecure(db, settingsToMove);
276            upgradeVersion = 28;
277        }
278
279        if (upgradeVersion == 28 || upgradeVersion == 29) {
280            // Note: The upgrade to 28 was flawed since it didn't delete the old
281            // setting first before inserting. Combining 28 and 29 with the
282            // fixed version.
283
284            // This upgrade adds the STREAM_NOTIFICATION type to the list of
285            // types affected by ringer modes (silent, vibrate, etc.)
286            db.beginTransaction();
287            try {
288                db.execSQL("DELETE FROM system WHERE name='"
289                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'");
290                int newValue = (1 << AudioManager.STREAM_RING)
291                        | (1 << AudioManager.STREAM_NOTIFICATION)
292                        | (1 << AudioManager.STREAM_SYSTEM);
293                db.execSQL("INSERT INTO system ('name', 'value') values ('"
294                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '"
295                        + String.valueOf(newValue) + "')");
296                db.setTransactionSuccessful();
297            } finally {
298                db.endTransaction();
299            }
300
301            upgradeVersion = 30;
302        }
303
304        if (upgradeVersion == 30) {
305            /*
306             * Upgrade 31 clears the title for all quick launch shortcuts so the
307             * activities' titles will be resolved at display time. Also, the
308             * folder is changed to '@quicklaunch'.
309             */
310            db.beginTransaction();
311            try {
312                db.execSQL("UPDATE bookmarks SET folder = '@quicklaunch'");
313                db.execSQL("UPDATE bookmarks SET title = ''");
314                db.setTransactionSuccessful();
315            } finally {
316                db.endTransaction();
317            }
318            upgradeVersion = 31;
319        }
320
321        if (upgradeVersion == 31) {
322            /*
323             * Animations are now managed in preferences, and may be
324             * enabled or disabled based on product resources.
325             */
326            db.beginTransaction();
327            SQLiteStatement stmt = null;
328            try {
329                db.execSQL("DELETE FROM system WHERE name='"
330                        + Settings.System.WINDOW_ANIMATION_SCALE + "'");
331                db.execSQL("DELETE FROM system WHERE name='"
332                        + Settings.System.TRANSITION_ANIMATION_SCALE + "'");
333                stmt = db.compileStatement("INSERT INTO system(name,value)"
334                        + " VALUES(?,?);");
335                loadDefaultAnimationSettings(stmt);
336                db.setTransactionSuccessful();
337            } finally {
338                db.endTransaction();
339                if (stmt != null) stmt.close();
340            }
341            upgradeVersion = 32;
342        }
343
344        if (upgradeVersion == 32) {
345            // The Wi-Fi watchdog SSID list is now seeded with the value of
346            // the property ro.com.android.wifi-watchlist
347            String wifiWatchList = SystemProperties.get("ro.com.android.wifi-watchlist");
348            if (!TextUtils.isEmpty(wifiWatchList)) {
349                db.beginTransaction();
350                try {
351                    db.execSQL("INSERT OR IGNORE INTO secure(name,value) values('" +
352                            Settings.Secure.WIFI_WATCHDOG_WATCH_LIST + "','" +
353                            wifiWatchList + "');");
354                    db.setTransactionSuccessful();
355                } finally {
356                    db.endTransaction();
357                }
358            }
359            upgradeVersion = 33;
360        }
361
362        if (upgradeVersion == 33) {
363            // Set the default zoom controls to: tap-twice to bring up +/-
364            db.beginTransaction();
365            try {
366                db.execSQL("INSERT INTO system(name,value) values('zoom','2');");
367                db.setTransactionSuccessful();
368            } finally {
369                db.endTransaction();
370            }
371            upgradeVersion = 34;
372        }
373
374        if (upgradeVersion == 34) {
375            db.beginTransaction();
376            SQLiteStatement stmt = null;
377            try {
378                stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
379                        + " VALUES(?,?);");
380                loadSecure35Settings(stmt);
381                db.setTransactionSuccessful();
382            } finally {
383                db.endTransaction();
384                if (stmt != null) stmt.close();
385            }
386            upgradeVersion = 35;
387        }
388            // due to a botched merge from donut to eclair, the initialization of ASSISTED_GPS_ENABLED
389            // was accidentally done out of order here.
390            // to fix this, ASSISTED_GPS_ENABLED is now initialized while upgrading from 38 to 39,
391            // and we intentionally do nothing from 35 to 36 now.
392        if (upgradeVersion == 35) {
393            upgradeVersion = 36;
394        }
395
396        if (upgradeVersion == 36) {
397           // This upgrade adds the STREAM_SYSTEM_ENFORCED type to the list of
398            // types affected by ringer modes (silent, vibrate, etc.)
399            db.beginTransaction();
400            try {
401                db.execSQL("DELETE FROM system WHERE name='"
402                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'");
403                int newValue = (1 << AudioManager.STREAM_RING)
404                        | (1 << AudioManager.STREAM_NOTIFICATION)
405                        | (1 << AudioManager.STREAM_SYSTEM)
406                        | (1 << AudioManager.STREAM_SYSTEM_ENFORCED);
407                db.execSQL("INSERT INTO system ('name', 'value') values ('"
408                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '"
409                        + String.valueOf(newValue) + "')");
410                db.setTransactionSuccessful();
411            } finally {
412                db.endTransaction();
413            }
414            upgradeVersion = 37;
415        }
416
417        if (upgradeVersion == 37) {
418            db.beginTransaction();
419            SQLiteStatement stmt = null;
420            try {
421                stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
422                        + " VALUES(?,?);");
423                loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
424                        R.string.airplane_mode_toggleable_radios);
425                db.setTransactionSuccessful();
426            } finally {
427                db.endTransaction();
428                if (stmt != null) stmt.close();
429            }
430            upgradeVersion = 38;
431        }
432
433        if (upgradeVersion == 38) {
434            db.beginTransaction();
435            try {
436                String value =
437                        mContext.getResources().getBoolean(R.bool.assisted_gps_enabled) ? "1" : "0";
438                db.execSQL("INSERT OR IGNORE INTO secure(name,value) values('" +
439                        Settings.Secure.ASSISTED_GPS_ENABLED + "','" + value + "');");
440                db.setTransactionSuccessful();
441            } finally {
442                db.endTransaction();
443            }
444
445            upgradeVersion = 39;
446        }
447
448        if (upgradeVersion == 39) {
449            upgradeAutoBrightness(db);
450            upgradeVersion = 40;
451        }
452
453        if (upgradeVersion == 40) {
454            /*
455             * All animations are now turned on by default!
456             */
457            db.beginTransaction();
458            SQLiteStatement stmt = null;
459            try {
460                db.execSQL("DELETE FROM system WHERE name='"
461                        + Settings.System.WINDOW_ANIMATION_SCALE + "'");
462                db.execSQL("DELETE FROM system WHERE name='"
463                        + Settings.System.TRANSITION_ANIMATION_SCALE + "'");
464                stmt = db.compileStatement("INSERT INTO system(name,value)"
465                        + " VALUES(?,?);");
466                loadDefaultAnimationSettings(stmt);
467                db.setTransactionSuccessful();
468            } finally {
469                db.endTransaction();
470                if (stmt != null) stmt.close();
471            }
472            upgradeVersion = 41;
473        }
474
475        if (upgradeVersion == 41) {
476            /*
477             * Initialize newly public haptic feedback setting
478             */
479            db.beginTransaction();
480            SQLiteStatement stmt = null;
481            try {
482                db.execSQL("DELETE FROM system WHERE name='"
483                        + Settings.System.HAPTIC_FEEDBACK_ENABLED + "'");
484                stmt = db.compileStatement("INSERT INTO system(name,value)"
485                        + " VALUES(?,?);");
486                loadDefaultHapticSettings(stmt);
487                db.setTransactionSuccessful();
488            } finally {
489                db.endTransaction();
490                if (stmt != null) stmt.close();
491            }
492            upgradeVersion = 42;
493        }
494
495        if (upgradeVersion == 42) {
496            /*
497             * Initialize new notification pulse setting
498             */
499            db.beginTransaction();
500            SQLiteStatement stmt = null;
501            try {
502                stmt = db.compileStatement("INSERT INTO system(name,value)"
503                        + " VALUES(?,?);");
504                loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
505                        R.bool.def_notification_pulse);
506                db.setTransactionSuccessful();
507            } finally {
508                db.endTransaction();
509                if (stmt != null) stmt.close();
510            }
511            upgradeVersion = 43;
512        }
513
514        if (upgradeVersion == 43) {
515            /*
516             * This upgrade stores bluetooth volume separately from voice volume
517             */
518            db.beginTransaction();
519            SQLiteStatement stmt = null;
520            try {
521                stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
522                        + " VALUES(?,?);");
523                loadSetting(stmt, Settings.System.VOLUME_BLUETOOTH_SCO,
524                        AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_BLUETOOTH_SCO]);
525                db.setTransactionSuccessful();
526            } finally {
527                db.endTransaction();
528                if (stmt != null) stmt.close();
529            }
530            upgradeVersion = 44;
531        }
532
533        if (upgradeVersion == 44) {
534            /*
535             * Gservices was moved into vendor/google.
536             */
537            db.execSQL("DROP TABLE IF EXISTS gservices");
538            db.execSQL("DROP INDEX IF EXISTS gservicesIndex1");
539            upgradeVersion = 45;
540        }
541
542        if (upgradeVersion == 45) {
543             /*
544              * New settings for MountService
545              */
546            db.beginTransaction();
547            try {
548                db.execSQL("INSERT INTO secure(name,value) values('" +
549                        Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND + "','1');");
550                db.execSQL("INSERT INTO secure(name,value) values('" +
551                        Settings.Secure.MOUNT_UMS_AUTOSTART + "','0');");
552                db.execSQL("INSERT INTO secure(name,value) values('" +
553                        Settings.Secure.MOUNT_UMS_PROMPT + "','1');");
554                db.execSQL("INSERT INTO secure(name,value) values('" +
555                        Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED + "','1');");
556                db.setTransactionSuccessful();
557            } finally {
558                db.endTransaction();
559            }
560            upgradeVersion = 46;
561        }
562
563        if (upgradeVersion == 46) {
564            /*
565             * The password mode constants have changed; reset back to no
566             * password.
567             */
568            db.beginTransaction();
569            try {
570                db.execSQL("DELETE FROM system WHERE name='lockscreen.password_type';");
571                db.setTransactionSuccessful();
572            } finally {
573                db.endTransaction();
574            }
575           upgradeVersion = 47;
576       }
577
578
579        if (upgradeVersion == 47) {
580            /*
581             * The password mode constants have changed again; reset back to no
582             * password.
583             */
584            db.beginTransaction();
585            try {
586                db.execSQL("DELETE FROM system WHERE name='lockscreen.password_type';");
587                db.setTransactionSuccessful();
588            } finally {
589                db.endTransaction();
590            }
591           upgradeVersion = 48;
592       }
593
594       if (upgradeVersion == 48) {
595           /*
596            * Default recognition service no longer initialized here,
597            * moved to RecognitionManagerService.
598            */
599           upgradeVersion = 49;
600       }
601
602       if (upgradeVersion == 49) {
603           /*
604            * New settings for new user interface noises.
605            */
606           db.beginTransaction();
607           SQLiteStatement stmt = null;
608           try {
609                stmt = db.compileStatement("INSERT INTO system(name,value)"
610                        + " VALUES(?,?);");
611                loadUISoundEffectsSettings(stmt);
612                db.setTransactionSuccessful();
613            } finally {
614                db.endTransaction();
615                if (stmt != null) stmt.close();
616            }
617
618           upgradeVersion = 50;
619       }
620
621       if (upgradeVersion == 50) {
622           /*
623            * Install location no longer initiated here.
624            */
625           upgradeVersion = 51;
626       }
627
628       if (upgradeVersion == 51) {
629           /* Move the lockscreen related settings to Secure, including some private ones. */
630           String[] settingsToMove = {
631                   Secure.LOCK_PATTERN_ENABLED,
632                   Secure.LOCK_PATTERN_VISIBLE,
633                   Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED,
634                   "lockscreen.password_type",
635                   "lockscreen.lockoutattemptdeadline",
636                   "lockscreen.patterneverchosen",
637                   "lock_pattern_autolock",
638                   "lockscreen.lockedoutpermanently",
639                   "lockscreen.password_salt"
640           };
641           moveFromSystemToSecure(db, settingsToMove);
642           upgradeVersion = 52;
643       }
644
645        if (upgradeVersion == 52) {
646            // new vibration/silent mode settings
647            db.beginTransaction();
648            SQLiteStatement stmt = null;
649            try {
650                stmt = db.compileStatement("INSERT INTO system(name,value)"
651                        + " VALUES(?,?);");
652                loadBooleanSetting(stmt, Settings.System.VIBRATE_IN_SILENT,
653                        R.bool.def_vibrate_in_silent);
654                db.setTransactionSuccessful();
655            } finally {
656                db.endTransaction();
657                if (stmt != null) stmt.close();
658            }
659
660            upgradeVersion = 53;
661        }
662
663        if (upgradeVersion == 53) {
664            /*
665             * New settings for set install location UI no longer initiated here.
666             */
667            upgradeVersion = 54;
668        }
669
670        if (upgradeVersion == 54) {
671            /*
672             * Update the screen timeout value if set to never
673             */
674            db.beginTransaction();
675            try {
676                upgradeScreenTimeoutFromNever(db);
677                db.setTransactionSuccessful();
678            } finally {
679                db.endTransaction();
680            }
681
682            upgradeVersion = 55;
683        }
684
685        if (upgradeVersion == 55) {
686            /* Move the install location settings. */
687            String[] settingsToMove = {
688                    Secure.SET_INSTALL_LOCATION,
689                    Secure.DEFAULT_INSTALL_LOCATION
690            };
691            moveFromSystemToSecure(db, settingsToMove);
692            db.beginTransaction();
693            SQLiteStatement stmt = null;
694            try {
695                stmt = db.compileStatement("INSERT INTO system(name,value)"
696                        + " VALUES(?,?);");
697                loadSetting(stmt, Secure.SET_INSTALL_LOCATION, 0);
698                loadSetting(stmt, Secure.DEFAULT_INSTALL_LOCATION,
699                        PackageHelper.APP_INSTALL_AUTO);
700                db.setTransactionSuccessful();
701             } finally {
702                 db.endTransaction();
703                 if (stmt != null) stmt.close();
704             }
705            upgradeVersion = 56;
706        }
707
708        if (upgradeVersion == 56) {
709            /*
710             * Add Bluetooth to list of toggleable radios in airplane mode
711             */
712            db.beginTransaction();
713            SQLiteStatement stmt = null;
714            try {
715                db.execSQL("DELETE FROM system WHERE name='"
716                        + Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS + "'");
717                stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
718                        + " VALUES(?,?);");
719                loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
720                        R.string.airplane_mode_toggleable_radios);
721                db.setTransactionSuccessful();
722            } finally {
723                db.endTransaction();
724                if (stmt != null) stmt.close();
725            }
726            upgradeVersion = 57;
727        }
728
729        /************* The following are Honeycomb changes ************/
730
731        if (upgradeVersion == 57) {
732            /*
733             * New settings to:
734             *  1. Enable injection of accessibility scripts in WebViews.
735             *  2. Define the key bindings for traversing web content in WebViews.
736             */
737            db.beginTransaction();
738            SQLiteStatement stmt = null;
739            try {
740                stmt = db.compileStatement("INSERT INTO secure(name,value)"
741                        + " VALUES(?,?);");
742                loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION,
743                        R.bool.def_accessibility_script_injection);
744                stmt.close();
745                stmt = db.compileStatement("INSERT INTO secure(name,value)"
746                        + " VALUES(?,?);");
747                loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS,
748                        R.string.def_accessibility_web_content_key_bindings);
749                db.setTransactionSuccessful();
750            } finally {
751                db.endTransaction();
752                if (stmt != null) stmt.close();
753            }
754            upgradeVersion = 58;
755        }
756
757        if (upgradeVersion == 58) {
758            /* Add default for new Auto Time Zone */
759            int autoTimeValue = getIntValueFromSystem(db, Settings.System.AUTO_TIME, 0);
760            db.beginTransaction();
761            SQLiteStatement stmt = null;
762            try {
763                stmt = db.compileStatement("INSERT INTO system(name,value)" + " VALUES(?,?);");
764                loadSetting(stmt, Settings.System.AUTO_TIME_ZONE,
765                        autoTimeValue); // Sync timezone to NITZ if auto_time was enabled
766                db.setTransactionSuccessful();
767            } finally {
768                db.endTransaction();
769                if (stmt != null) stmt.close();
770            }
771            upgradeVersion = 59;
772        }
773
774        if (upgradeVersion == 59) {
775            // Persistence for the rotation lock feature.
776            db.beginTransaction();
777            SQLiteStatement stmt = null;
778            try {
779                stmt = db.compileStatement("INSERT INTO system(name,value)"
780                        + " VALUES(?,?);");
781                loadBooleanSetting(stmt, Settings.System.USER_ROTATION,
782                        R.integer.def_user_rotation); // should be zero degrees
783                db.setTransactionSuccessful();
784            } finally {
785                db.endTransaction();
786                if (stmt != null) stmt.close();
787            }
788            upgradeVersion = 60;
789        }
790
791        if (upgradeVersion == 60) {
792            // Don't do this for upgrades from Gingerbread
793            // Were only required for intra-Honeycomb upgrades for testing
794            // upgradeScreenTimeout(db);
795            upgradeVersion = 61;
796        }
797
798        if (upgradeVersion == 61) {
799            // Don't do this for upgrades from Gingerbread
800            // Were only required for intra-Honeycomb upgrades for testing
801            // upgradeScreenTimeout(db);
802            upgradeVersion = 62;
803        }
804
805        // Change the default for screen auto-brightness mode
806        if (upgradeVersion == 62) {
807            // Don't do this for upgrades from Gingerbread
808            // Were only required for intra-Honeycomb upgrades for testing
809            // upgradeAutoBrightness(db);
810            upgradeVersion = 63;
811        }
812
813        if (upgradeVersion == 63) {
814            // This upgrade adds the STREAM_MUSIC type to the list of
815             // types affected by ringer modes (silent, vibrate, etc.)
816             db.beginTransaction();
817             try {
818                 db.execSQL("DELETE FROM system WHERE name='"
819                         + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'");
820                 int newValue = (1 << AudioManager.STREAM_RING)
821                         | (1 << AudioManager.STREAM_NOTIFICATION)
822                         | (1 << AudioManager.STREAM_SYSTEM)
823                         | (1 << AudioManager.STREAM_SYSTEM_ENFORCED)
824                         | (1 << AudioManager.STREAM_MUSIC);
825                 db.execSQL("INSERT INTO system ('name', 'value') values ('"
826                         + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '"
827                         + String.valueOf(newValue) + "')");
828                 db.setTransactionSuccessful();
829             } finally {
830                 db.endTransaction();
831             }
832             upgradeVersion = 64;
833         }
834
835        if (upgradeVersion == 64) {
836            // New setting to configure the long press timeout.
837            db.beginTransaction();
838            SQLiteStatement stmt = null;
839            try {
840                stmt = db.compileStatement("INSERT INTO secure(name,value)"
841                        + " VALUES(?,?);");
842                loadIntegerSetting(stmt, Settings.Secure.LONG_PRESS_TIMEOUT,
843                        R.integer.def_long_press_timeout_millis);
844                stmt.close();
845                db.setTransactionSuccessful();
846            } finally {
847                db.endTransaction();
848                if (stmt != null) stmt.close();
849            }
850            upgradeVersion = 65;
851        }
852
853        /************* The following are Ice Cream Sandwich changes ************/
854
855        if (upgradeVersion == 65) {
856            /*
857             * Animations are removed from Settings. Turned on by default
858             */
859            db.beginTransaction();
860            SQLiteStatement stmt = null;
861            try {
862                db.execSQL("DELETE FROM system WHERE name='"
863                        + Settings.System.WINDOW_ANIMATION_SCALE + "'");
864                db.execSQL("DELETE FROM system WHERE name='"
865                        + Settings.System.TRANSITION_ANIMATION_SCALE + "'");
866                stmt = db.compileStatement("INSERT INTO system(name,value)"
867                        + " VALUES(?,?);");
868                loadDefaultAnimationSettings(stmt);
869                db.setTransactionSuccessful();
870            } finally {
871                db.endTransaction();
872                if (stmt != null) stmt.close();
873            }
874            upgradeVersion = 66;
875        }
876
877        if (upgradeVersion == 66) {
878            // This upgrade makes sure that MODE_RINGER_STREAMS_AFFECTED is set
879            // according to device voice capability
880            db.beginTransaction();
881            try {
882                int ringerModeAffectedStreams = (1 << AudioManager.STREAM_RING) |
883                                                (1 << AudioManager.STREAM_NOTIFICATION) |
884                                                (1 << AudioManager.STREAM_SYSTEM) |
885                                                (1 << AudioManager.STREAM_SYSTEM_ENFORCED);
886                if (!mContext.getResources().getBoolean(
887                        com.android.internal.R.bool.config_voice_capable)) {
888                    ringerModeAffectedStreams |= (1 << AudioManager.STREAM_MUSIC);
889                }
890                db.execSQL("DELETE FROM system WHERE name='"
891                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'");
892                db.execSQL("INSERT INTO system ('name', 'value') values ('"
893                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '"
894                        + String.valueOf(ringerModeAffectedStreams) + "')");
895                db.setTransactionSuccessful();
896            } finally {
897                db.endTransaction();
898            }
899            upgradeVersion = 67;
900        }
901
902        if (upgradeVersion == 67) {
903            // New setting to enable touch exploration.
904            db.beginTransaction();
905            SQLiteStatement stmt = null;
906            try {
907                stmt = db.compileStatement("INSERT INTO secure(name,value)"
908                        + " VALUES(?,?);");
909                loadBooleanSetting(stmt, Settings.Secure.TOUCH_EXPLORATION_ENABLED,
910                        R.bool.def_touch_exploration_enabled);
911                stmt.close();
912                db.setTransactionSuccessful();
913            } finally {
914                db.endTransaction();
915                if (stmt != null) stmt.close();
916            }
917            upgradeVersion = 68;
918        }
919
920        if (upgradeVersion == 68) {
921            // Enable all system sounds by default
922            db.beginTransaction();
923            try {
924                db.execSQL("DELETE FROM system WHERE name='"
925                        + Settings.System.NOTIFICATIONS_USE_RING_VOLUME + "'");
926                db.setTransactionSuccessful();
927            } finally {
928                db.endTransaction();
929            }
930            upgradeVersion = 69;
931        }
932
933        if (upgradeVersion == 69) {
934            // Add RADIO_NFC to AIRPLANE_MODE_RADIO and AIRPLANE_MODE_TOGGLEABLE_RADIOS
935            String airplaneRadios = mContext.getResources().getString(
936                    R.string.def_airplane_mode_radios);
937            String toggleableRadios = mContext.getResources().getString(
938                    R.string.airplane_mode_toggleable_radios);
939            db.beginTransaction();
940            try {
941                db.execSQL("UPDATE system SET value='" + airplaneRadios + "' " +
942                        "WHERE name='" + Settings.System.AIRPLANE_MODE_RADIOS + "'");
943                db.execSQL("UPDATE system SET value='" + toggleableRadios + "' " +
944                        "WHERE name='" + Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS + "'");
945                db.setTransactionSuccessful();
946            } finally {
947                db.endTransaction();
948            }
949            upgradeVersion = 70;
950        }
951
952        if (upgradeVersion == 70) {
953            // Update all built-in bookmarks.  Some of the package names have changed.
954            loadBookmarks(db);
955            upgradeVersion = 71;
956        }
957
958        if (upgradeVersion == 71) {
959             // New setting to specify whether to speak passwords in accessibility mode.
960            db.beginTransaction();
961            SQLiteStatement stmt = null;
962            try {
963                stmt = db.compileStatement("INSERT INTO secure(name,value)"
964                        + " VALUES(?,?);");
965                loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD,
966                        R.bool.def_accessibility_speak_password);
967                db.setTransactionSuccessful();
968            } finally {
969                db.endTransaction();
970                if (stmt != null) stmt.close();
971            }
972            upgradeVersion = 72;
973        }
974
975        if (upgradeVersion == 72) {
976            // update vibration settings
977            db.beginTransaction();
978            SQLiteStatement stmt = null;
979            try {
980                stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)"
981                        + " VALUES(?,?);");
982                loadBooleanSetting(stmt, Settings.System.VIBRATE_IN_SILENT,
983                        R.bool.def_vibrate_in_silent);
984                db.setTransactionSuccessful();
985            } finally {
986                db.endTransaction();
987                if (stmt != null) stmt.close();
988            }
989            upgradeVersion = 73;
990        }
991
992        if (upgradeVersion == 73) {
993            upgradeVibrateSettingFromNone(db);
994            upgradeVersion = 74;
995        }
996
997        if (upgradeVersion == 74) {
998            // URL from which WebView loads a JavaScript based screen-reader.
999            db.beginTransaction();
1000            SQLiteStatement stmt = null;
1001            try {
1002                stmt = db.compileStatement("INSERT INTO secure(name,value) VALUES(?,?);");
1003                loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_SCREEN_READER_URL,
1004                        R.string.def_accessibility_screen_reader_url);
1005                db.setTransactionSuccessful();
1006            } finally {
1007                db.endTransaction();
1008                if (stmt != null) stmt.close();
1009            }
1010            upgradeVersion = 75;
1011        }
1012        if (upgradeVersion == 75) {
1013            db.beginTransaction();
1014            SQLiteStatement stmt = null;
1015            Cursor c = null;
1016            try {
1017                c = db.query("secure", new String[] {"_id", "value"},
1018                        "name='lockscreen.disabled'",
1019                        null, null, null, null);
1020                // only set default if it has not yet been set
1021                if (c == null || c.getCount() == 0) {
1022                    stmt = db.compileStatement("INSERT INTO system(name,value)"
1023                            + " VALUES(?,?);");
1024                    loadBooleanSetting(stmt, Settings.System.LOCKSCREEN_DISABLED,
1025                            R.bool.def_lockscreen_disabled);
1026                }
1027                db.setTransactionSuccessful();
1028            } finally {
1029                db.endTransaction();
1030                if (c != null) c.close();
1031                if (stmt != null) stmt.close();
1032            }
1033            upgradeVersion = 76;
1034        }
1035
1036        /************* The following are Jelly Bean changes ************/
1037
1038        if (upgradeVersion == 76) {
1039            // Removed VIBRATE_IN_SILENT setting
1040            db.beginTransaction();
1041            try {
1042                db.execSQL("DELETE FROM system WHERE name='"
1043                                + Settings.System.VIBRATE_IN_SILENT + "'");
1044                db.setTransactionSuccessful();
1045            } finally {
1046                db.endTransaction();
1047            }
1048
1049            upgradeVersion = 77;
1050        }
1051
1052        if (upgradeVersion == 77) {
1053            // Introduce "vibrate when ringing" setting
1054            loadVibrateWhenRingingSetting(db);
1055
1056            upgradeVersion = 78;
1057        }
1058
1059        if (upgradeVersion == 78) {
1060            // The JavaScript based screen-reader URL changes in JellyBean.
1061            db.beginTransaction();
1062            SQLiteStatement stmt = null;
1063            try {
1064                stmt = db.compileStatement("INSERT OR REPLACE INTO secure(name,value)"
1065                        + " VALUES(?,?);");
1066                loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_SCREEN_READER_URL,
1067                        R.string.def_accessibility_screen_reader_url);
1068                db.setTransactionSuccessful();
1069            } finally {
1070                db.endTransaction();
1071                if (stmt != null) stmt.close();
1072            }
1073            upgradeVersion = 79;
1074        }
1075
1076        // vvv Jelly Bean MR1 changes begin here vvv
1077
1078        if (upgradeVersion == 79) {
1079            // update screensaver settings
1080            db.beginTransaction();
1081            SQLiteStatement stmt = null;
1082            try {
1083                stmt = db.compileStatement("INSERT OR REPLACE INTO secure(name,value)"
1084                        + " VALUES(?,?);");
1085                loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ENABLED,
1086                        R.bool.def_screensaver_enabled);
1087                loadBooleanSetting(stmt, Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
1088                        R.bool.def_screensaver_activate_on_dock);
1089                loadStringSetting(stmt, Settings.Secure.SCREENSAVER_COMPONENT,
1090                        R.string.def_screensaver_component);
1091                db.setTransactionSuccessful();
1092            } finally {
1093                db.endTransaction();
1094                if (stmt != null) stmt.close();
1095            }
1096            upgradeVersion = 80;
1097        }
1098
1099
1100        // *** Remember to update DATABASE_VERSION above!
1101
1102        if (upgradeVersion != currentVersion) {
1103            Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion
1104                    + ", must wipe the settings provider");
1105            db.execSQL("DROP TABLE IF EXISTS system");
1106            db.execSQL("DROP INDEX IF EXISTS systemIndex1");
1107            db.execSQL("DROP TABLE IF EXISTS secure");
1108            db.execSQL("DROP INDEX IF EXISTS secureIndex1");
1109            db.execSQL("DROP TABLE IF EXISTS gservices");
1110            db.execSQL("DROP INDEX IF EXISTS gservicesIndex1");
1111            db.execSQL("DROP TABLE IF EXISTS bluetooth_devices");
1112            db.execSQL("DROP TABLE IF EXISTS bookmarks");
1113            db.execSQL("DROP INDEX IF EXISTS bookmarksIndex1");
1114            db.execSQL("DROP INDEX IF EXISTS bookmarksIndex2");
1115            db.execSQL("DROP TABLE IF EXISTS favorites");
1116            onCreate(db);
1117
1118            // Added for diagnosing settings.db wipes after the fact
1119            String wipeReason = oldVersion + "/" + upgradeVersion + "/" + currentVersion;
1120            db.execSQL("INSERT INTO secure(name,value) values('" +
1121                    "wiped_db_reason" + "','" + wipeReason + "');");
1122        }
1123    }
1124
1125    private void moveFromSystemToSecure(SQLiteDatabase db, String [] settingsToMove) {
1126        // Copy settings values from 'system' to 'secure' and delete them from 'system'
1127        SQLiteStatement insertStmt = null;
1128        SQLiteStatement deleteStmt = null;
1129
1130        db.beginTransaction();
1131        try {
1132            insertStmt =
1133                db.compileStatement("INSERT INTO secure (name,value) SELECT name,value FROM "
1134                    + "system WHERE name=?");
1135            deleteStmt = db.compileStatement("DELETE FROM system WHERE name=?");
1136
1137
1138            for (String setting : settingsToMove) {
1139                insertStmt.bindString(1, setting);
1140                insertStmt.execute();
1141
1142                deleteStmt.bindString(1, setting);
1143                deleteStmt.execute();
1144            }
1145            db.setTransactionSuccessful();
1146        } finally {
1147            db.endTransaction();
1148            if (insertStmt != null) {
1149                insertStmt.close();
1150            }
1151            if (deleteStmt != null) {
1152                deleteStmt.close();
1153            }
1154        }
1155    }
1156
1157    private void upgradeLockPatternLocation(SQLiteDatabase db) {
1158        Cursor c = db.query("system", new String[] {"_id", "value"}, "name='lock_pattern'",
1159                null, null, null, null);
1160        if (c.getCount() > 0) {
1161            c.moveToFirst();
1162            String lockPattern = c.getString(1);
1163            if (!TextUtils.isEmpty(lockPattern)) {
1164                // Convert lock pattern
1165                try {
1166                    LockPatternUtils lpu = new LockPatternUtils(mContext);
1167                    List<LockPatternView.Cell> cellPattern =
1168                            LockPatternUtils.stringToPattern(lockPattern);
1169                    lpu.saveLockPattern(cellPattern);
1170                } catch (IllegalArgumentException e) {
1171                    // Don't want corrupted lock pattern to hang the reboot process
1172                }
1173            }
1174            c.close();
1175            db.delete("system", "name='lock_pattern'", null);
1176        } else {
1177            c.close();
1178        }
1179    }
1180
1181    private void upgradeScreenTimeoutFromNever(SQLiteDatabase db) {
1182        // See if the timeout is -1 (for "Never").
1183        Cursor c = db.query("system", new String[] { "_id", "value" }, "name=? AND value=?",
1184                new String[] { Settings.System.SCREEN_OFF_TIMEOUT, "-1" },
1185                null, null, null);
1186
1187        SQLiteStatement stmt = null;
1188        if (c.getCount() > 0) {
1189            c.close();
1190            try {
1191                stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)"
1192                        + " VALUES(?,?);");
1193
1194                // Set the timeout to 30 minutes in milliseconds
1195                loadSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
1196                        Integer.toString(30 * 60 * 1000));
1197            } finally {
1198                if (stmt != null) stmt.close();
1199            }
1200        } else {
1201            c.close();
1202        }
1203    }
1204
1205    private void upgradeVibrateSettingFromNone(SQLiteDatabase db) {
1206        int vibrateSetting = getIntValueFromSystem(db, Settings.System.VIBRATE_ON, 0);
1207        // If the ringer vibrate value is invalid, set it to the default
1208        if ((vibrateSetting & 3) == AudioManager.VIBRATE_SETTING_OFF) {
1209            vibrateSetting = AudioService.getValueForVibrateSetting(0,
1210                    AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_ONLY_SILENT);
1211        }
1212        // Apply the same setting to the notification vibrate value
1213        vibrateSetting = AudioService.getValueForVibrateSetting(vibrateSetting,
1214                AudioManager.VIBRATE_TYPE_NOTIFICATION, vibrateSetting);
1215
1216        SQLiteStatement stmt = null;
1217        try {
1218            stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)"
1219                    + " VALUES(?,?);");
1220            loadSetting(stmt, Settings.System.VIBRATE_ON, vibrateSetting);
1221        } finally {
1222            if (stmt != null)
1223                stmt.close();
1224        }
1225    }
1226
1227    private void upgradeScreenTimeout(SQLiteDatabase db) {
1228        // Change screen timeout to current default
1229        db.beginTransaction();
1230        SQLiteStatement stmt = null;
1231        try {
1232            stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)"
1233                    + " VALUES(?,?);");
1234            loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
1235                    R.integer.def_screen_off_timeout);
1236            db.setTransactionSuccessful();
1237        } finally {
1238            db.endTransaction();
1239            if (stmt != null)
1240                stmt.close();
1241        }
1242    }
1243
1244    private void upgradeAutoBrightness(SQLiteDatabase db) {
1245        db.beginTransaction();
1246        try {
1247            String value =
1248                    mContext.getResources().getBoolean(
1249                    R.bool.def_screen_brightness_automatic_mode) ? "1" : "0";
1250            db.execSQL("INSERT OR REPLACE INTO system(name,value) values('" +
1251                    Settings.System.SCREEN_BRIGHTNESS_MODE + "','" + value + "');");
1252            db.setTransactionSuccessful();
1253        } finally {
1254            db.endTransaction();
1255        }
1256    }
1257
1258    /**
1259     * Loads the default set of bookmarked shortcuts from an xml file.
1260     *
1261     * @param db The database to write the values into
1262     */
1263    private void loadBookmarks(SQLiteDatabase db) {
1264        ContentValues values = new ContentValues();
1265
1266        PackageManager packageManager = mContext.getPackageManager();
1267        try {
1268            XmlResourceParser parser = mContext.getResources().getXml(R.xml.bookmarks);
1269            XmlUtils.beginDocument(parser, "bookmarks");
1270
1271            final int depth = parser.getDepth();
1272            int type;
1273
1274            while (((type = parser.next()) != XmlPullParser.END_TAG ||
1275                    parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
1276
1277                if (type != XmlPullParser.START_TAG) {
1278                    continue;
1279                }
1280
1281                String name = parser.getName();
1282                if (!"bookmark".equals(name)) {
1283                    break;
1284                }
1285
1286                String pkg = parser.getAttributeValue(null, "package");
1287                String cls = parser.getAttributeValue(null, "class");
1288                String shortcutStr = parser.getAttributeValue(null, "shortcut");
1289                String category = parser.getAttributeValue(null, "category");
1290
1291                int shortcutValue = shortcutStr.charAt(0);
1292                if (TextUtils.isEmpty(shortcutStr)) {
1293                    Log.w(TAG, "Unable to get shortcut for: " + pkg + "/" + cls);
1294                    continue;
1295                }
1296
1297                final Intent intent;
1298                final String title;
1299                if (pkg != null && cls != null) {
1300                    ActivityInfo info = null;
1301                    ComponentName cn = new ComponentName(pkg, cls);
1302                    try {
1303                        info = packageManager.getActivityInfo(cn, 0);
1304                    } catch (PackageManager.NameNotFoundException e) {
1305                        String[] packages = packageManager.canonicalToCurrentPackageNames(
1306                                new String[] { pkg });
1307                        cn = new ComponentName(packages[0], cls);
1308                        try {
1309                            info = packageManager.getActivityInfo(cn, 0);
1310                        } catch (PackageManager.NameNotFoundException e1) {
1311                            Log.w(TAG, "Unable to add bookmark: " + pkg + "/" + cls, e);
1312                            continue;
1313                        }
1314                    }
1315
1316                    intent = new Intent(Intent.ACTION_MAIN, null);
1317                    intent.addCategory(Intent.CATEGORY_LAUNCHER);
1318                    intent.setComponent(cn);
1319                    title = info.loadLabel(packageManager).toString();
1320                } else if (category != null) {
1321                    intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
1322                    title = "";
1323                } else {
1324                    Log.w(TAG, "Unable to add bookmark for shortcut " + shortcutStr
1325                            + ": missing package/class or category attributes");
1326                    continue;
1327                }
1328
1329                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1330                values.put(Settings.Bookmarks.INTENT, intent.toUri(0));
1331                values.put(Settings.Bookmarks.TITLE, title);
1332                values.put(Settings.Bookmarks.SHORTCUT, shortcutValue);
1333                db.delete("bookmarks", "shortcut = ?",
1334                        new String[] { Integer.toString(shortcutValue) });
1335                db.insert("bookmarks", null, values);
1336            }
1337        } catch (XmlPullParserException e) {
1338            Log.w(TAG, "Got execption parsing bookmarks.", e);
1339        } catch (IOException e) {
1340            Log.w(TAG, "Got execption parsing bookmarks.", e);
1341        }
1342    }
1343
1344    /**
1345     * Loads the default volume levels. It is actually inserting the index of
1346     * the volume array for each of the volume controls.
1347     *
1348     * @param db the database to insert the volume levels into
1349     */
1350    private void loadVolumeLevels(SQLiteDatabase db) {
1351        SQLiteStatement stmt = null;
1352        try {
1353            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
1354                    + " VALUES(?,?);");
1355
1356            loadSetting(stmt, Settings.System.VOLUME_MUSIC,
1357                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_MUSIC]);
1358            loadSetting(stmt, Settings.System.VOLUME_RING,
1359                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_RING]);
1360            loadSetting(stmt, Settings.System.VOLUME_SYSTEM,
1361                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_SYSTEM]);
1362            loadSetting(
1363                    stmt,
1364                    Settings.System.VOLUME_VOICE,
1365                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_VOICE_CALL]);
1366            loadSetting(stmt, Settings.System.VOLUME_ALARM,
1367                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_ALARM]);
1368            loadSetting(
1369                    stmt,
1370                    Settings.System.VOLUME_NOTIFICATION,
1371                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_NOTIFICATION]);
1372            loadSetting(
1373                    stmt,
1374                    Settings.System.VOLUME_BLUETOOTH_SCO,
1375                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_BLUETOOTH_SCO]);
1376
1377            loadSetting(stmt, Settings.System.MODE_RINGER,
1378                    AudioManager.RINGER_MODE_NORMAL);
1379
1380            // By default:
1381            // - ringtones, notification, system and music streams are affected by ringer mode
1382            // on non voice capable devices (tablets)
1383            // - ringtones, notification and system streams are affected by ringer mode
1384            // on voice capable devices (phones)
1385            int ringerModeAffectedStreams = (1 << AudioManager.STREAM_RING) |
1386                                            (1 << AudioManager.STREAM_NOTIFICATION) |
1387                                            (1 << AudioManager.STREAM_SYSTEM) |
1388                                            (1 << AudioManager.STREAM_SYSTEM_ENFORCED);
1389            if (!mContext.getResources().getBoolean(
1390                    com.android.internal.R.bool.config_voice_capable)) {
1391                ringerModeAffectedStreams |= (1 << AudioManager.STREAM_MUSIC);
1392            }
1393            loadSetting(stmt, Settings.System.MODE_RINGER_STREAMS_AFFECTED,
1394                    ringerModeAffectedStreams);
1395
1396            loadSetting(stmt, Settings.System.MUTE_STREAMS_AFFECTED,
1397                    ((1 << AudioManager.STREAM_MUSIC) |
1398                     (1 << AudioManager.STREAM_RING) |
1399                     (1 << AudioManager.STREAM_NOTIFICATION) |
1400                     (1 << AudioManager.STREAM_SYSTEM)));
1401        } finally {
1402            if (stmt != null) stmt.close();
1403        }
1404
1405        loadVibrateWhenRingingSetting(db);
1406    }
1407
1408    private void loadVibrateSetting(SQLiteDatabase db, boolean deleteOld) {
1409        if (deleteOld) {
1410            db.execSQL("DELETE FROM system WHERE name='" + Settings.System.VIBRATE_ON + "'");
1411        }
1412
1413        SQLiteStatement stmt = null;
1414        try {
1415            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
1416                    + " VALUES(?,?);");
1417
1418            // Vibrate on by default for ringer, on for notification
1419            int vibrate = 0;
1420            vibrate = AudioService.getValueForVibrateSetting(vibrate,
1421                    AudioManager.VIBRATE_TYPE_NOTIFICATION,
1422                    AudioManager.VIBRATE_SETTING_ONLY_SILENT);
1423            vibrate |= AudioService.getValueForVibrateSetting(vibrate,
1424                    AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_ONLY_SILENT);
1425            loadSetting(stmt, Settings.System.VIBRATE_ON, vibrate);
1426        } finally {
1427            if (stmt != null) stmt.close();
1428        }
1429    }
1430
1431    private void loadVibrateWhenRingingSetting(SQLiteDatabase db) {
1432        // The default should be off. VIBRATE_SETTING_ONLY_SILENT should also be ignored here.
1433        // Phone app should separately check whether AudioManager#getRingerMode() returns
1434        // RINGER_MODE_VIBRATE, with which the device should vibrate anyway.
1435        int vibrateSetting = getIntValueFromSystem(db, Settings.System.VIBRATE_ON,
1436                AudioManager.VIBRATE_SETTING_OFF);
1437        boolean vibrateWhenRinging = ((vibrateSetting & 3) == AudioManager.VIBRATE_SETTING_ON);
1438
1439        SQLiteStatement stmt = null;
1440        try {
1441            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
1442                    + " VALUES(?,?);");
1443            loadSetting(stmt, Settings.System.VIBRATE_WHEN_RINGING, vibrateWhenRinging ? 1 : 0);
1444        } finally {
1445            if (stmt != null) stmt.close();
1446        }
1447    }
1448
1449    private void loadSettings(SQLiteDatabase db) {
1450        loadSystemSettings(db);
1451        loadSecureSettings(db);
1452    }
1453
1454    private void loadSystemSettings(SQLiteDatabase db) {
1455        SQLiteStatement stmt = null;
1456        try {
1457            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
1458                    + " VALUES(?,?);");
1459
1460            loadBooleanSetting(stmt, Settings.System.DIM_SCREEN,
1461                    R.bool.def_dim_screen);
1462            loadSetting(stmt, Settings.System.STAY_ON_WHILE_PLUGGED_IN,
1463                    ("1".equals(SystemProperties.get("ro.kernel.qemu")) ||
1464                        mContext.getResources().getBoolean(R.bool.def_stay_on_while_plugged_in))
1465                     ? 1 : 0);
1466            loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
1467                    R.integer.def_screen_off_timeout);
1468
1469            // Set default cdma emergency tone
1470            loadSetting(stmt, Settings.System.EMERGENCY_TONE, 0);
1471
1472            // Set default cdma call auto retry
1473            loadSetting(stmt, Settings.System.CALL_AUTO_RETRY, 0);
1474
1475            // Set default cdma DTMF type
1476            loadSetting(stmt, Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, 0);
1477
1478            // Set default hearing aid
1479            loadSetting(stmt, Settings.System.HEARING_AID, 0);
1480
1481            // Set default tty mode
1482            loadSetting(stmt, Settings.System.TTY_MODE, 0);
1483
1484            loadBooleanSetting(stmt, Settings.System.AIRPLANE_MODE_ON,
1485                    R.bool.def_airplane_mode_on);
1486
1487            loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_RADIOS,
1488                    R.string.def_airplane_mode_radios);
1489
1490            loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
1491                    R.string.airplane_mode_toggleable_radios);
1492
1493            loadBooleanSetting(stmt, Settings.System.AUTO_TIME,
1494                    R.bool.def_auto_time); // Sync time to NITZ
1495
1496            loadBooleanSetting(stmt, Settings.System.AUTO_TIME_ZONE,
1497                    R.bool.def_auto_time_zone); // Sync timezone to NITZ
1498
1499            loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS,
1500                    R.integer.def_screen_brightness);
1501
1502            loadBooleanSetting(stmt, Settings.System.SCREEN_BRIGHTNESS_MODE,
1503                    R.bool.def_screen_brightness_automatic_mode);
1504
1505            loadDefaultAnimationSettings(stmt);
1506
1507            loadBooleanSetting(stmt, Settings.System.ACCELEROMETER_ROTATION,
1508                    R.bool.def_accelerometer_rotation);
1509
1510            loadDefaultHapticSettings(stmt);
1511
1512            loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
1513                    R.bool.def_notification_pulse);
1514            loadSetting(stmt, Settings.Secure.SET_INSTALL_LOCATION, 0);
1515            loadSetting(stmt, Settings.Secure.DEFAULT_INSTALL_LOCATION,
1516                    PackageHelper.APP_INSTALL_AUTO);
1517
1518            loadUISoundEffectsSettings(stmt);
1519
1520            loadIntegerSetting(stmt, Settings.System.POINTER_SPEED,
1521                    R.integer.def_pointer_speed);
1522
1523        } finally {
1524            if (stmt != null) stmt.close();
1525        }
1526    }
1527
1528    private void loadUISoundEffectsSettings(SQLiteStatement stmt) {
1529        loadIntegerSetting(stmt, Settings.System.POWER_SOUNDS_ENABLED,
1530            R.integer.def_power_sounds_enabled);
1531        loadStringSetting(stmt, Settings.System.LOW_BATTERY_SOUND,
1532            R.string.def_low_battery_sound);
1533        loadBooleanSetting(stmt, Settings.System.DTMF_TONE_WHEN_DIALING,
1534                R.bool.def_dtmf_tones_enabled);
1535        loadBooleanSetting(stmt, Settings.System.SOUND_EFFECTS_ENABLED,
1536                R.bool.def_sound_effects_enabled);
1537        loadBooleanSetting(stmt, Settings.System.HAPTIC_FEEDBACK_ENABLED,
1538                R.bool.def_haptic_feedback);
1539
1540        loadIntegerSetting(stmt, Settings.System.DOCK_SOUNDS_ENABLED,
1541            R.integer.def_dock_sounds_enabled);
1542        loadStringSetting(stmt, Settings.System.DESK_DOCK_SOUND,
1543            R.string.def_desk_dock_sound);
1544        loadStringSetting(stmt, Settings.System.DESK_UNDOCK_SOUND,
1545            R.string.def_desk_undock_sound);
1546        loadStringSetting(stmt, Settings.System.CAR_DOCK_SOUND,
1547            R.string.def_car_dock_sound);
1548        loadStringSetting(stmt, Settings.System.CAR_UNDOCK_SOUND,
1549            R.string.def_car_undock_sound);
1550
1551        loadIntegerSetting(stmt, Settings.System.LOCKSCREEN_SOUNDS_ENABLED,
1552            R.integer.def_lockscreen_sounds_enabled);
1553        loadStringSetting(stmt, Settings.System.LOCK_SOUND,
1554            R.string.def_lock_sound);
1555        loadStringSetting(stmt, Settings.System.UNLOCK_SOUND,
1556            R.string.def_unlock_sound);
1557    }
1558
1559    private void loadDefaultAnimationSettings(SQLiteStatement stmt) {
1560        loadFractionSetting(stmt, Settings.System.WINDOW_ANIMATION_SCALE,
1561                R.fraction.def_window_animation_scale, 1);
1562        loadFractionSetting(stmt, Settings.System.TRANSITION_ANIMATION_SCALE,
1563                R.fraction.def_window_transition_scale, 1);
1564    }
1565
1566    private void loadDefaultHapticSettings(SQLiteStatement stmt) {
1567        loadBooleanSetting(stmt, Settings.System.HAPTIC_FEEDBACK_ENABLED,
1568                R.bool.def_haptic_feedback);
1569    }
1570
1571    private void loadSecureSettings(SQLiteDatabase db) {
1572        SQLiteStatement stmt = null;
1573        try {
1574            stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
1575                    + " VALUES(?,?);");
1576
1577            loadBooleanSetting(stmt, Settings.Secure.BLUETOOTH_ON,
1578                    R.bool.def_bluetooth_on);
1579
1580            // Data roaming default, based on build
1581            loadSetting(stmt, Settings.Secure.DATA_ROAMING,
1582                    "true".equalsIgnoreCase(
1583                            SystemProperties.get("ro.com.android.dataroaming",
1584                                    "false")) ? 1 : 0);
1585
1586            // Mobile Data default, based on build
1587            loadSetting(stmt, Settings.Secure.MOBILE_DATA,
1588                    "true".equalsIgnoreCase(
1589                            SystemProperties.get("ro.com.android.mobiledata",
1590                                    "true")) ? 1 : 0);
1591
1592            loadBooleanSetting(stmt, Settings.Secure.INSTALL_NON_MARKET_APPS,
1593                    R.bool.def_install_non_market_apps);
1594
1595            loadStringSetting(stmt, Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
1596                    R.string.def_location_providers_allowed);
1597
1598            loadBooleanSetting(stmt, Settings.Secure.ASSISTED_GPS_ENABLED,
1599                    R.bool.assisted_gps_enabled);
1600
1601            loadIntegerSetting(stmt, Settings.Secure.NETWORK_PREFERENCE,
1602                    R.integer.def_network_preference);
1603
1604            loadBooleanSetting(stmt, Settings.Secure.USB_MASS_STORAGE_ENABLED,
1605                    R.bool.def_usb_mass_storage_enabled);
1606
1607            loadBooleanSetting(stmt, Settings.Secure.WIFI_ON,
1608                    R.bool.def_wifi_on);
1609            loadBooleanSetting(stmt, Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
1610                    R.bool.def_networks_available_notification_on);
1611
1612            String wifiWatchList = SystemProperties.get("ro.com.android.wifi-watchlist");
1613            if (!TextUtils.isEmpty(wifiWatchList)) {
1614                loadSetting(stmt, Settings.Secure.WIFI_WATCHDOG_WATCH_LIST, wifiWatchList);
1615            }
1616
1617            // Set the preferred network mode to 0 = Global, CDMA default
1618            int type;
1619            if (TelephonyManager.getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) {
1620                type = Phone.NT_MODE_GLOBAL;
1621            } else {
1622                type = SystemProperties.getInt("ro.telephony.default_network",
1623                        RILConstants.PREFERRED_NETWORK_MODE);
1624            }
1625            loadSetting(stmt, Settings.Secure.PREFERRED_NETWORK_MODE, type);
1626
1627            // Enable or disable Cell Broadcast SMS
1628            loadSetting(stmt, Settings.Secure.CDMA_CELL_BROADCAST_SMS,
1629                    RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED);
1630
1631            // Don't do this.  The SystemServer will initialize ADB_ENABLED from a
1632            // persistent system property instead.
1633            //loadSetting(stmt, Settings.Secure.ADB_ENABLED, 0);
1634
1635            // Allow mock locations default, based on build
1636            loadSetting(stmt, Settings.Secure.ALLOW_MOCK_LOCATION,
1637                    "1".equals(SystemProperties.get("ro.allow.mock.location")) ? 1 : 0);
1638
1639            loadSecure35Settings(stmt);
1640
1641            loadBooleanSetting(stmt, Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND,
1642                    R.bool.def_mount_play_notification_snd);
1643
1644            loadBooleanSetting(stmt, Settings.Secure.MOUNT_UMS_AUTOSTART,
1645                    R.bool.def_mount_ums_autostart);
1646
1647            loadBooleanSetting(stmt, Settings.Secure.MOUNT_UMS_PROMPT,
1648                    R.bool.def_mount_ums_prompt);
1649
1650            loadBooleanSetting(stmt, Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED,
1651                    R.bool.def_mount_ums_notify_enabled);
1652
1653            loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION,
1654                    R.bool.def_accessibility_script_injection);
1655
1656            loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS,
1657                    R.string.def_accessibility_web_content_key_bindings);
1658
1659            final int maxBytes = mContext.getResources().getInteger(
1660                    R.integer.def_download_manager_max_bytes_over_mobile);
1661            if (maxBytes > 0) {
1662                loadSetting(stmt, Settings.Secure.DOWNLOAD_MAX_BYTES_OVER_MOBILE,
1663                        Integer.toString(maxBytes));
1664            }
1665
1666            final int recommendedMaxBytes = mContext.getResources().getInteger(
1667                    R.integer.def_download_manager_recommended_max_bytes_over_mobile);
1668            if (recommendedMaxBytes > 0) {
1669                loadSetting(stmt, Settings.Secure.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE,
1670                        Integer.toString(recommendedMaxBytes));
1671            }
1672
1673            loadIntegerSetting(stmt, Settings.Secure.LONG_PRESS_TIMEOUT,
1674                    R.integer.def_long_press_timeout_millis);
1675
1676            loadBooleanSetting(stmt, Settings.Secure.TOUCH_EXPLORATION_ENABLED,
1677                    R.bool.def_touch_exploration_enabled);
1678
1679            loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD,
1680                    R.bool.def_accessibility_speak_password);
1681
1682            loadStringSetting(stmt, Settings.Secure.ACCESSIBILITY_SCREEN_READER_URL,
1683                    R.string.def_accessibility_screen_reader_url);
1684
1685            if (SystemProperties.getBoolean("ro.lockscreen.disable.default", false) == true) {
1686                loadSetting(stmt, Settings.System.LOCKSCREEN_DISABLED, "1");
1687            } else {
1688                loadBooleanSetting(stmt, Settings.System.LOCKSCREEN_DISABLED,
1689                        R.bool.def_lockscreen_disabled);
1690            }
1691
1692            loadBooleanSetting(stmt, Settings.Secure.DEVICE_PROVISIONED,
1693                    R.bool.def_device_provisioned);
1694
1695            loadBooleanSetting(stmt, Settings.Secure.NETSTATS_ENABLED,
1696                    R.bool.def_netstats_enabled);
1697
1698            loadIntegerSetting(stmt, Settings.Secure.WIFI_MAX_DHCP_RETRY_COUNT,
1699                    R.integer.def_max_dhcp_retries);
1700        } finally {
1701            if (stmt != null) stmt.close();
1702        }
1703    }
1704
1705    private void loadSecure35Settings(SQLiteStatement stmt) {
1706        loadBooleanSetting(stmt, Settings.Secure.BACKUP_ENABLED,
1707                R.bool.def_backup_enabled);
1708
1709        loadStringSetting(stmt, Settings.Secure.BACKUP_TRANSPORT,
1710                R.string.def_backup_transport);
1711    }
1712
1713    private void loadSetting(SQLiteStatement stmt, String key, Object value) {
1714        stmt.bindString(1, key);
1715        stmt.bindString(2, value.toString());
1716        stmt.execute();
1717    }
1718
1719    private void loadStringSetting(SQLiteStatement stmt, String key, int resid) {
1720        loadSetting(stmt, key, mContext.getResources().getString(resid));
1721    }
1722
1723    private void loadBooleanSetting(SQLiteStatement stmt, String key, int resid) {
1724        loadSetting(stmt, key,
1725                mContext.getResources().getBoolean(resid) ? "1" : "0");
1726    }
1727
1728    private void loadIntegerSetting(SQLiteStatement stmt, String key, int resid) {
1729        loadSetting(stmt, key,
1730                Integer.toString(mContext.getResources().getInteger(resid)));
1731    }
1732
1733    private void loadFractionSetting(SQLiteStatement stmt, String key, int resid, int base) {
1734        loadSetting(stmt, key,
1735                Float.toString(mContext.getResources().getFraction(resid, base, base)));
1736    }
1737
1738    private int getIntValueFromSystem(SQLiteDatabase db, String name, int defaultValue) {
1739        int value = defaultValue;
1740        Cursor c = null;
1741        try {
1742            c = db.query("system", new String[] { Settings.System.VALUE }, "name='" + name + "'",
1743                    null, null, null, null);
1744            if (c != null && c.moveToFirst()) {
1745                String val = c.getString(0);
1746                value = val == null ? defaultValue : Integer.parseInt(val);
1747            }
1748        } finally {
1749            if (c != null) c.close();
1750        }
1751        return value;
1752    }
1753}
1754