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