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