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