diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java index 78f6ace3c53bf..eac83d8e2563e 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java @@ -32,14 +32,18 @@ import android.os.FileUtils; import android.os.Handler; import android.os.ParcelFileDescriptor; import android.os.Process; +import android.os.UserHandle; import android.provider.Settings; import android.util.Log; +import com.android.internal.widget.LockPatternUtils; + import libcore.io.IoUtils; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.CharArrayReader; import java.io.DataInputStream; @@ -76,10 +80,11 @@ public class SettingsBackupAgent extends BackupAgentHelper { private static final String KEY_SECURE = "secure"; private static final String KEY_GLOBAL = "global"; private static final String KEY_LOCALE = "locale"; + private static final String KEY_LOCK_SETTINGS = "lock_settings"; // Versioning of the state file. Increment this version // number any time the set of state items is altered. - private static final int STATE_VERSION = 3; + private static final int STATE_VERSION = 4; // Slots in the checksum array. Never insert new items in the middle // of this array; new slots must be appended. @@ -89,20 +94,23 @@ public class SettingsBackupAgent extends BackupAgentHelper { private static final int STATE_WIFI_SUPPLICANT = 3; private static final int STATE_WIFI_CONFIG = 4; private static final int STATE_GLOBAL = 5; + private static final int STATE_LOCK_SETTINGS = 6; - private static final int STATE_SIZE = 6; // The current number of state items + private static final int STATE_SIZE = 7; // The current number of state items // Number of entries in the checksum array at various version numbers private static final int STATE_SIZES[] = { 0, 4, // version 1 5, // version 2 added STATE_WIFI_CONFIG - STATE_SIZE // version 3 added STATE_GLOBAL + 6, // version 3 added STATE_GLOBAL + STATE_SIZE // version 4 added STATE_LOCK_SETTINGS }; // Versioning of the 'full backup' format - private static final int FULL_BACKUP_VERSION = 2; + private static final int FULL_BACKUP_VERSION = 3; private static final int FULL_BACKUP_ADDED_GLOBAL = 2; // added the "global" entry + private static final int FULL_BACKUP_ADDED_LOCK_SETTINGS = 3; // added the "lock_settings" entry private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE; @@ -124,6 +132,10 @@ public class SettingsBackupAgent extends BackupAgentHelper { private static final String KEY_WIFI_SUPPLICANT = "\uffedWIFI"; private static final String KEY_WIFI_CONFIG = "\uffedCONFIG_WIFI"; + // Keys within the lock settings section + private static final String KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED = "owner_info_enabled"; + private static final String KEY_LOCK_SETTINGS_OWNER_INFO = "owner_info"; + // Name of the temporary file we use during full backup/restore. This is // stored in the full-backup tarfile as well, so should not be changed. private static final String STAGE_FILE = "flattened-data"; @@ -367,6 +379,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { byte[] systemSettingsData = getSystemSettings(); byte[] secureSettingsData = getSecureSettings(); byte[] globalSettingsData = getGlobalSettings(); + byte[] lockSettingsData = getLockSettings(); byte[] locale = mSettingsHelper.getLocaleData(); byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT); byte[] wifiConfigData = getFileData(mWifiConfigFile); @@ -387,6 +400,9 @@ public class SettingsBackupAgent extends BackupAgentHelper { stateChecksums[STATE_WIFI_CONFIG] = writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData, data); + stateChecksums[STATE_LOCK_SETTINGS] = + writeIfChanged(stateChecksums[STATE_LOCK_SETTINGS], KEY_LOCK_SETTINGS, + lockSettingsData, data); writeNewChecksums(stateChecksums, newState); } @@ -492,6 +508,8 @@ public class SettingsBackupAgent extends BackupAgentHelper { } else if (KEY_WIFI_CONFIG.equals(key)) { initWifiRestoreIfNecessary(); mWifiRestore.incorporateWifiConfigFile(data); + } else if (KEY_LOCK_SETTINGS.equals(key)) { + restoreLockSettings(data); } else { data.skipEntityData(); } @@ -513,6 +531,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { byte[] systemSettingsData = getSystemSettings(); byte[] secureSettingsData = getSecureSettings(); byte[] globalSettingsData = getGlobalSettings(); + byte[] lockSettingsData = getLockSettings(); byte[] locale = mSettingsHelper.getLocaleData(); byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT); byte[] wifiConfigData = getFileData(mWifiConfigFile); @@ -547,6 +566,9 @@ public class SettingsBackupAgent extends BackupAgentHelper { if (DEBUG_BACKUP) Log.d(TAG, wifiConfigData.length + " bytes of wifi config data"); out.writeInt(wifiConfigData.length); out.write(wifiConfigData); + if (DEBUG_BACKUP) Log.d(TAG, lockSettingsData.length + " bytes of lock settings data"); + out.writeInt(lockSettingsData.length); + out.write(lockSettingsData); out.flush(); // also flushes downstream @@ -629,6 +651,16 @@ public class SettingsBackupAgent extends BackupAgentHelper { in.readFully(buffer, 0, nBytes); restoreFileData(mWifiConfigFile, buffer, nBytes); + if (version >= FULL_BACKUP_ADDED_LOCK_SETTINGS) { + nBytes = in.readInt(); + if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of lock settings data"); + if (nBytes > buffer.length) buffer = new byte[nBytes]; + if (nBytes > 0) { + in.readFully(buffer, 0, nBytes); + restoreLockSettings(buffer, nBytes); + } + } + if (DEBUG_BACKUP) Log.d(TAG, "Full restore complete."); } else { data.close(); @@ -676,6 +708,9 @@ public class SettingsBackupAgent extends BackupAgentHelper { return oldChecksum; } try { + if (DEBUG_BACKUP) { + Log.v(TAG, "Writing entity " + key + " of size " + data.length); + } output.writeEntityHeader(key, data.length); output.writeEntityData(data, data.length); } catch (IOException ioe) { @@ -714,6 +749,31 @@ public class SettingsBackupAgent extends BackupAgentHelper { } } + /** + * Serialize the owner info settings + */ + private byte[] getLockSettings() { + final LockPatternUtils lockPatternUtils = new LockPatternUtils(this); + final boolean ownerInfoEnabled = lockPatternUtils.isOwnerInfoEnabled(); + final String ownerInfo = lockPatternUtils.getOwnerInfo(UserHandle.myUserId()); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream out = new DataOutputStream(baos); + try { + out.writeUTF(KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED); + out.writeUTF(ownerInfoEnabled ? "1" : "0"); + if (ownerInfo != null) { + out.writeUTF(KEY_LOCK_SETTINGS_OWNER_INFO); + out.writeUTF(ownerInfo != null ? ownerInfo : ""); + } + // End marker + out.writeUTF(""); + out.flush(); + } catch (IOException ioe) { + } + return baos.toByteArray(); + } + private void restoreSettings(BackupDataInput data, Uri contentUri, HashSet movedToGlobal) { byte[] settings = new byte[data.getDataSize()]; @@ -796,6 +856,50 @@ public class SettingsBackupAgent extends BackupAgentHelper { } } + /** + * Restores the owner info enabled and owner info settings in LockSettings. + * + * @param buffer + * @param nBytes + */ + private void restoreLockSettings(byte[] buffer, int nBytes) { + final LockPatternUtils lockPatternUtils = new LockPatternUtils(this); + + ByteArrayInputStream bais = new ByteArrayInputStream(buffer, 0, nBytes); + DataInputStream in = new DataInputStream(bais); + try { + String key; + // Read until empty string marker + while ((key = in.readUTF()).length() > 0) { + final String value = in.readUTF(); + if (DEBUG_BACKUP) { + Log.v(TAG, "Restoring lock_settings " + key + " = " + value); + } + switch (key) { + case KEY_LOCK_SETTINGS_OWNER_INFO_ENABLED: + lockPatternUtils.setOwnerInfoEnabled("1".equals(value)); + break; + case KEY_LOCK_SETTINGS_OWNER_INFO: + lockPatternUtils.setOwnerInfo(value, UserHandle.myUserId()); + break; + } + } + in.close(); + } catch (IOException ioe) { + } + } + + private void restoreLockSettings(BackupDataInput data) { + final byte[] settings = new byte[data.getDataSize()]; + try { + data.readEntityData(settings, 0, settings.length); + } catch (IOException ioe) { + Log.e(TAG, "Couldn't read entity data"); + return; + } + restoreLockSettings(settings, settings.length); + } + /** * Given a cursor and a set of keys, extract the required keys and * values and write them to a byte array. diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index 77b8b31d43eb7..895a5c3a6799f 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -17,6 +17,7 @@ package com.android.server; import android.app.admin.DevicePolicyManager; +import android.app.backup.BackupManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -46,6 +47,7 @@ import android.security.KeyStore; import android.text.TextUtils; import android.util.Slog; +import com.android.internal.util.ArrayUtils; import com.android.internal.widget.ILockSettings; import com.android.internal.widget.LockPatternUtils; @@ -257,6 +259,9 @@ public class LockSettingsService extends ILockSettings.Stub { private void setStringUnchecked(String key, int userId, String value) { mStorage.writeKeyValue(key, value, userId); + if (ArrayUtils.contains(SETTINGS_TO_BACKUP, key)) { + BackupManager.dataChanged("com.android.providers.settings"); + } } @Override @@ -463,6 +468,11 @@ public class LockSettingsService extends ILockSettings.Stub { Secure.LOCK_SCREEN_OWNER_INFO }; + private static final String[] SETTINGS_TO_BACKUP = new String[] { + Secure.LOCK_SCREEN_OWNER_INFO_ENABLED, + Secure.LOCK_SCREEN_OWNER_INFO + }; + private IMountService getMountService() { final IBinder service = ServiceManager.getService("mount"); if (service != null) {