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