Skip to content

Commit 624181a

Browse files
sganovAndroid (Google) Code Review
authored andcommitted
Merge "Settings are restored in alphabetical order rather in order of dependency." into ics-factoryrom
2 parents 90fb9aa + a571a58 commit 624181a

2 files changed

Lines changed: 137 additions & 122 deletions

File tree

core/java/android/provider/Settings.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1882,6 +1882,11 @@ public static void setShowGTalkServiceStatus(ContentResolver cr, boolean flag) {
18821882
/**
18831883
* Settings to backup. This is here so that it's in the same place as the settings
18841884
* keys and easy to update.
1885+
*
1886+
* NOTE: Settings are backed up and restored in the order they appear
1887+
* in this array. If you have one setting depending on another,
1888+
* make sure that they are ordered appropriately.
1889+
*
18851890
* @hide
18861891
*/
18871892
public static final String[] SETTINGS_TO_BACKUP = {
@@ -4048,6 +4053,12 @@ public static final String getBluetoothInputDevicePriorityKey(String address) {
40484053
public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout";
40494054

40504055
/**
4056+
* This are the settings to be backed up.
4057+
*
4058+
* NOTE: Settings are backed up and restored in the order they appear
4059+
* in this array. If you have one setting depending on another,
4060+
* make sure that they are ordered appropriately.
4061+
*
40514062
* @hide
40524063
*/
40534064
public static final String[] SETTINGS_TO_BACKUP = {
@@ -4056,11 +4067,11 @@ public static final String getBluetoothInputDevicePriorityKey(String address) {
40564067
PARENTAL_CONTROL_ENABLED,
40574068
PARENTAL_CONTROL_REDIRECT_URL,
40584069
USB_MASS_STORAGE_ENABLED,
4059-
ACCESSIBILITY_ENABLED,
40604070
ACCESSIBILITY_SCRIPT_INJECTION,
40614071
BACKUP_AUTO_RESTORE,
40624072
ENABLED_ACCESSIBILITY_SERVICES,
40634073
TOUCH_EXPLORATION_ENABLED,
4074+
ACCESSIBILITY_ENABLED,
40644075
TTS_USE_DEFAULTS,
40654076
TTS_DEFAULT_RATE,
40664077
TTS_DEFAULT_PITCH,

packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java

Lines changed: 125 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,21 @@
1616

1717
package com.android.providers.settings;
1818

19+
import android.app.backup.BackupAgentHelper;
20+
import android.app.backup.BackupDataInput;
21+
import android.app.backup.BackupDataOutput;
22+
import android.app.backup.FullBackupDataOutput;
23+
import android.content.ContentValues;
24+
import android.content.Context;
25+
import android.database.Cursor;
26+
import android.net.Uri;
27+
import android.net.wifi.WifiManager;
28+
import android.os.FileUtils;
29+
import android.os.ParcelFileDescriptor;
30+
import android.os.Process;
31+
import android.provider.Settings;
32+
import android.util.Log;
33+
1934
import java.io.BufferedOutputStream;
2035
import java.io.BufferedReader;
2136
import java.io.BufferedWriter;
@@ -27,28 +42,13 @@
2742
import java.io.FileOutputStream;
2843
import java.io.FileReader;
2944
import java.io.FileWriter;
30-
import java.io.InputStream;
3145
import java.io.IOException;
46+
import java.io.InputStream;
3247
import java.io.OutputStream;
33-
import java.util.Arrays;
48+
import java.util.HashMap;
49+
import java.util.Map;
3450
import java.util.zip.CRC32;
3551

36-
import android.app.backup.BackupDataInput;
37-
import android.app.backup.BackupDataOutput;
38-
import android.app.backup.BackupAgentHelper;
39-
import android.app.backup.FullBackupDataOutput;
40-
import android.content.ContentValues;
41-
import android.content.Context;
42-
import android.database.Cursor;
43-
import android.net.Uri;
44-
import android.net.wifi.WifiManager;
45-
import android.os.FileUtils;
46-
import android.os.ParcelFileDescriptor;
47-
import android.os.Process;
48-
import android.provider.Settings;
49-
import android.text.TextUtils;
50-
import android.util.Log;
51-
5252
/**
5353
* Performs backup and restore of the System and Secure settings.
5454
* List of settings that are backed up are stored in the Settings.java file
@@ -79,8 +79,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
7979
// Versioning of the 'full backup' format
8080
private static final int FULL_BACKUP_VERSION = 1;
8181

82-
private static String[] sortedSystemKeys = null;
83-
private static String[] sortedSecureKeys = null;
82+
private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE;
8483

8584
private static final byte[] EMPTY_DATA = new byte[0];
8685

@@ -112,6 +111,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
112111
private WifiManager mWfm;
113112
private static String mWifiConfigFile;
114113

114+
@Override
115115
public void onCreate() {
116116
if (DEBUG_BACKUP) Log.d(TAG, "onCreate() invoked");
117117

@@ -348,26 +348,17 @@ private long writeIfChanged(long oldChecksum, String key, byte[] data,
348348
}
349349

350350
private byte[] getSystemSettings() {
351-
Cursor sortedCursor = getContentResolver().query(Settings.System.CONTENT_URI, PROJECTION,
352-
null, null, Settings.NameValueTable.NAME);
353-
// Copy and sort the array
354-
if (sortedSystemKeys == null) {
355-
sortedSystemKeys = copyAndSort(Settings.System.SETTINGS_TO_BACKUP);
356-
}
357-
byte[] result = extractRelevantValues(sortedCursor, sortedSystemKeys);
358-
sortedCursor.close();
351+
Cursor cursor = getContentResolver().query(Settings.System.CONTENT_URI, PROJECTION, null,
352+
null, null);
353+
byte[] result = extractRelevantValues(cursor, Settings.System.SETTINGS_TO_BACKUP);
354+
cursor.close();
359355
return result;
360356
}
361357

362358
private byte[] getSecureSettings() {
363-
Cursor sortedCursor = getContentResolver().query(Settings.Secure.CONTENT_URI, PROJECTION,
364-
null, null, Settings.NameValueTable.NAME);
365-
// Copy and sort the array
366-
if (sortedSecureKeys == null) {
367-
sortedSecureKeys = copyAndSort(Settings.Secure.SETTINGS_TO_BACKUP);
368-
}
369-
byte[] result = extractRelevantValues(sortedCursor, sortedSecureKeys);
370-
sortedCursor.close();
359+
Cursor cursor = getContentResolver().query(Settings.Secure.CONTENT_URI, PROJECTION, null,
360+
null, null);
361+
byte[] result = extractRelevantValues(cursor, Settings.Secure.SETTINGS_TO_BACKUP);
371362
return result;
372363
}
373364

@@ -383,119 +374,132 @@ private void restoreSettings(BackupDataInput data, Uri contentUri) {
383374
}
384375

385376
private void restoreSettings(byte[] settings, int bytes, Uri contentUri) {
386-
if (DEBUG) Log.i(TAG, "restoreSettings: " + contentUri);
377+
if (DEBUG) {
378+
Log.i(TAG, "restoreSettings: " + contentUri);
379+
}
380+
381+
// Figure out the white list.
387382
String[] whitelist = null;
388383
if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
389384
whitelist = Settings.Secure.SETTINGS_TO_BACKUP;
390385
} else if (contentUri.equals(Settings.System.CONTENT_URI)) {
391386
whitelist = Settings.System.SETTINGS_TO_BACKUP;
387+
} else {
388+
throw new IllegalArgumentException("Unknown URI: " + contentUri);
392389
}
393390

394-
ContentValues cv = new ContentValues(2);
391+
// Restore only the white list data.
395392
int pos = 0;
396-
while (pos < bytes) {
397-
int length = readInt(settings, pos);
398-
pos += 4;
399-
String settingName = length > 0? new String(settings, pos, length) : null;
400-
pos += length;
401-
length = readInt(settings, pos);
402-
pos += 4;
403-
String settingValue = length > 0? new String(settings, pos, length) : null;
404-
pos += length;
405-
if (!TextUtils.isEmpty(settingName) && !TextUtils.isEmpty(settingValue)) {
406-
//Log.i(TAG, "Restore " + settingName + " = " + settingValue);
407-
408-
// Only restore settings in our list of known-acceptable data
409-
if (invalidSavedSetting(whitelist, settingName)) {
410-
continue;
393+
Map<String, String> cachedEntries = new HashMap<String, String>();
394+
ContentValues contentValues = new ContentValues(2);
395+
SettingsHelper settingsHelper = mSettingsHelper;
396+
397+
final int whiteListSize = whitelist.length;
398+
for (int i = 0; i < whiteListSize; i++) {
399+
String key = whitelist[i];
400+
String value = cachedEntries.remove(key);
401+
402+
// If the value not cached, let us look it up.
403+
if (value == null) {
404+
while (pos < bytes) {
405+
int length = readInt(settings, pos);
406+
pos += INTEGER_BYTE_COUNT;
407+
String dataKey = length > 0 ? new String(settings, pos, length) : null;
408+
pos += length;
409+
length = readInt(settings, pos);
410+
pos += INTEGER_BYTE_COUNT;
411+
String dataValue = length > 0 ? new String(settings, pos, length) : null;
412+
pos += length;
413+
if (key.equals(dataKey)) {
414+
value = dataValue;
415+
break;
416+
}
417+
cachedEntries.put(dataKey, dataValue);
411418
}
419+
}
412420

413-
if (mSettingsHelper.restoreValue(settingName, settingValue)) {
414-
cv.clear();
415-
cv.put(Settings.NameValueTable.NAME, settingName);
416-
cv.put(Settings.NameValueTable.VALUE, settingValue);
417-
getContentResolver().insert(contentUri, cv);
418-
}
421+
if (value == null) {
422+
continue;
419423
}
420-
}
421-
}
422424

423-
// Returns 'true' if the given setting is one that we refuse to restore
424-
private boolean invalidSavedSetting(String[] knownNames, String candidate) {
425-
// no filter? allow everything
426-
if (knownNames == null) {
427-
return false;
428-
}
425+
if (settingsHelper.restoreValue(key, value)) {
426+
contentValues.clear();
427+
contentValues.put(Settings.NameValueTable.NAME, key);
428+
contentValues.put(Settings.NameValueTable.VALUE, value);
429+
getContentResolver().insert(contentUri, contentValues);
430+
}
429431

430-
// whitelisted setting? allow it
431-
for (String name : knownNames) {
432-
if (name.equals(candidate)) {
433-
return false;
432+
if (DEBUG) {
433+
Log.d(TAG, "Restored setting: " + key + "=" + value);
434434
}
435435
}
436-
437-
// refuse everything else
438-
if (DEBUG) Log.v(TAG, "Ignoring restore datum: " + candidate);
439-
return true;
440-
}
441-
442-
private String[] copyAndSort(String[] keys) {
443-
String[] sortedKeys = new String[keys.length];
444-
System.arraycopy(keys, 0, sortedKeys, 0, keys.length);
445-
Arrays.sort(sortedKeys);
446-
return sortedKeys;
447436
}
448437

449438
/**
450-
* Given a cursor sorted by key name and a set of keys sorted by name,
451-
* extract the required keys and values and write them to a byte array.
452-
* @param sortedCursor
453-
* @param sortedKeys
454-
* @return
439+
* Given a cursor and a set of keys, extract the required keys and
440+
* values and write them to a byte array.
441+
*
442+
* @param cursor A cursor with settings data.
443+
* @param settings The settings to extract.
444+
* @return The byte array of extracted values.
455445
*/
456-
byte[] extractRelevantValues(Cursor sortedCursor, String[] sortedKeys) {
457-
byte[][] values = new byte[sortedKeys.length * 2][]; // keys and values
458-
if (!sortedCursor.moveToFirst()) {
446+
private byte[] extractRelevantValues(Cursor cursor, String[] settings) {
447+
final int settingsCount = settings.length;
448+
byte[][] values = new byte[settingsCount * 2][]; // keys and values
449+
if (!cursor.moveToFirst()) {
459450
Log.e(TAG, "Couldn't read from the cursor");
460451
return new byte[0];
461452
}
462-
int keyIndex = 0;
453+
454+
// Obtain the relevant data in a temporary array.
463455
int totalSize = 0;
464-
while (!sortedCursor.isAfterLast()) {
465-
String name = sortedCursor.getString(COLUMN_NAME);
466-
while (sortedKeys[keyIndex].compareTo(name.toString()) < 0) {
467-
keyIndex++;
468-
if (keyIndex == sortedKeys.length) break;
469-
}
470-
if (keyIndex < sortedKeys.length && name.equals(sortedKeys[keyIndex])) {
471-
String value = sortedCursor.getString(COLUMN_VALUE);
472-
byte[] nameBytes = name.toString().getBytes();
473-
totalSize += 4 + nameBytes.length;
474-
values[keyIndex * 2] = nameBytes;
475-
byte[] valueBytes;
476-
if (TextUtils.isEmpty(value)) {
477-
valueBytes = null;
478-
totalSize += 4;
479-
} else {
480-
valueBytes = value.toString().getBytes();
481-
totalSize += 4 + valueBytes.length;
482-
//Log.i(TAG, "Backing up " + name + " = " + value);
456+
int backedUpSettingIndex = 0;
457+
Map<String, String> cachedEntries = new HashMap<String, String>();
458+
for (int i = 0; i < settingsCount; i++) {
459+
String key = settings[i];
460+
String value = cachedEntries.remove(key);
461+
462+
// If the value not cached, let us look it up.
463+
if (value == null) {
464+
while (!cursor.isAfterLast()) {
465+
String cursorKey = cursor.getString(COLUMN_NAME);
466+
String cursorValue = cursor.getString(COLUMN_VALUE);
467+
cursor.moveToNext();
468+
if (key.equals(cursorKey)) {
469+
value = cursorValue;
470+
break;
471+
}
472+
cachedEntries.put(cursorKey, cursorValue);
483473
}
484-
values[keyIndex * 2 + 1] = valueBytes;
485-
keyIndex++;
486474
}
487-
if (keyIndex == sortedKeys.length || !sortedCursor.moveToNext()) {
488-
break;
475+
476+
if (value == null) {
477+
continue;
478+
}
479+
480+
// Write the key and value in the intermediary array.
481+
byte[] keyBytes = key.getBytes();
482+
totalSize += INTEGER_BYTE_COUNT + keyBytes.length;
483+
values[backedUpSettingIndex * 2] = keyBytes;
484+
485+
byte[] valueBytes = value.getBytes();
486+
totalSize += INTEGER_BYTE_COUNT + valueBytes.length;
487+
values[backedUpSettingIndex * 2 + 1] = valueBytes;
488+
489+
backedUpSettingIndex++;
490+
491+
if (DEBUG) {
492+
Log.d(TAG, "Backed up setting: " + key + "=" + value);
489493
}
490494
}
491495

496+
// Aggregate the result.
492497
byte[] result = new byte[totalSize];
493498
int pos = 0;
494-
for (int i = 0; i < sortedKeys.length * 2; i++) {
495-
if (values[i] != null) {
496-
pos = writeInt(result, pos, values[i].length);
497-
pos = writeBytes(result, pos, values[i]);
498-
}
499+
final int keyValuePairCount = backedUpSettingIndex * 2;
500+
for (int i = 0; i < keyValuePairCount; i++) {
501+
pos = writeInt(result, pos, values[i].length);
502+
pos = writeBytes(result, pos, values[i]);
499503
}
500504
return result;
501505
}
@@ -647,14 +651,14 @@ private void copyWifiSupplicantTemplate() {
647651
* @param out byte array
648652
* @param pos current pos in array
649653
* @param value integer to write
650-
* @return the index after adding the size of an int (4)
654+
* @return the index after adding the size of an int (4) in bytes.
651655
*/
652656
private int writeInt(byte[] out, int pos, int value) {
653657
out[pos + 0] = (byte) ((value >> 24) & 0xFF);
654658
out[pos + 1] = (byte) ((value >> 16) & 0xFF);
655659
out[pos + 2] = (byte) ((value >> 8) & 0xFF);
656660
out[pos + 3] = (byte) ((value >> 0) & 0xFF);
657-
return pos + 4;
661+
return pos + INTEGER_BYTE_COUNT;
658662
}
659663

660664
private int writeBytes(byte[] out, int pos, byte[] value) {

0 commit comments

Comments
 (0)