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

Commit df8e00ff authored by Svetoslav Ganov's avatar Svetoslav Ganov Committed by Android Git Automerger
Browse files

am 624181af: Merge "Settings are restored in alphabetical order rather in...

am 624181af: Merge "Settings are restored in alphabetical order rather in order of dependency." into ics-factoryrom

* commit '624181af':
  Settings are restored in alphabetical order rather in order of dependency.
parents a0c7ec2b 624181af
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) {