DatabaseHelper.java revision 8932020f542ae6dd4750fa823bbf2d2bcf504267
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.PackageInfo;
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.SystemProperties;
35import android.provider.Settings;
36import android.provider.Settings.Secure;
37import android.text.TextUtils;
38import android.util.AttributeSet;
39import android.util.Config;
40import android.util.Log;
41import android.util.Xml;
42
43import com.android.internal.content.PackageHelper;
44import com.android.internal.telephony.RILConstants;
45import com.android.internal.util.XmlUtils;
46import com.android.internal.widget.LockPatternUtils;
47import com.android.internal.widget.LockPatternView;
48import org.xmlpull.v1.XmlPullParser;
49import org.xmlpull.v1.XmlPullParserException;
50
51import java.io.IOException;
52import java.util.List;
53
54/**
55 * Database helper class for {@link SettingsProvider}.
56 * Mostly just has a bit {@link #onCreate} to initialize the database.
57 */
58public class DatabaseHelper extends SQLiteOpenHelper {
59    private static final String TAG = "SettingsProvider";
60    private static final String DATABASE_NAME = "settings.db";
61
62    // Please, please please. If you update the database version, check to make sure the
63    // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
64    // is properly propagated through your change.  Not doing so will result in a loss of user
65    // settings.
66    private static final int DATABASE_VERSION = 56;
67
68    private Context mContext;
69
70    public DatabaseHelper(Context context) {
71        super(context, DATABASE_NAME, null, DATABASE_VERSION);
72        mContext = context;
73    }
74
75    private void createSecureTable(SQLiteDatabase db) {
76        db.execSQL("CREATE TABLE secure (" +
77                "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
78                "name TEXT UNIQUE ON CONFLICT REPLACE," +
79                "value TEXT" +
80                ");");
81        db.execSQL("CREATE INDEX secureIndex1 ON secure (name);");
82    }
83
84    @Override
85    public void onCreate(SQLiteDatabase db) {
86        db.execSQL("CREATE TABLE system (" +
87                    "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
88                    "name TEXT UNIQUE ON CONFLICT REPLACE," +
89                    "value TEXT" +
90                    ");");
91        db.execSQL("CREATE INDEX systemIndex1 ON system (name);");
92
93        createSecureTable(db);
94
95        db.execSQL("CREATE TABLE bluetooth_devices (" +
96                    "_id INTEGER PRIMARY KEY," +
97                    "name TEXT," +
98                    "addr TEXT," +
99                    "channel INTEGER," +
100                    "type INTEGER" +
101                    ");");
102
103        db.execSQL("CREATE TABLE bookmarks (" +
104                    "_id INTEGER PRIMARY KEY," +
105                    "title TEXT," +
106                    "folder TEXT," +
107                    "intent TEXT," +
108                    "shortcut INTEGER," +
109                    "ordering INTEGER" +
110                    ");");
111
112        db.execSQL("CREATE INDEX bookmarksIndex1 ON bookmarks (folder);");
113        db.execSQL("CREATE INDEX bookmarksIndex2 ON bookmarks (shortcut);");
114
115        // Populate bookmarks table with initial bookmarks
116        loadBookmarks(db);
117
118        // Load initial volume levels into DB
119        loadVolumeLevels(db);
120
121        // Load inital settings values
122        loadSettings(db);
123    }
124
125    @Override
126    public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
127        Log.w(TAG, "Upgrading settings database from version " + oldVersion + " to "
128                + currentVersion);
129
130        int upgradeVersion = oldVersion;
131
132        // Pattern for upgrade blocks:
133        //
134        //    if (upgradeVersion == [the DATABASE_VERSION you set] - 1) {
135        //        .. your upgrade logic..
136        //        upgradeVersion = [the DATABASE_VERSION you set]
137        //    }
138
139        if (upgradeVersion == 20) {
140            /*
141             * Version 21 is part of the volume control refresh. There is no
142             * longer a UI-visible for setting notification vibrate on/off (in
143             * our design), but the functionality still exists. Force the
144             * notification vibrate to on.
145             */
146            loadVibrateSetting(db, true);
147
148            upgradeVersion = 21;
149        }
150
151        if (upgradeVersion < 22) {
152            upgradeVersion = 22;
153            // Upgrade the lock gesture storage location and format
154            upgradeLockPatternLocation(db);
155        }
156
157        if (upgradeVersion < 23) {
158            db.execSQL("UPDATE favorites SET iconResource=0 WHERE iconType=0");
159            upgradeVersion = 23;
160        }
161
162        if (upgradeVersion == 23) {
163            db.beginTransaction();
164            try {
165                db.execSQL("ALTER TABLE favorites ADD spanX INTEGER");
166                db.execSQL("ALTER TABLE favorites ADD spanY INTEGER");
167                // Shortcuts, applications, folders
168                db.execSQL("UPDATE favorites SET spanX=1, spanY=1 WHERE itemType<=0");
169                // Photo frames, clocks
170                db.execSQL(
171                    "UPDATE favorites SET spanX=2, spanY=2 WHERE itemType=1000 or itemType=1002");
172                // Search boxes
173                db.execSQL("UPDATE favorites SET spanX=4, spanY=1 WHERE itemType=1001");
174                db.setTransactionSuccessful();
175            } finally {
176                db.endTransaction();
177            }
178            upgradeVersion = 24;
179        }
180
181        if (upgradeVersion == 24) {
182            db.beginTransaction();
183            try {
184                // The value of the constants for preferring wifi or preferring mobile have been
185                // swapped, so reload the default.
186                db.execSQL("DELETE FROM system WHERE name='network_preference'");
187                db.execSQL("INSERT INTO system ('name', 'value') values ('network_preference', '" +
188                        ConnectivityManager.DEFAULT_NETWORK_PREFERENCE + "')");
189                db.setTransactionSuccessful();
190            } finally {
191                db.endTransaction();
192            }
193            upgradeVersion = 25;
194        }
195
196        if (upgradeVersion == 25) {
197            db.beginTransaction();
198            try {
199                db.execSQL("ALTER TABLE favorites ADD uri TEXT");
200                db.execSQL("ALTER TABLE favorites ADD displayMode INTEGER");
201                db.setTransactionSuccessful();
202            } finally {
203                db.endTransaction();
204            }
205            upgradeVersion = 26;
206        }
207
208        if (upgradeVersion == 26) {
209            // This introduces the new secure settings table.
210            db.beginTransaction();
211            try {
212                createSecureTable(db);
213                db.setTransactionSuccessful();
214            } finally {
215                db.endTransaction();
216            }
217            upgradeVersion = 27;
218        }
219
220        if (upgradeVersion == 27) {
221            String[] settingsToMove = {
222                    Settings.Secure.ADB_ENABLED,
223                    Settings.Secure.ANDROID_ID,
224                    Settings.Secure.BLUETOOTH_ON,
225                    Settings.Secure.DATA_ROAMING,
226                    Settings.Secure.DEVICE_PROVISIONED,
227                    Settings.Secure.HTTP_PROXY,
228                    Settings.Secure.INSTALL_NON_MARKET_APPS,
229                    Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
230                    Settings.Secure.LOGGING_ID,
231                    Settings.Secure.NETWORK_PREFERENCE,
232                    Settings.Secure.PARENTAL_CONTROL_ENABLED,
233                    Settings.Secure.PARENTAL_CONTROL_LAST_UPDATE,
234                    Settings.Secure.PARENTAL_CONTROL_REDIRECT_URL,
235                    Settings.Secure.SETTINGS_CLASSNAME,
236                    Settings.Secure.USB_MASS_STORAGE_ENABLED,
237                    Settings.Secure.USE_GOOGLE_MAIL,
238                    Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
239                    Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
240                    Settings.Secure.WIFI_NUM_OPEN_NETWORKS_KEPT,
241                    Settings.Secure.WIFI_ON,
242                    Settings.Secure.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE,
243                    Settings.Secure.WIFI_WATCHDOG_AP_COUNT,
244                    Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS,
245                    Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED,
246                    Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS,
247                    Settings.Secure.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT,
248                    Settings.Secure.WIFI_WATCHDOG_MAX_AP_CHECKS,
249                    Settings.Secure.WIFI_WATCHDOG_ON,
250                    Settings.Secure.WIFI_WATCHDOG_PING_COUNT,
251                    Settings.Secure.WIFI_WATCHDOG_PING_DELAY_MS,
252                    Settings.Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS,
253                };
254            moveFromSystemToSecure(db, settingsToMove);
255            upgradeVersion = 28;
256        }
257
258        if (upgradeVersion == 28 || upgradeVersion == 29) {
259            // Note: The upgrade to 28 was flawed since it didn't delete the old
260            // setting first before inserting. Combining 28 and 29 with the
261            // fixed version.
262
263            // This upgrade adds the STREAM_NOTIFICATION type to the list of
264            // types affected by ringer modes (silent, vibrate, etc.)
265            db.beginTransaction();
266            try {
267                db.execSQL("DELETE FROM system WHERE name='"
268                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'");
269                int newValue = (1 << AudioManager.STREAM_RING)
270                        | (1 << AudioManager.STREAM_NOTIFICATION)
271                        | (1 << AudioManager.STREAM_SYSTEM);
272                db.execSQL("INSERT INTO system ('name', 'value') values ('"
273                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '"
274                        + String.valueOf(newValue) + "')");
275                db.setTransactionSuccessful();
276            } finally {
277                db.endTransaction();
278            }
279
280            upgradeVersion = 30;
281        }
282
283        if (upgradeVersion == 30) {
284            /*
285             * Upgrade 31 clears the title for all quick launch shortcuts so the
286             * activities' titles will be resolved at display time. Also, the
287             * folder is changed to '@quicklaunch'.
288             */
289            db.beginTransaction();
290            try {
291                db.execSQL("UPDATE bookmarks SET folder = '@quicklaunch'");
292                db.execSQL("UPDATE bookmarks SET title = ''");
293                db.setTransactionSuccessful();
294            } finally {
295                db.endTransaction();
296            }
297            upgradeVersion = 31;
298        }
299
300        if (upgradeVersion == 31) {
301            /*
302             * Animations are now managed in preferences, and may be
303             * enabled or disabled based on product resources.
304             */
305            db.beginTransaction();
306            SQLiteStatement stmt = null;
307            try {
308                db.execSQL("DELETE FROM system WHERE name='"
309                        + Settings.System.WINDOW_ANIMATION_SCALE + "'");
310                db.execSQL("DELETE FROM system WHERE name='"
311                        + Settings.System.TRANSITION_ANIMATION_SCALE + "'");
312                stmt = db.compileStatement("INSERT INTO system(name,value)"
313                        + " VALUES(?,?);");
314                loadDefaultAnimationSettings(stmt);
315                db.setTransactionSuccessful();
316            } finally {
317                db.endTransaction();
318                if (stmt != null) stmt.close();
319            }
320            upgradeVersion = 32;
321        }
322
323        if (upgradeVersion == 32) {
324            // The Wi-Fi watchdog SSID list is now seeded with the value of
325            // the property ro.com.android.wifi-watchlist
326            String wifiWatchList = SystemProperties.get("ro.com.android.wifi-watchlist");
327            if (!TextUtils.isEmpty(wifiWatchList)) {
328                db.beginTransaction();
329                try {
330                    db.execSQL("INSERT OR IGNORE INTO secure(name,value) values('" +
331                            Settings.Secure.WIFI_WATCHDOG_WATCH_LIST + "','" +
332                            wifiWatchList + "');");
333                    db.setTransactionSuccessful();
334                } finally {
335                    db.endTransaction();
336                }
337            }
338            upgradeVersion = 33;
339        }
340
341        if (upgradeVersion == 33) {
342            // Set the default zoom controls to: tap-twice to bring up +/-
343            db.beginTransaction();
344            try {
345                db.execSQL("INSERT INTO system(name,value) values('zoom','2');");
346                db.setTransactionSuccessful();
347            } finally {
348                db.endTransaction();
349            }
350            upgradeVersion = 34;
351        }
352
353        if (upgradeVersion == 34) {
354            db.beginTransaction();
355            SQLiteStatement stmt = null;
356            try {
357                stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
358                        + " VALUES(?,?);");
359                loadSecure35Settings(stmt);
360                db.setTransactionSuccessful();
361            } finally {
362                db.endTransaction();
363                if (stmt != null) stmt.close();
364            }
365            upgradeVersion = 35;
366        }
367            // due to a botched merge from donut to eclair, the initialization of ASSISTED_GPS_ENABLED
368            // was accidentally done out of order here.
369            // to fix this, ASSISTED_GPS_ENABLED is now initialized while upgrading from 38 to 39,
370            // and we intentionally do nothing from 35 to 36 now.
371        if (upgradeVersion == 35) {
372            upgradeVersion = 36;
373        }
374
375        if (upgradeVersion == 36) {
376           // This upgrade adds the STREAM_SYSTEM_ENFORCED type to the list of
377            // types affected by ringer modes (silent, vibrate, etc.)
378            db.beginTransaction();
379            try {
380                db.execSQL("DELETE FROM system WHERE name='"
381                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "'");
382                int newValue = (1 << AudioManager.STREAM_RING)
383                        | (1 << AudioManager.STREAM_NOTIFICATION)
384                        | (1 << AudioManager.STREAM_SYSTEM)
385                        | (1 << AudioManager.STREAM_SYSTEM_ENFORCED);
386                db.execSQL("INSERT INTO system ('name', 'value') values ('"
387                        + Settings.System.MODE_RINGER_STREAMS_AFFECTED + "', '"
388                        + String.valueOf(newValue) + "')");
389                db.setTransactionSuccessful();
390            } finally {
391                db.endTransaction();
392            }
393            upgradeVersion = 37;
394        }
395
396        if (upgradeVersion == 37) {
397            db.beginTransaction();
398            SQLiteStatement stmt = null;
399            try {
400                stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
401                        + " VALUES(?,?);");
402                loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
403                        R.string.airplane_mode_toggleable_radios);
404                db.setTransactionSuccessful();
405            } finally {
406                db.endTransaction();
407                if (stmt != null) stmt.close();
408            }
409            upgradeVersion = 38;
410        }
411
412        if (upgradeVersion == 38) {
413            db.beginTransaction();
414            try {
415                String value =
416                        mContext.getResources().getBoolean(R.bool.assisted_gps_enabled) ? "1" : "0";
417                db.execSQL("INSERT OR IGNORE INTO secure(name,value) values('" +
418                        Settings.Secure.ASSISTED_GPS_ENABLED + "','" + value + "');");
419                db.setTransactionSuccessful();
420            } finally {
421                db.endTransaction();
422            }
423
424            upgradeVersion = 39;
425        }
426
427        if (upgradeVersion == 39) {
428            db.beginTransaction();
429            try {
430                String value =
431                        mContext.getResources().getBoolean(
432                        R.bool.def_screen_brightness_automatic_mode) ? "1" : "0";
433                db.execSQL("INSERT OR IGNORE INTO system(name,value) values('" +
434                        Settings.System.SCREEN_BRIGHTNESS_MODE + "','" + value + "');");
435                db.setTransactionSuccessful();
436            } finally {
437                db.endTransaction();
438            }
439
440            upgradeVersion = 40;
441        }
442
443        if (upgradeVersion == 40) {
444            /*
445             * All animations are now turned on by default!
446             */
447            db.beginTransaction();
448            SQLiteStatement stmt = null;
449            try {
450                db.execSQL("DELETE FROM system WHERE name='"
451                        + Settings.System.WINDOW_ANIMATION_SCALE + "'");
452                db.execSQL("DELETE FROM system WHERE name='"
453                        + Settings.System.TRANSITION_ANIMATION_SCALE + "'");
454                stmt = db.compileStatement("INSERT INTO system(name,value)"
455                        + " VALUES(?,?);");
456                loadDefaultAnimationSettings(stmt);
457                db.setTransactionSuccessful();
458            } finally {
459                db.endTransaction();
460                if (stmt != null) stmt.close();
461            }
462            upgradeVersion = 41;
463        }
464
465        if (upgradeVersion == 41) {
466            /*
467             * Initialize newly public haptic feedback setting
468             */
469            db.beginTransaction();
470            SQLiteStatement stmt = null;
471            try {
472                db.execSQL("DELETE FROM system WHERE name='"
473                        + Settings.System.HAPTIC_FEEDBACK_ENABLED + "'");
474                stmt = db.compileStatement("INSERT INTO system(name,value)"
475                        + " VALUES(?,?);");
476                loadDefaultHapticSettings(stmt);
477                db.setTransactionSuccessful();
478            } finally {
479                db.endTransaction();
480                if (stmt != null) stmt.close();
481            }
482            upgradeVersion = 42;
483        }
484
485        if (upgradeVersion == 42) {
486            /*
487             * Initialize new notification pulse setting
488             */
489            db.beginTransaction();
490            SQLiteStatement stmt = null;
491            try {
492                stmt = db.compileStatement("INSERT INTO system(name,value)"
493                        + " VALUES(?,?);");
494                loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
495                        R.bool.def_notification_pulse);
496                db.setTransactionSuccessful();
497            } finally {
498                db.endTransaction();
499                if (stmt != null) stmt.close();
500            }
501            upgradeVersion = 43;
502        }
503
504        if (upgradeVersion == 43) {
505            /*
506             * This upgrade stores bluetooth volume separately from voice volume
507             */
508            db.beginTransaction();
509            SQLiteStatement stmt = null;
510            try {
511                stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
512                        + " VALUES(?,?);");
513                loadSetting(stmt, Settings.System.VOLUME_BLUETOOTH_SCO,
514                        AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_BLUETOOTH_SCO]);
515                db.setTransactionSuccessful();
516            } finally {
517                db.endTransaction();
518                if (stmt != null) stmt.close();
519            }
520            upgradeVersion = 44;
521        }
522
523        if (upgradeVersion == 44) {
524            /*
525             * Gservices was moved into vendor/google.
526             */
527            db.execSQL("DROP TABLE IF EXISTS gservices");
528            db.execSQL("DROP INDEX IF EXISTS gservicesIndex1");
529            upgradeVersion = 45;
530        }
531
532        if (upgradeVersion == 45) {
533             /*
534              * New settings for MountService
535              */
536            db.beginTransaction();
537            try {
538                db.execSQL("INSERT INTO secure(name,value) values('" +
539                        Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND + "','1');");
540                db.execSQL("INSERT INTO secure(name,value) values('" +
541                        Settings.Secure.MOUNT_UMS_AUTOSTART + "','0');");
542                db.execSQL("INSERT INTO secure(name,value) values('" +
543                        Settings.Secure.MOUNT_UMS_PROMPT + "','1');");
544                db.execSQL("INSERT INTO secure(name,value) values('" +
545                        Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED + "','1');");
546                db.setTransactionSuccessful();
547            } finally {
548                db.endTransaction();
549            }
550            upgradeVersion = 46;
551        }
552
553        if (upgradeVersion == 46) {
554            /*
555             * The password mode constants have changed; reset back to no
556             * password.
557             */
558            db.beginTransaction();
559            try {
560                db.execSQL("DELETE FROM system WHERE name='lockscreen.password_type';");
561                db.setTransactionSuccessful();
562            } finally {
563                db.endTransaction();
564            }
565           upgradeVersion = 47;
566       }
567
568
569        if (upgradeVersion == 47) {
570            /*
571             * The password mode constants have changed again; reset back to no
572             * password.
573             */
574            db.beginTransaction();
575            try {
576                db.execSQL("DELETE FROM system WHERE name='lockscreen.password_type';");
577                db.setTransactionSuccessful();
578            } finally {
579                db.endTransaction();
580            }
581           upgradeVersion = 48;
582       }
583
584       if (upgradeVersion == 48) {
585           /*
586            * Default recognition service no longer initialized here,
587            * moved to RecognitionManagerService.
588            */
589           upgradeVersion = 49;
590       }
591
592       if (upgradeVersion == 49) {
593           /*
594            * New settings for new user interface noises.
595            */
596           db.beginTransaction();
597           SQLiteStatement stmt = null;
598           try {
599                stmt = db.compileStatement("INSERT INTO system(name,value)"
600                        + " VALUES(?,?);");
601                loadUISoundEffectsSettings(stmt);
602                db.setTransactionSuccessful();
603            } finally {
604                db.endTransaction();
605                if (stmt != null) stmt.close();
606            }
607
608           upgradeVersion = 50;
609       }
610
611       if (upgradeVersion == 50) {
612           /*
613            * Install location no longer initiated here.
614            */
615           upgradeVersion = 51;
616       }
617
618       if (upgradeVersion == 51) {
619           /* Move the lockscreen related settings to Secure, including some private ones. */
620           String[] settingsToMove = {
621                   Secure.LOCK_PATTERN_ENABLED,
622                   Secure.LOCK_PATTERN_VISIBLE,
623                   Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED,
624                   "lockscreen.password_type",
625                   "lockscreen.lockoutattemptdeadline",
626                   "lockscreen.patterneverchosen",
627                   "lock_pattern_autolock",
628                   "lockscreen.lockedoutpermanently",
629                   "lockscreen.password_salt"
630           };
631           moveFromSystemToSecure(db, settingsToMove);
632           upgradeVersion = 52;
633       }
634
635        if (upgradeVersion == 52) {
636            // new vibration/silent mode settings
637            db.beginTransaction();
638            SQLiteStatement stmt = null;
639            try {
640                stmt = db.compileStatement("INSERT INTO system(name,value)"
641                        + " VALUES(?,?);");
642                loadBooleanSetting(stmt, Settings.System.VIBRATE_IN_SILENT,
643                        R.bool.def_vibrate_in_silent);
644                db.setTransactionSuccessful();
645            } finally {
646                db.endTransaction();
647                if (stmt != null) stmt.close();
648            }
649
650            upgradeVersion = 53;
651        }
652
653        if (upgradeVersion == 53) {
654            /*
655             * New settings for set install location UI no longer initiated here.
656             */
657            upgradeVersion = 54;
658        }
659
660        if (upgradeVersion == 54) {
661            /*
662             * Update the screen timeout value if set to never
663             */
664            db.beginTransaction();
665            try {
666                upgradeScreenTimeoutFromNever(db);
667                db.setTransactionSuccessful();
668            } finally {
669                db.endTransaction();
670            }
671
672            upgradeVersion = 55;
673        }
674
675        if (upgradeVersion == 55) {
676            /* Move the install location settings. */
677            String[] settingsToMove = {
678                    Secure.SET_INSTALL_LOCATION,
679                    Secure.DEFAULT_INSTALL_LOCATION
680            };
681            moveFromSystemToSecure(db, settingsToMove);
682            db.beginTransaction();
683            SQLiteStatement stmt = null;
684            try {
685                stmt = db.compileStatement("INSERT INTO system(name,value)"
686                        + " VALUES(?,?);");
687                loadSetting(stmt, Secure.SET_INSTALL_LOCATION, 0);
688                loadSetting(stmt, Secure.DEFAULT_INSTALL_LOCATION,
689                        PackageHelper.APP_INSTALL_AUTO);
690                db.setTransactionSuccessful();
691             } finally {
692                 db.endTransaction();
693                 if (stmt != null) stmt.close();
694             }
695            upgradeVersion = 56;
696        }
697        // *** Remember to update DATABASE_VERSION above!
698
699        if (upgradeVersion != currentVersion) {
700            Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion
701                    + ", must wipe the settings provider");
702            db.execSQL("DROP TABLE IF EXISTS system");
703            db.execSQL("DROP INDEX IF EXISTS systemIndex1");
704            db.execSQL("DROP TABLE IF EXISTS secure");
705            db.execSQL("DROP INDEX IF EXISTS secureIndex1");
706            db.execSQL("DROP TABLE IF EXISTS gservices");
707            db.execSQL("DROP INDEX IF EXISTS gservicesIndex1");
708            db.execSQL("DROP TABLE IF EXISTS bluetooth_devices");
709            db.execSQL("DROP TABLE IF EXISTS bookmarks");
710            db.execSQL("DROP INDEX IF EXISTS bookmarksIndex1");
711            db.execSQL("DROP INDEX IF EXISTS bookmarksIndex2");
712            db.execSQL("DROP TABLE IF EXISTS favorites");
713            onCreate(db);
714
715            // Added for diagnosing settings.db wipes after the fact
716            String wipeReason = oldVersion + "/" + upgradeVersion + "/" + currentVersion;
717            db.execSQL("INSERT INTO secure(name,value) values('" +
718                    "wiped_db_reason" + "','" + wipeReason + "');");
719        }
720    }
721
722    private void moveFromSystemToSecure(SQLiteDatabase db, String [] settingsToMove) {
723        // Copy settings values from 'system' to 'secure' and delete them from 'system'
724        SQLiteStatement insertStmt = null;
725        SQLiteStatement deleteStmt = null;
726
727        db.beginTransaction();
728        try {
729            insertStmt =
730                db.compileStatement("INSERT INTO secure (name,value) SELECT name,value FROM "
731                    + "system WHERE name=?");
732            deleteStmt = db.compileStatement("DELETE FROM system WHERE name=?");
733
734
735            for (String setting : settingsToMove) {
736                insertStmt.bindString(1, setting);
737                insertStmt.execute();
738
739                deleteStmt.bindString(1, setting);
740                deleteStmt.execute();
741            }
742            db.setTransactionSuccessful();
743        } finally {
744            db.endTransaction();
745            if (insertStmt != null) {
746                insertStmt.close();
747            }
748            if (deleteStmt != null) {
749                deleteStmt.close();
750            }
751        }
752    }
753
754    private void upgradeLockPatternLocation(SQLiteDatabase db) {
755        Cursor c = db.query("system", new String[] {"_id", "value"}, "name='lock_pattern'",
756                null, null, null, null);
757        if (c.getCount() > 0) {
758            c.moveToFirst();
759            String lockPattern = c.getString(1);
760            if (!TextUtils.isEmpty(lockPattern)) {
761                // Convert lock pattern
762                try {
763                    LockPatternUtils lpu = new LockPatternUtils(mContext);
764                    List<LockPatternView.Cell> cellPattern =
765                            LockPatternUtils.stringToPattern(lockPattern);
766                    lpu.saveLockPattern(cellPattern);
767                } catch (IllegalArgumentException e) {
768                    // Don't want corrupted lock pattern to hang the reboot process
769                }
770            }
771            c.close();
772            db.delete("system", "name='lock_pattern'", null);
773        } else {
774            c.close();
775        }
776    }
777
778    private void upgradeScreenTimeoutFromNever(SQLiteDatabase db) {
779        // See if the timeout is -1 (for "Never").
780        Cursor c = db.query("system", new String[] { "_id", "value" }, "name=? AND value=?",
781                new String[] { Settings.System.SCREEN_OFF_TIMEOUT, "-1" },
782                null, null, null);
783
784        SQLiteStatement stmt = null;
785        if (c.getCount() > 0) {
786            c.close();
787            try {
788                stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)"
789                        + " VALUES(?,?);");
790
791                // Set the timeout to 30 minutes in milliseconds
792                loadSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
793                        Integer.toString(30 * 60 * 1000));
794            } finally {
795                if (stmt != null) stmt.close();
796            }
797        } else {
798            c.close();
799        }
800    }
801
802    /**
803     * Loads the default set of bookmarked shortcuts from an xml file.
804     *
805     * @param db The database to write the values into
806     * @param startingIndex The zero-based position at which bookmarks in this file should begin
807     */
808    private int loadBookmarks(SQLiteDatabase db, int startingIndex) {
809        Intent intent = new Intent(Intent.ACTION_MAIN, null);
810        intent.addCategory(Intent.CATEGORY_LAUNCHER);
811        ContentValues values = new ContentValues();
812
813        PackageManager packageManager = mContext.getPackageManager();
814        int i = startingIndex;
815
816        try {
817            XmlResourceParser parser = mContext.getResources().getXml(R.xml.bookmarks);
818            XmlUtils.beginDocument(parser, "bookmarks");
819
820            final int depth = parser.getDepth();
821            int type;
822
823            while (((type = parser.next()) != XmlPullParser.END_TAG ||
824                    parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
825
826                if (type != XmlPullParser.START_TAG) {
827                    continue;
828                }
829
830                String name = parser.getName();
831                if (!"bookmark".equals(name)) {
832                    break;
833                }
834
835                String pkg = parser.getAttributeValue(null, "package");
836                String cls = parser.getAttributeValue(null, "class");
837                String shortcutStr = parser.getAttributeValue(null, "shortcut");
838
839                int shortcutValue = (int) shortcutStr.charAt(0);
840                if (TextUtils.isEmpty(shortcutStr)) {
841                    Log.w(TAG, "Unable to get shortcut for: " + pkg + "/" + cls);
842                }
843
844                ActivityInfo info = null;
845                ComponentName cn = new ComponentName(pkg, cls);
846                try {
847                    info = packageManager.getActivityInfo(cn, 0);
848                } catch (PackageManager.NameNotFoundException e) {
849                    String[] packages = packageManager.canonicalToCurrentPackageNames(
850                            new String[] { pkg });
851                    cn = new ComponentName(packages[0], cls);
852                    try {
853                        info = packageManager.getActivityInfo(cn, 0);
854                    } catch (PackageManager.NameNotFoundException e1) {
855                        Log.w(TAG, "Unable to add bookmark: " + pkg + "/" + cls, e);
856                    }
857                }
858
859                if (info != null) {
860                    intent.setComponent(cn);
861                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
862                    values.put(Settings.Bookmarks.INTENT, intent.toUri(0));
863                    values.put(Settings.Bookmarks.TITLE,
864                            info.loadLabel(packageManager).toString());
865                    values.put(Settings.Bookmarks.SHORTCUT, shortcutValue);
866                    db.insert("bookmarks", null, values);
867                    i++;
868                }
869            }
870        } catch (XmlPullParserException e) {
871            Log.w(TAG, "Got execption parsing bookmarks.", e);
872        } catch (IOException e) {
873            Log.w(TAG, "Got execption parsing bookmarks.", e);
874        }
875
876        return i;
877    }
878
879    /**
880     * Loads the default set of bookmark packages.
881     *
882     * @param db The database to write the values into
883     */
884    private void loadBookmarks(SQLiteDatabase db) {
885        loadBookmarks(db, 0);
886    }
887
888    /**
889     * Loads the default volume levels. It is actually inserting the index of
890     * the volume array for each of the volume controls.
891     *
892     * @param db the database to insert the volume levels into
893     */
894    private void loadVolumeLevels(SQLiteDatabase db) {
895        SQLiteStatement stmt = null;
896        try {
897            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
898                    + " VALUES(?,?);");
899
900            loadSetting(stmt, Settings.System.VOLUME_MUSIC,
901                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_MUSIC]);
902            loadSetting(stmt, Settings.System.VOLUME_RING,
903                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_RING]);
904            loadSetting(stmt, Settings.System.VOLUME_SYSTEM,
905                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_SYSTEM]);
906            loadSetting(
907                    stmt,
908                    Settings.System.VOLUME_VOICE,
909                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_VOICE_CALL]);
910            loadSetting(stmt, Settings.System.VOLUME_ALARM,
911                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_ALARM]);
912            loadSetting(
913                    stmt,
914                    Settings.System.VOLUME_NOTIFICATION,
915                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_NOTIFICATION]);
916            loadSetting(
917                    stmt,
918                    Settings.System.VOLUME_BLUETOOTH_SCO,
919                    AudioManager.DEFAULT_STREAM_VOLUME[AudioManager.STREAM_BLUETOOTH_SCO]);
920
921            loadSetting(stmt, Settings.System.MODE_RINGER,
922                    AudioManager.RINGER_MODE_NORMAL);
923
924            loadVibrateSetting(db, false);
925
926            // By default, only the ring/notification and system streams are affected
927            loadSetting(stmt, Settings.System.MODE_RINGER_STREAMS_AFFECTED,
928                    (1 << AudioManager.STREAM_RING) | (1 << AudioManager.STREAM_NOTIFICATION) |
929                    (1 << AudioManager.STREAM_SYSTEM) | (1 << AudioManager.STREAM_SYSTEM_ENFORCED));
930
931            loadSetting(stmt, Settings.System.MUTE_STREAMS_AFFECTED,
932                    ((1 << AudioManager.STREAM_MUSIC) |
933                     (1 << AudioManager.STREAM_RING) |
934                     (1 << AudioManager.STREAM_NOTIFICATION) |
935                     (1 << AudioManager.STREAM_SYSTEM)));
936        } finally {
937            if (stmt != null) stmt.close();
938        }
939    }
940
941    private void loadVibrateSetting(SQLiteDatabase db, boolean deleteOld) {
942        if (deleteOld) {
943            db.execSQL("DELETE FROM system WHERE name='" + Settings.System.VIBRATE_ON + "'");
944        }
945
946        SQLiteStatement stmt = null;
947        try {
948            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
949                    + " VALUES(?,?);");
950
951            // Vibrate off by default for ringer, on for notification
952            int vibrate = 0;
953            vibrate = AudioService.getValueForVibrateSetting(vibrate,
954                    AudioManager.VIBRATE_TYPE_NOTIFICATION, AudioManager.VIBRATE_SETTING_ON);
955            vibrate |= AudioService.getValueForVibrateSetting(vibrate,
956                    AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_OFF);
957            loadSetting(stmt, Settings.System.VIBRATE_ON, vibrate);
958        } finally {
959            if (stmt != null) stmt.close();
960        }
961    }
962
963    private void loadSettings(SQLiteDatabase db) {
964        loadSystemSettings(db);
965        loadSecureSettings(db);
966    }
967
968    private void loadSystemSettings(SQLiteDatabase db) {
969        SQLiteStatement stmt = null;
970        try {
971            stmt = db.compileStatement("INSERT OR IGNORE INTO system(name,value)"
972                    + " VALUES(?,?);");
973
974            loadBooleanSetting(stmt, Settings.System.DIM_SCREEN,
975                    R.bool.def_dim_screen);
976            loadSetting(stmt, Settings.System.STAY_ON_WHILE_PLUGGED_IN,
977                    "1".equals(SystemProperties.get("ro.kernel.qemu")) ? 1 : 0);
978            loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
979                    R.integer.def_screen_off_timeout);
980
981            // Set default cdma emergency tone
982            loadSetting(stmt, Settings.System.EMERGENCY_TONE, 0);
983
984            // Set default cdma call auto retry
985            loadSetting(stmt, Settings.System.CALL_AUTO_RETRY, 0);
986
987            // Set default cdma DTMF type
988            loadSetting(stmt, Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, 0);
989
990            // Set default hearing aid
991            loadSetting(stmt, Settings.System.HEARING_AID, 0);
992
993            // Set default tty mode
994            loadSetting(stmt, Settings.System.TTY_MODE, 0);
995
996            loadBooleanSetting(stmt, Settings.System.AIRPLANE_MODE_ON,
997                    R.bool.def_airplane_mode_on);
998
999            loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_RADIOS,
1000                    R.string.def_airplane_mode_radios);
1001
1002            loadStringSetting(stmt, Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
1003                    R.string.airplane_mode_toggleable_radios);
1004
1005            loadBooleanSetting(stmt, Settings.System.AUTO_TIME,
1006                    R.bool.def_auto_time); // Sync time to NITZ
1007
1008            loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS,
1009                    R.integer.def_screen_brightness);
1010
1011            loadBooleanSetting(stmt, Settings.System.SCREEN_BRIGHTNESS_MODE,
1012                    R.bool.def_screen_brightness_automatic_mode);
1013
1014            loadDefaultAnimationSettings(stmt);
1015
1016            loadBooleanSetting(stmt, Settings.System.ACCELEROMETER_ROTATION,
1017                    R.bool.def_accelerometer_rotation);
1018
1019            loadDefaultHapticSettings(stmt);
1020
1021            loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
1022                    R.bool.def_notification_pulse);
1023            loadSetting(stmt, Settings.Secure.SET_INSTALL_LOCATION, 0);
1024            loadSetting(stmt, Settings.Secure.DEFAULT_INSTALL_LOCATION,
1025                    PackageHelper.APP_INSTALL_AUTO);
1026
1027            loadUISoundEffectsSettings(stmt);
1028
1029            loadBooleanSetting(stmt, Settings.System.VIBRATE_IN_SILENT,
1030                    R.bool.def_vibrate_in_silent);
1031        } finally {
1032            if (stmt != null) stmt.close();
1033        }
1034    }
1035
1036    private void loadUISoundEffectsSettings(SQLiteStatement stmt) {
1037        loadIntegerSetting(stmt, Settings.System.POWER_SOUNDS_ENABLED,
1038            R.integer.def_power_sounds_enabled);
1039        loadStringSetting(stmt, Settings.System.LOW_BATTERY_SOUND,
1040            R.string.def_low_battery_sound);
1041
1042        loadIntegerSetting(stmt, Settings.System.DOCK_SOUNDS_ENABLED,
1043            R.integer.def_dock_sounds_enabled);
1044        loadStringSetting(stmt, Settings.System.DESK_DOCK_SOUND,
1045            R.string.def_desk_dock_sound);
1046        loadStringSetting(stmt, Settings.System.DESK_UNDOCK_SOUND,
1047            R.string.def_desk_undock_sound);
1048        loadStringSetting(stmt, Settings.System.CAR_DOCK_SOUND,
1049            R.string.def_car_dock_sound);
1050        loadStringSetting(stmt, Settings.System.CAR_UNDOCK_SOUND,
1051            R.string.def_car_undock_sound);
1052
1053        loadIntegerSetting(stmt, Settings.System.LOCKSCREEN_SOUNDS_ENABLED,
1054            R.integer.def_lockscreen_sounds_enabled);
1055        loadStringSetting(stmt, Settings.System.LOCK_SOUND,
1056            R.string.def_lock_sound);
1057        loadStringSetting(stmt, Settings.System.UNLOCK_SOUND,
1058            R.string.def_unlock_sound);
1059    }
1060
1061    private void loadDefaultAnimationSettings(SQLiteStatement stmt) {
1062        loadFractionSetting(stmt, Settings.System.WINDOW_ANIMATION_SCALE,
1063                R.fraction.def_window_animation_scale, 1);
1064        loadFractionSetting(stmt, Settings.System.TRANSITION_ANIMATION_SCALE,
1065                R.fraction.def_window_transition_scale, 1);
1066    }
1067
1068    private void loadDefaultHapticSettings(SQLiteStatement stmt) {
1069        loadBooleanSetting(stmt, Settings.System.HAPTIC_FEEDBACK_ENABLED,
1070                R.bool.def_haptic_feedback);
1071    }
1072
1073    private void loadSecureSettings(SQLiteDatabase db) {
1074        SQLiteStatement stmt = null;
1075        try {
1076            stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
1077                    + " VALUES(?,?);");
1078
1079            loadBooleanSetting(stmt, Settings.Secure.BLUETOOTH_ON,
1080                    R.bool.def_bluetooth_on);
1081
1082            // Data roaming default, based on build
1083            loadSetting(stmt, Settings.Secure.DATA_ROAMING,
1084                    "true".equalsIgnoreCase(
1085                            SystemProperties.get("ro.com.android.dataroaming",
1086                                    "false")) ? 1 : 0);
1087
1088            loadBooleanSetting(stmt, Settings.Secure.INSTALL_NON_MARKET_APPS,
1089                    R.bool.def_install_non_market_apps);
1090
1091            loadStringSetting(stmt, Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
1092                    R.string.def_location_providers_allowed);
1093
1094            loadBooleanSetting(stmt, Settings.Secure.ASSISTED_GPS_ENABLED,
1095                    R.bool.assisted_gps_enabled);
1096
1097            loadIntegerSetting(stmt, Settings.Secure.NETWORK_PREFERENCE,
1098                    R.integer.def_network_preference);
1099
1100            loadBooleanSetting(stmt, Settings.Secure.USB_MASS_STORAGE_ENABLED,
1101                    R.bool.def_usb_mass_storage_enabled);
1102
1103            loadBooleanSetting(stmt, Settings.Secure.WIFI_ON,
1104                    R.bool.def_wifi_on);
1105            loadBooleanSetting(stmt, Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
1106                    R.bool.def_networks_available_notification_on);
1107
1108            String wifiWatchList = SystemProperties.get("ro.com.android.wifi-watchlist");
1109            if (!TextUtils.isEmpty(wifiWatchList)) {
1110                loadSetting(stmt, Settings.Secure.WIFI_WATCHDOG_WATCH_LIST, wifiWatchList);
1111            }
1112
1113            // Set the preferred network mode to 0 = Global, CDMA default
1114            int type = SystemProperties.getInt("ro.telephony.default_network",
1115                    RILConstants.PREFERRED_NETWORK_MODE);
1116            loadSetting(stmt, Settings.Secure.PREFERRED_NETWORK_MODE, type);
1117
1118            // Enable or disable Cell Broadcast SMS
1119            loadSetting(stmt, Settings.Secure.CDMA_CELL_BROADCAST_SMS,
1120                    RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED);
1121
1122            // Set the preferred cdma subscription to 0 = Subscription from RUIM, when available
1123            loadSetting(stmt, Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION,
1124                    RILConstants.PREFERRED_CDMA_SUBSCRIPTION);
1125
1126            // Don't do this.  The SystemServer will initialize ADB_ENABLED from a
1127            // persistent system property instead.
1128            //loadSetting(stmt, Settings.Secure.ADB_ENABLED, 0);
1129
1130            // Allow mock locations default, based on build
1131            loadSetting(stmt, Settings.Secure.ALLOW_MOCK_LOCATION,
1132                    "1".equals(SystemProperties.get("ro.allow.mock.location")) ? 1 : 0);
1133
1134            loadSecure35Settings(stmt);
1135
1136            loadBooleanSetting(stmt, Settings.Secure.MOUNT_PLAY_NOTIFICATION_SND,
1137                    R.bool.def_mount_play_notification_snd);
1138
1139            loadBooleanSetting(stmt, Settings.Secure.MOUNT_UMS_AUTOSTART,
1140                    R.bool.def_mount_ums_autostart);
1141
1142            loadBooleanSetting(stmt, Settings.Secure.MOUNT_UMS_PROMPT,
1143                    R.bool.def_mount_ums_prompt);
1144
1145            loadBooleanSetting(stmt, Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED,
1146                    R.bool.def_mount_ums_notify_enabled);
1147        } finally {
1148            if (stmt != null) stmt.close();
1149        }
1150    }
1151
1152    private void loadSecure35Settings(SQLiteStatement stmt) {
1153        loadBooleanSetting(stmt, Settings.Secure.BACKUP_ENABLED,
1154                R.bool.def_backup_enabled);
1155
1156        loadStringSetting(stmt, Settings.Secure.BACKUP_TRANSPORT,
1157                R.string.def_backup_transport);
1158    }
1159
1160    private void loadSetting(SQLiteStatement stmt, String key, Object value) {
1161        stmt.bindString(1, key);
1162        stmt.bindString(2, value.toString());
1163        stmt.execute();
1164    }
1165
1166    private void loadStringSetting(SQLiteStatement stmt, String key, int resid) {
1167        loadSetting(stmt, key, mContext.getResources().getString(resid));
1168    }
1169
1170    private void loadBooleanSetting(SQLiteStatement stmt, String key, int resid) {
1171        loadSetting(stmt, key,
1172                mContext.getResources().getBoolean(resid) ? "1" : "0");
1173    }
1174
1175    private void loadIntegerSetting(SQLiteStatement stmt, String key, int resid) {
1176        loadSetting(stmt, key,
1177                Integer.toString(mContext.getResources().getInteger(resid)));
1178    }
1179
1180    private void loadFractionSetting(SQLiteStatement stmt, String key, int resid, int base) {
1181        loadSetting(stmt, key,
1182                Float.toString(mContext.getResources().getFraction(resid, base, base)));
1183    }
1184}
1185