Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 624181af authored by Svetoslav Ganov's avatar Svetoslav Ganov Committed by Android (Google) Code Review
Browse files

Merge "Settings are restored in alphabetical order rather in order of...

Merge "Settings are restored in alphabetical order rather in order of dependency." into ics-factoryrom
parents 90fb9aa9 a571a583
Loading
Loading
Loading
Loading
+12 −1
Original line number Original line Diff line number Diff line
@@ -1882,6 +1882,11 @@ public final class Settings {
        /**
        /**
         * Settings to backup. This is here so that it's in the same place as the settings
         * Settings to backup. This is here so that it's in the same place as the settings
         * keys and easy to update.
         * keys and easy to update.
         *
         * NOTE: Settings are backed up and restored in the order they appear
         *       in this array. If you have one setting depending on another,
         *       make sure that they are ordered appropriately.
         *
         * @hide
         * @hide
         */
         */
        public static final String[] SETTINGS_TO_BACKUP = {
        public static final String[] SETTINGS_TO_BACKUP = {
@@ -4048,6 +4053,12 @@ public final class Settings {
        public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout";
        public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout";


        /**
        /**
         * This are the settings to be backed up.
         *
         * NOTE: Settings are backed up and restored in the order they appear
         *       in this array. If you have one setting depending on another,
         *       make sure that they are ordered appropriately.
         *
         * @hide
         * @hide
         */
         */
        public static final String[] SETTINGS_TO_BACKUP = {
        public static final String[] SETTINGS_TO_BACKUP = {
@@ -4056,11 +4067,11 @@ public final class Settings {
            PARENTAL_CONTROL_ENABLED,
            PARENTAL_CONTROL_ENABLED,
            PARENTAL_CONTROL_REDIRECT_URL,
            PARENTAL_CONTROL_REDIRECT_URL,
            USB_MASS_STORAGE_ENABLED,
            USB_MASS_STORAGE_ENABLED,
            ACCESSIBILITY_ENABLED,
            ACCESSIBILITY_SCRIPT_INJECTION,
            ACCESSIBILITY_SCRIPT_INJECTION,
            BACKUP_AUTO_RESTORE,
            BACKUP_AUTO_RESTORE,
            ENABLED_ACCESSIBILITY_SERVICES,
            ENABLED_ACCESSIBILITY_SERVICES,
            TOUCH_EXPLORATION_ENABLED,
            TOUCH_EXPLORATION_ENABLED,
            ACCESSIBILITY_ENABLED,
            TTS_USE_DEFAULTS,
            TTS_USE_DEFAULTS,
            TTS_DEFAULT_RATE,
            TTS_DEFAULT_RATE,
            TTS_DEFAULT_PITCH,
            TTS_DEFAULT_PITCH,
+125 −121
Original line number Original line Diff line number Diff line
@@ -16,6 +16,21 @@


package com.android.providers.settings;
package com.android.providers.settings;


import android.app.backup.BackupAgentHelper;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.FullBackupDataOutput;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.provider.Settings;
import android.util.Log;

import java.io.BufferedOutputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.BufferedWriter;
@@ -27,28 +42,13 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.IOException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.CRC32;
import java.util.zip.CRC32;


import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupAgentHelper;
import android.app.backup.FullBackupDataOutput;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;

/**
/**
 * Performs backup and restore of the System and Secure settings.
 * Performs backup and restore of the System and Secure settings.
 * List of settings that are backed up are stored in the Settings.java file
 * List of settings that are backed up are stored in the Settings.java file
@@ -79,8 +79,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
    // Versioning of the 'full backup' format
    // Versioning of the 'full backup' format
    private static final int FULL_BACKUP_VERSION = 1;
    private static final int FULL_BACKUP_VERSION = 1;


    private static String[] sortedSystemKeys = null;
    private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE;
    private static String[] sortedSecureKeys = null;


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


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


    @Override
    public void onCreate() {
    public void onCreate() {
        if (DEBUG_BACKUP) Log.d(TAG, "onCreate() invoked");
        if (DEBUG_BACKUP) Log.d(TAG, "onCreate() invoked");


@@ -348,26 +348,17 @@ public class SettingsBackupAgent extends BackupAgentHelper {
    }
    }


    private byte[] getSystemSettings() {
    private byte[] getSystemSettings() {
        Cursor sortedCursor = getContentResolver().query(Settings.System.CONTENT_URI, PROJECTION,
        Cursor cursor = getContentResolver().query(Settings.System.CONTENT_URI, PROJECTION, null,
                null, null, Settings.NameValueTable.NAME);
                null, null);
        // Copy and sort the array
        byte[] result = extractRelevantValues(cursor, Settings.System.SETTINGS_TO_BACKUP);
        if (sortedSystemKeys == null) {
        cursor.close();
            sortedSystemKeys = copyAndSort(Settings.System.SETTINGS_TO_BACKUP);
        }
        byte[] result = extractRelevantValues(sortedCursor, sortedSystemKeys);
        sortedCursor.close();
        return result;
        return result;
    }
    }


    private byte[] getSecureSettings() {
    private byte[] getSecureSettings() {
        Cursor sortedCursor = getContentResolver().query(Settings.Secure.CONTENT_URI, PROJECTION,
        Cursor cursor = getContentResolver().query(Settings.Secure.CONTENT_URI, PROJECTION, null,
                null, null, Settings.NameValueTable.NAME);
                null, null);
        // Copy and sort the array
        byte[] result = extractRelevantValues(cursor, Settings.Secure.SETTINGS_TO_BACKUP);
        if (sortedSecureKeys == null) {
            sortedSecureKeys = copyAndSort(Settings.Secure.SETTINGS_TO_BACKUP);
        }
        byte[] result = extractRelevantValues(sortedCursor, sortedSecureKeys);
        sortedCursor.close();
        return result;
        return result;
    }
    }


@@ -383,120 +374,133 @@ public class SettingsBackupAgent extends BackupAgentHelper {
    }
    }


    private void restoreSettings(byte[] settings, int bytes, Uri contentUri) {
    private void restoreSettings(byte[] settings, int bytes, Uri contentUri) {
        if (DEBUG) Log.i(TAG, "restoreSettings: " + contentUri);
        if (DEBUG) {
            Log.i(TAG, "restoreSettings: " + contentUri);
        }

        // Figure out the white list.
        String[] whitelist = null;
        String[] whitelist = null;
        if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
        if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
            whitelist = Settings.Secure.SETTINGS_TO_BACKUP;
            whitelist = Settings.Secure.SETTINGS_TO_BACKUP;
        } else if (contentUri.equals(Settings.System.CONTENT_URI)) {
        } else if (contentUri.equals(Settings.System.CONTENT_URI)) {
            whitelist = Settings.System.SETTINGS_TO_BACKUP;
            whitelist = Settings.System.SETTINGS_TO_BACKUP;
        } else {
            throw new IllegalArgumentException("Unknown URI: " + contentUri);
        }
        }


        ContentValues cv = new ContentValues(2);
        // Restore only the white list data.
        int pos = 0;
        int pos = 0;
        Map<String, String> cachedEntries = new HashMap<String, String>();
        ContentValues contentValues = new ContentValues(2);
        SettingsHelper settingsHelper = mSettingsHelper;

        final int whiteListSize = whitelist.length;
        for (int i = 0; i < whiteListSize; i++) {
            String key = whitelist[i];
            String value = cachedEntries.remove(key);

            // If the value not cached, let us look it up.
            if (value == null) {
                while (pos < bytes) {
                while (pos < bytes) {
                    int length = readInt(settings, pos);
                    int length = readInt(settings, pos);
            pos += 4;
                    pos += INTEGER_BYTE_COUNT;
            String settingName = length > 0? new String(settings, pos, length) : null;
                    String dataKey = length > 0 ? new String(settings, pos, length) : null;
                    pos += length;
                    pos += length;
                    length = readInt(settings, pos);
                    length = readInt(settings, pos);
            pos += 4;
                    pos += INTEGER_BYTE_COUNT;
            String settingValue = length > 0? new String(settings, pos, length) : null;
                    String dataValue = length > 0 ? new String(settings, pos, length) : null;
                    pos += length;
                    pos += length;
            if (!TextUtils.isEmpty(settingName) && !TextUtils.isEmpty(settingValue)) {
                    if (key.equals(dataKey)) {
                //Log.i(TAG, "Restore " + settingName + " = " + settingValue);
                        value = dataValue;

                        break;
                // Only restore settings in our list of known-acceptable data
                if (invalidSavedSetting(whitelist, settingName)) {
                    continue;
                }

                if (mSettingsHelper.restoreValue(settingName, settingValue)) {
                    cv.clear();
                    cv.put(Settings.NameValueTable.NAME, settingName);
                    cv.put(Settings.NameValueTable.VALUE, settingValue);
                    getContentResolver().insert(contentUri, cv);
                }
                    }
                    }
                    cachedEntries.put(dataKey, dataValue);
                }
                }
            }
            }


    // Returns 'true' if the given setting is one that we refuse to restore
            if (value == null) {
    private boolean invalidSavedSetting(String[] knownNames, String candidate) {
                continue;
        // no filter? allow everything
        if (knownNames == null) {
            return false;
            }
            }


        // whitelisted setting?  allow it
            if (settingsHelper.restoreValue(key, value)) {
        for (String name : knownNames) {
                contentValues.clear();
            if (name.equals(candidate)) {
                contentValues.put(Settings.NameValueTable.NAME, key);
                return false;
                contentValues.put(Settings.NameValueTable.VALUE, value);
            }
                getContentResolver().insert(contentUri, contentValues);
            }
            }


        // refuse everything else
            if (DEBUG) {
        if (DEBUG) Log.v(TAG, "Ignoring restore datum: " + candidate);
                Log.d(TAG, "Restored setting: " + key + "=" + value);
        return true;
            }
        }
        }

    private String[] copyAndSort(String[] keys) {
        String[] sortedKeys = new String[keys.length];
        System.arraycopy(keys, 0, sortedKeys, 0, keys.length);
        Arrays.sort(sortedKeys);
        return sortedKeys;
    }
    }


    /**
    /**
     * Given a cursor sorted by key name and a set of keys sorted by name,
     * Given a cursor and a set of keys, extract the required keys and
     * extract the required keys and values and write them to a byte array.
     * values and write them to a byte array.
     * @param sortedCursor
     *
     * @param sortedKeys
     * @param cursor A cursor with settings data.
     * @return
     * @param settings The settings to extract.
     * @return The byte array of extracted values.
     */
     */
    byte[] extractRelevantValues(Cursor sortedCursor, String[] sortedKeys) {
    private byte[] extractRelevantValues(Cursor cursor, String[] settings) {
        byte[][] values = new byte[sortedKeys.length * 2][]; // keys and values
        final int settingsCount = settings.length;
        if (!sortedCursor.moveToFirst()) {
        byte[][] values = new byte[settingsCount * 2][]; // keys and values
        if (!cursor.moveToFirst()) {
            Log.e(TAG, "Couldn't read from the cursor");
            Log.e(TAG, "Couldn't read from the cursor");
            return new byte[0];
            return new byte[0];
        }
        }
        int keyIndex = 0;

        // Obtain the relevant data in a temporary array.
        int totalSize = 0;
        int totalSize = 0;
        while (!sortedCursor.isAfterLast()) {
        int backedUpSettingIndex = 0;
            String name = sortedCursor.getString(COLUMN_NAME);
        Map<String, String> cachedEntries = new HashMap<String, String>();
            while (sortedKeys[keyIndex].compareTo(name.toString()) < 0) {
        for (int i = 0; i < settingsCount; i++) {
                keyIndex++;
            String key = settings[i];
                if (keyIndex == sortedKeys.length) break;
            String value = cachedEntries.remove(key);
            }

            if (keyIndex < sortedKeys.length && name.equals(sortedKeys[keyIndex])) {
            // If the value not cached, let us look it up.
                String value = sortedCursor.getString(COLUMN_VALUE);
            if (value == null) {
                byte[] nameBytes = name.toString().getBytes();
                while (!cursor.isAfterLast()) {
                totalSize += 4 + nameBytes.length;
                    String cursorKey = cursor.getString(COLUMN_NAME);
                values[keyIndex * 2] = nameBytes;
                    String cursorValue = cursor.getString(COLUMN_VALUE);
                byte[] valueBytes;
                    cursor.moveToNext();
                if (TextUtils.isEmpty(value)) {
                    if (key.equals(cursorKey)) {
                    valueBytes = null;
                        value = cursorValue;
                    totalSize += 4;
                        break;
                } else {
                    valueBytes = value.toString().getBytes();
                    totalSize += 4 + valueBytes.length;
                    //Log.i(TAG, "Backing up " + name + " = " + value);
                    }
                    }
                values[keyIndex * 2 + 1] = valueBytes;
                    cachedEntries.put(cursorKey, cursorValue);
                keyIndex++;
                }
                }
            if (keyIndex == sortedKeys.length || !sortedCursor.moveToNext()) {
                break;
            }
            }

            if (value == null) {
                continue;
            }
            }


            // Write the key and value in the intermediary array.
            byte[] keyBytes = key.getBytes();
            totalSize += INTEGER_BYTE_COUNT + keyBytes.length;
            values[backedUpSettingIndex * 2] = keyBytes;

            byte[] valueBytes = value.getBytes();
            totalSize += INTEGER_BYTE_COUNT + valueBytes.length;
            values[backedUpSettingIndex * 2 + 1] = valueBytes;

            backedUpSettingIndex++;

            if (DEBUG) {
                Log.d(TAG, "Backed up setting: " + key + "=" + value);
            }
        }

        // Aggregate the result.
        byte[] result = new byte[totalSize];
        byte[] result = new byte[totalSize];
        int pos = 0;
        int pos = 0;
        for (int i = 0; i < sortedKeys.length * 2; i++) {
        final int keyValuePairCount = backedUpSettingIndex * 2;
            if (values[i] != null) {
        for (int i = 0; i < keyValuePairCount; i++) {
            pos = writeInt(result, pos, values[i].length);
            pos = writeInt(result, pos, values[i].length);
            pos = writeBytes(result, pos, values[i]);
            pos = writeBytes(result, pos, values[i]);
        }
        }
        }
        return result;
        return result;
    }
    }


@@ -647,14 +651,14 @@ public class SettingsBackupAgent extends BackupAgentHelper {
     * @param out byte array
     * @param out byte array
     * @param pos current pos in array
     * @param pos current pos in array
     * @param value integer to write
     * @param value integer to write
     * @return the index after adding the size of an int (4)
     * @return the index after adding the size of an int (4) in bytes.
     */
     */
    private int writeInt(byte[] out, int pos, int value) {
    private int writeInt(byte[] out, int pos, int value) {
        out[pos + 0] = (byte) ((value >> 24) & 0xFF);
        out[pos + 0] = (byte) ((value >> 24) & 0xFF);
        out[pos + 1] = (byte) ((value >> 16) & 0xFF);
        out[pos + 1] = (byte) ((value >> 16) & 0xFF);
        out[pos + 2] = (byte) ((value >>  8) & 0xFF);
        out[pos + 2] = (byte) ((value >>  8) & 0xFF);
        out[pos + 3] = (byte) ((value >>  0) & 0xFF);
        out[pos + 3] = (byte) ((value >>  0) & 0xFF);
        return pos + 4;
        return pos + INTEGER_BYTE_COUNT;
    }
    }


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