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