diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java index f8fb1e5794461..702c9bb4aa752 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java @@ -28,12 +28,9 @@ import android.net.NetworkPolicy; import android.net.NetworkPolicyManager; import android.net.Uri; import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiConfiguration.KeyMgmt; import android.net.wifi.WifiManager; -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.BackupUtils; @@ -41,34 +38,19 @@ 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; import java.io.DataOutputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.BitSet; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.zip.CRC32; /** @@ -86,10 +68,11 @@ public class SettingsBackupAgent extends BackupAgentHelper { private static final String KEY_LOCK_SETTINGS = "lock_settings"; private static final String KEY_SOFTAP_CONFIG = "softap_config"; private static final String KEY_NETWORK_POLICIES = "network_policies"; + private static final String KEY_WIFI_NEW_CONFIG = "wifi_new_config"; // Versioning of the state file. Increment this version // number any time the set of state items is altered. - private static final int STATE_VERSION = 6; + private static final int STATE_VERSION = 7; // Versioning of the Network Policies backup payload. private static final int NETWORK_POLICIES_BACKUP_VERSION = 1; @@ -106,8 +89,9 @@ public class SettingsBackupAgent extends BackupAgentHelper { private static final int STATE_LOCK_SETTINGS = 6; private static final int STATE_SOFTAP_CONFIG = 7; private static final int STATE_NETWORK_POLICIES = 8; + private static final int STATE_WIFI_NEW_CONFIG = 9; - private static final int STATE_SIZE = 9; // The current number of state items + private static final int STATE_SIZE = 10; // The current number of state items // Number of entries in the checksum array at various version numbers private static final int STATE_SIZES[] = { @@ -117,16 +101,18 @@ public class SettingsBackupAgent extends BackupAgentHelper { 6, // version 3 added STATE_GLOBAL 7, // version 4 added STATE_LOCK_SETTINGS 8, // version 5 added STATE_SOFTAP_CONFIG - STATE_SIZE // version 6 added STATE_NETWORK_POLICIES + 9, // version 6 added STATE_NETWORK_POLICIES + STATE_SIZE // version 7 added STATE_WIFI_NEW_CONFIG }; // Versioning of the 'full backup' format // Increment this version any time a new item is added - private static final int FULL_BACKUP_VERSION = 5; + private static final int FULL_BACKUP_VERSION = 6; 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 FULL_BACKUP_ADDED_SOFTAP_CONF = 4; //added the "softap_config" entry private static final int FULL_BACKUP_ADDED_NETWORK_POLICIES = 5; //added "network_policies" + private static final int FULL_BACKUP_ADDED_WIFI_NEW = 6; // added "wifi_new_config" entry private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE; @@ -139,10 +125,6 @@ public class SettingsBackupAgent extends BackupAgentHelper { Settings.NameValueTable.VALUE }; - private static final String FILE_WIFI_SUPPLICANT = "/data/misc/wifi/wpa_supplicant.conf"; - private static final String FILE_WIFI_SUPPLICANT_TEMPLATE = - "/system/etc/wifi/wpa_supplicant.conf"; - // the key to store the WIFI data under, should be sorted as last, so restore happens last. // use very late unicode character to quasi-guarantee last sort position. private static final String KEY_WIFI_SUPPLICANT = "\uffedWIFI"; @@ -156,259 +138,17 @@ public class SettingsBackupAgent extends BackupAgentHelper { // stored in the full-backup tarfile as well, so should not be changed. private static final String STAGE_FILE = "flattened-data"; - // Delay in milliseconds between the restore operation and when we will bounce - // wifi in order to rewrite the supplicant config etc. - private static final long WIFI_BOUNCE_DELAY_MILLIS = 60 * 1000; // one minute - private SettingsHelper mSettingsHelper; - private WifiManager mWfm; - private String mWifiConfigFile; - // Chain of asynchronous operations used when rewriting the wifi supplicant config file - WifiDisableRunnable mWifiDisable = null; - WifiRestoreRunnable mWifiRestore = null; - int mRetainedWifiState; // used only during config file rewrite - - // Class for capturing a network definition from the wifi supplicant config file - static class Network { - String ssid = ""; // equals() and hashCode() need these to be non-null - String key_mgmt = ""; - boolean certUsed = false; - boolean hasWepKey = false; - boolean isEap = false; - final ArrayList rawLines = new ArrayList(); - - public static Network readFromStream(BufferedReader in) { - final Network n = new Network(); - String line; - try { - while (in.ready()) { - line = in.readLine(); - if (line == null || line.startsWith("}")) { - break; - } - n.rememberLine(line); - } - } catch (IOException e) { - return null; - } - return n; - } - - void rememberLine(String line) { - // can't rely on particular whitespace patterns so strip leading/trailing - line = line.trim(); - if (line.isEmpty()) return; // only whitespace; drop the line - rawLines.add(line); - - // remember the ssid and key_mgmt lines for duplicate culling - if (line.startsWith("ssid=")) { - ssid = line; - } else if (line.startsWith("key_mgmt=")) { - key_mgmt = line; - if (line.contains("EAP")) { - isEap = true; - } - } else if (line.startsWith("client_cert=")) { - certUsed = true; - } else if (line.startsWith("ca_cert=")) { - certUsed = true; - } else if (line.startsWith("ca_path=")) { - certUsed = true; - } else if (line.startsWith("wep_")) { - hasWepKey = true; - } else if (line.startsWith("eap=")) { - isEap = true; - } - } - - public void write(Writer w) throws IOException { - w.write("\nnetwork={\n"); - for (String line : rawLines) { - w.write("\t" + line + "\n"); - } - w.write("}\n"); - } - - public void dump() { - Log.v(TAG, "network={"); - for (String line : rawLines) { - Log.v(TAG, " " + line); - } - Log.v(TAG, "}"); - } - - // Calculate the equivalent of WifiConfiguration's configKey() - public String configKey() { - if (ssid == null) { - // No SSID => malformed network definition - return null; - } - - final String bareSsid = ssid.substring(ssid.indexOf('=') + 1); - - final BitSet types = new BitSet(); - if (key_mgmt == null) { - // no key_mgmt specified; this is defined as equivalent to "WPA-PSK WPA-EAP" - types.set(KeyMgmt.WPA_PSK); - types.set(KeyMgmt.WPA_EAP); - } else { - // Need to parse the key_mgmt line - final String bareKeyMgmt = key_mgmt.substring(key_mgmt.indexOf('=') + 1); - String[] typeStrings = bareKeyMgmt.split("\\s+"); - - // Parse out all the key management regimes permitted for this network. The literal - // strings here are the standard values permitted in wpa_supplicant.conf. - for (int i = 0; i < typeStrings.length; i++) { - final String ktype = typeStrings[i]; - if (ktype.equals("WPA-PSK")) { - Log.v(TAG, " + setting WPA_PSK bit"); - types.set(KeyMgmt.WPA_PSK); - } else if (ktype.equals("WPA-EAP")) { - Log.v(TAG, " + setting WPA_EAP bit"); - types.set(KeyMgmt.WPA_EAP); - } else if (ktype.equals("IEEE8021X")) { - Log.v(TAG, " + setting IEEE8021X bit"); - types.set(KeyMgmt.IEEE8021X); - } - } - } - - // Now build the canonical config key paralleling the WifiConfiguration semantics - final String key; - if (types.get(KeyMgmt.WPA_PSK)) { - key = bareSsid + KeyMgmt.strings[KeyMgmt.WPA_PSK]; - } else if (types.get(KeyMgmt.WPA_EAP) || types.get(KeyMgmt.IEEE8021X)) { - key = bareSsid + KeyMgmt.strings[KeyMgmt.WPA_EAP]; - } else if (hasWepKey) { - key = bareSsid + "WEP"; // hardcoded this way in WifiConfiguration - } else { - key = bareSsid + KeyMgmt.strings[KeyMgmt.NONE]; - } - return key; - } - - // Same approach as Pair.equals() and Pair.hashCode() - @Override - public boolean equals(Object o) { - if (o == this) return true; - if (!(o instanceof Network)) return false; - final Network other; - try { - other = (Network) o; - } catch (ClassCastException e) { - return false; - } - return ssid.equals(other.ssid) && key_mgmt.equals(other.key_mgmt); - } - - @Override - public int hashCode() { - int result = 17; - result = 31 * result + ssid.hashCode(); - result = 31 * result + key_mgmt.hashCode(); - return result; - } - } - - boolean networkInWhitelist(Network net, List whitelist) { - final String netConfigKey = net.configKey(); - final int N = whitelist.size(); - for (int i = 0; i < N; i++) { - if (Objects.equals(netConfigKey, whitelist.get(i).configKey(true))) { - return true; - } - } - return false; - } - - // Ingest multiple wifi config file fragments, looking for network={} blocks - // and eliminating duplicates - class WifiNetworkSettings { - // One for fast lookup, one for maintaining ordering - final HashSet mKnownNetworks = new HashSet(); - final ArrayList mNetworks = new ArrayList(8); - - public void readNetworks(BufferedReader in, List whitelist, - boolean acceptEapNetworks) { - try { - String line; - while (in.ready()) { - line = in.readLine(); - if (line != null) { - // Parse out 'network=' decls so we can ignore duplicates - if (line.startsWith("network")) { - Network net = Network.readFromStream(in); - if (whitelist != null) { - if (!networkInWhitelist(net, whitelist)) { - if (DEBUG_BACKUP) { - Log.v(TAG, "Network not in whitelist, skipping: " - + net.ssid + " / " + net.key_mgmt); - } - continue; - } - } - // Don't propagate EAP network definitions - if (net.isEap && !acceptEapNetworks) { - if (DEBUG_BACKUP) { - Log.v(TAG, "Skipping EAP network " + net.ssid + " / " + net.key_mgmt); - } - continue; - } - if (!mKnownNetworks.contains(net)) { - if (DEBUG_BACKUP) { - Log.v(TAG, "Adding " + net.ssid + " / " + net.key_mgmt); - } - mKnownNetworks.add(net); - mNetworks.add(net); - } else { - if (DEBUG_BACKUP) { - Log.v(TAG, "Dupe; skipped " + net.ssid + " / " + net.key_mgmt); - } - } - } - } - } - } catch (IOException e) { - // whatever happened, we're done now - } - } - - public void write(Writer w) throws IOException { - for (Network net : mNetworks) { - if (net.certUsed) { - // Networks that use certificates for authentication can't be restored - // because the certificates they need don't get restored (because they - // are stored in keystore, and can't be restored) - continue; - } - - if (net.isEap) { - // Similarly, omit EAP network definitions to avoid propagating - // controlled enterprise network definitions. - continue; - } - - net.write(w); - } - } - - public void dump() { - for (Network net : mNetworks) { - net.dump(); - } - } - } + private WifiManager mWifiManager; @Override public void onCreate() { if (DEBUG_BACKUP) Log.d(TAG, "onCreate() invoked"); mSettingsHelper = new SettingsHelper(this); + mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); super.onCreate(); - - WifiManager mWfm = (WifiManager) getSystemService(Context.WIFI_SERVICE); - if (mWfm != null) mWifiConfigFile = mWfm.getConfigFile(); } @Override @@ -420,10 +160,9 @@ public class SettingsBackupAgent extends BackupAgentHelper { byte[] globalSettingsData = getGlobalSettings(); byte[] lockSettingsData = getLockSettings(); byte[] locale = mSettingsHelper.getLocaleData(); - byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT); - byte[] wifiConfigData = getFileData(mWifiConfigFile); byte[] softApConfigData = getSoftAPConfiguration(); byte[] netPoliciesData = getNetworkPolicies(); + byte[] wifiFullConfigData = getNewWifiConfigData(); long[] stateChecksums = readOldChecksums(oldState); @@ -435,12 +174,8 @@ public class SettingsBackupAgent extends BackupAgentHelper { writeIfChanged(stateChecksums[STATE_GLOBAL], KEY_GLOBAL, globalSettingsData, data); stateChecksums[STATE_LOCALE] = writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data); - stateChecksums[STATE_WIFI_SUPPLICANT] = - writeIfChanged(stateChecksums[STATE_WIFI_SUPPLICANT], KEY_WIFI_SUPPLICANT, - wifiSupplicantData, data); - stateChecksums[STATE_WIFI_CONFIG] = - writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData, - data); + stateChecksums[STATE_WIFI_SUPPLICANT] = 0; + stateChecksums[STATE_WIFI_CONFIG] = 0; stateChecksums[STATE_LOCK_SETTINGS] = writeIfChanged(stateChecksums[STATE_LOCK_SETTINGS], KEY_LOCK_SETTINGS, lockSettingsData, data); @@ -450,112 +185,13 @@ public class SettingsBackupAgent extends BackupAgentHelper { stateChecksums[STATE_NETWORK_POLICIES] = writeIfChanged(stateChecksums[STATE_NETWORK_POLICIES], KEY_NETWORK_POLICIES, netPoliciesData, data); + stateChecksums[STATE_WIFI_NEW_CONFIG] = + writeIfChanged(stateChecksums[STATE_WIFI_NEW_CONFIG], KEY_WIFI_NEW_CONFIG, + wifiFullConfigData, data); writeNewChecksums(stateChecksums, newState); } - class WifiDisableRunnable implements Runnable { - final WifiRestoreRunnable mNextPhase; - - public WifiDisableRunnable(WifiRestoreRunnable next) { - mNextPhase = next; - } - - @Override - public void run() { - if (DEBUG_BACKUP) { - Log.v(TAG, "Disabling wifi during restore"); - } - final ContentResolver cr = getContentResolver(); - final int scanAlways = Settings.Global.getInt(cr, - Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0); - final int retainedWifiState = enableWifi(false); - if (scanAlways != 0) { - Settings.Global.putInt(cr, - Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0); - } - - // Tell the final stage how to clean up after itself - mNextPhase.setPriorState(retainedWifiState, scanAlways); - - // And run it after a modest pause to give broadcasts and content - // observers time an opportunity to run on this looper thread, so - // that the wifi stack actually goes all the way down. - new Handler(getMainLooper()).postDelayed(mNextPhase, 2500); - } - } - - class WifiRestoreRunnable implements Runnable { - private byte[] restoredSupplicantData; - private byte[] restoredWifiConfigFile; - private int retainedWifiState; // provided by disable stage - private int scanAlways; // provided by disable stage - - void setPriorState(int retainedState, int always) { - retainedWifiState = retainedState; - scanAlways = always; - } - - void incorporateWifiSupplicant(BackupDataInput data) { - restoredSupplicantData = new byte[data.getDataSize()]; - if (restoredSupplicantData.length <= 0) return; - try { - data.readEntityData(restoredSupplicantData, 0, data.getDataSize()); - } catch (IOException e) { - Log.w(TAG, "Unable to read supplicant data"); - restoredSupplicantData = null; - } - } - - void incorporateWifiConfigFile(BackupDataInput data) { - restoredWifiConfigFile = new byte[data.getDataSize()]; - if (restoredWifiConfigFile.length <= 0) return; - try { - data.readEntityData(restoredWifiConfigFile, 0, data.getDataSize()); - } catch (IOException e) { - Log.w(TAG, "Unable to read config file"); - restoredWifiConfigFile = null; - } - } - - @Override - public void run() { - if (restoredSupplicantData != null || restoredWifiConfigFile != null) { - if (DEBUG_BACKUP) { - Log.v(TAG, "Applying restored wifi data"); - } - if (restoredSupplicantData != null) { - restoreWifiSupplicant(FILE_WIFI_SUPPLICANT, - restoredSupplicantData, restoredSupplicantData.length); - FileUtils.setPermissions(FILE_WIFI_SUPPLICANT, - FileUtils.S_IRUSR | FileUtils.S_IWUSR - | FileUtils.S_IRGRP | FileUtils.S_IWGRP, - Process.myUid(), Process.WIFI_UID); - } - if (restoredWifiConfigFile != null) { - restoreFileData(mWifiConfigFile, - restoredWifiConfigFile, restoredWifiConfigFile.length); - } - // restore the previous WIFI state. - if (scanAlways != 0) { - Settings.Global.putInt(getContentResolver(), - Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, scanAlways); - } - enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED - || retainedWifiState == WifiManager.WIFI_STATE_ENABLING); - } - } - } - - // Instantiate the wifi-config restore runnable, scheduling it for execution - // a minute hence - void initWifiRestoreIfNecessary() { - if (mWifiRestore == null) { - mWifiRestore = new WifiRestoreRunnable(); - mWifiDisable = new WifiDisableRunnable(mWifiRestore); - } - } - @Override public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { @@ -563,6 +199,8 @@ public class SettingsBackupAgent extends BackupAgentHelper { HashSet movedToGlobal = new HashSet(); Settings.System.getMovedToGlobalSettings(movedToGlobal); Settings.Secure.getMovedToGlobalSettings(movedToGlobal); + byte[] restoredWifiSupplicantData = null; + byte[] restoredWifiIpConfigData = null; while (data.readNextHeader()) { final String key = data.getKey(); @@ -582,8 +220,8 @@ public class SettingsBackupAgent extends BackupAgentHelper { break; case KEY_WIFI_SUPPLICANT : - initWifiRestoreIfNecessary(); - mWifiRestore.incorporateWifiSupplicant(data); + restoredWifiSupplicantData = new byte[size]; + data.readEntityData(restoredWifiSupplicantData, 0, size); break; case KEY_LOCALE : @@ -593,8 +231,8 @@ public class SettingsBackupAgent extends BackupAgentHelper { break; case KEY_WIFI_CONFIG : - initWifiRestoreIfNecessary(); - mWifiRestore.incorporateWifiConfigFile(data); + restoredWifiIpConfigData = new byte[size]; + data.readEntityData(restoredWifiIpConfigData, 0, size); break; case KEY_LOCK_SETTINGS : @@ -613,23 +251,23 @@ public class SettingsBackupAgent extends BackupAgentHelper { restoreNetworkPolicies(netPoliciesData); break; + case KEY_WIFI_NEW_CONFIG: + byte[] restoredWifiNewConfigData = new byte[size]; + data.readEntityData(restoredWifiNewConfigData, 0, size); + restoreNewWifiConfigData(restoredWifiNewConfigData, size); + break; + default : data.skipEntityData(); } } - // If we have wifi data to restore, post a runnable to perform the - // bounce-and-update operation a little ways in the future. The - // 'disable' runnable brings down the stack and remembers its state, - // and in turn schedules the 'restore' runnable to do the rewrite - // and cleanup operations. - if (mWifiRestore != null) { - long wifiBounceDelayMillis = Settings.Global.getLong( - getContentResolver(), - Settings.Global.WIFI_BOUNCE_DELAY_OVERRIDE_MS, - WIFI_BOUNCE_DELAY_MILLIS); - new Handler(getMainLooper()).postDelayed(mWifiDisable, wifiBounceDelayMillis); + // Do this at the end so that we also pull in the ipconfig data. + if (restoredWifiSupplicantData != null) { + restoreSupplicantWifiConfigData( + restoredWifiSupplicantData, restoredWifiSupplicantData.length, + restoredWifiIpConfigData, restoredWifiIpConfigData.length); } } @@ -640,10 +278,9 @@ public class SettingsBackupAgent extends BackupAgentHelper { byte[] globalSettingsData = getGlobalSettings(); byte[] lockSettingsData = getLockSettings(); byte[] locale = mSettingsHelper.getLocaleData(); - byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT); - byte[] wifiConfigData = getFileData(mWifiConfigFile); byte[] softApConfigData = getSoftAPConfiguration(); byte[] netPoliciesData = getNetworkPolicies(); + byte[] wifiFullConfigData = getNewWifiConfigData(); // Write the data to the staging file, then emit that as our tarfile // representation of the backed-up settings. @@ -673,14 +310,6 @@ public class SettingsBackupAgent extends BackupAgentHelper { if (DEBUG_BACKUP) Log.d(TAG, locale.length + " bytes of locale data"); out.writeInt(locale.length); out.write(locale); - if (DEBUG_BACKUP) { - Log.d(TAG, wifiSupplicantData.length + " bytes of wifi supplicant data"); - } - out.writeInt(wifiSupplicantData.length); - out.write(wifiSupplicantData); - 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); @@ -690,6 +319,11 @@ public class SettingsBackupAgent extends BackupAgentHelper { if (DEBUG_BACKUP) Log.d(TAG, netPoliciesData.length + " bytes of net policies data"); out.writeInt(netPoliciesData.length); out.write(netPoliciesData); + if (DEBUG_BACKUP) { + Log.d(TAG, wifiFullConfigData.length + " bytes of wifi config data"); + } + out.writeInt(wifiFullConfigData.length); + out.write(wifiFullConfigData); out.flush(); // also flushes downstream @@ -750,27 +384,22 @@ public class SettingsBackupAgent extends BackupAgentHelper { in.readFully(buffer, 0, nBytes); mSettingsHelper.setLocaleData(buffer, nBytes); - // wifi supplicant - nBytes = in.readInt(); - if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of wifi supplicant data"); - if (nBytes > buffer.length) buffer = new byte[nBytes]; - in.readFully(buffer, 0, nBytes); - int retainedWifiState = enableWifi(false); - restoreWifiSupplicant(FILE_WIFI_SUPPLICANT, buffer, nBytes); - FileUtils.setPermissions(FILE_WIFI_SUPPLICANT, - FileUtils.S_IRUSR | FileUtils.S_IWUSR - | FileUtils.S_IRGRP | FileUtils.S_IWGRP, - Process.myUid(), Process.WIFI_UID); - // retain the previous WIFI state. - enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED - || retainedWifiState == WifiManager.WIFI_STATE_ENABLING); + // Restore older backups performing the necessary migrations. + if (version < FULL_BACKUP_ADDED_WIFI_NEW) { + // wifi supplicant + int supplicant_size = in.readInt(); + if (DEBUG_BACKUP) Log.d(TAG, supplicant_size + " bytes of wifi supplicant data"); + byte[] supplicant_buffer = new byte[supplicant_size]; + in.readFully(supplicant_buffer, 0, supplicant_size); - // wifi config - nBytes = in.readInt(); - if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of wifi config data"); - if (nBytes > buffer.length) buffer = new byte[nBytes]; - in.readFully(buffer, 0, nBytes); - restoreFileData(mWifiConfigFile, buffer, nBytes); + // ip config + int ipconfig_size = in.readInt(); + if (DEBUG_BACKUP) Log.d(TAG, ipconfig_size + " bytes of ip config data"); + byte[] ipconfig_buffer = new byte[ipconfig_size]; + in.readFully(ipconfig_buffer, 0, nBytes); + restoreSupplicantWifiConfigData(supplicant_buffer, supplicant_size, ipconfig_buffer, + ipconfig_size); + } if (version >= FULL_BACKUP_ADDED_LOCK_SETTINGS) { nBytes = in.readInt(); @@ -801,6 +430,15 @@ public class SettingsBackupAgent extends BackupAgentHelper { restoreNetworkPolicies(buffer); } } + // Restore full wifi config data + if (version >= FULL_BACKUP_ADDED_WIFI_NEW) { + nBytes = in.readInt(); + if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of full wifi config data"); + if (nBytes > buffer.length) buffer = new byte[nBytes]; + in.readFully(buffer, 0, nBytes); + restoreNewWifiConfigData(buffer, nBytes); + } + if (DEBUG_BACKUP) Log.d(TAG, "Full restore complete."); } else { data.close(); @@ -1114,146 +752,17 @@ public class SettingsBackupAgent extends BackupAgentHelper { return result; } - private byte[] getFileData(String filename) { - InputStream is = null; - try { - File file = new File(filename); - is = new FileInputStream(file); - - //Will truncate read on a very long file, - //should not happen for a config file - byte[] bytes = new byte[(int) file.length()]; - - int offset = 0; - int numRead = 0; - while (offset < bytes.length - && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) { - offset += numRead; - } - - //read failure - if (offset < bytes.length) { - Log.w(TAG, "Couldn't backup " + filename); - return EMPTY_DATA; - } - return bytes; - } catch (IOException ioe) { - Log.w(TAG, "Couldn't backup " + filename); - return EMPTY_DATA; - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - } - } - } - } - - private void restoreFileData(String filename, byte[] bytes, int size) { - try { - File file = new File(filename); - if (file.exists()) file.delete(); - - OutputStream os = new BufferedOutputStream(new FileOutputStream(filename, true)); - os.write(bytes, 0, size); - os.close(); - } catch (IOException ioe) { - Log.w(TAG, "Couldn't restore " + filename); - } - } - - - private byte[] getWifiSupplicant(String filename) { - BufferedReader br = null; - try { - File file = new File(filename); - if (!file.exists()) { - return EMPTY_DATA; - } - - WifiManager wifi = (WifiManager) getSystemService(WIFI_SERVICE); - List configs = wifi.getConfiguredNetworks(); - - WifiNetworkSettings fromFile = new WifiNetworkSettings(); - br = new BufferedReader(new FileReader(file)); - fromFile.readNetworks(br, configs, false); - - // Write the parsed networks into a packed byte array - if (fromFile.mKnownNetworks.size() > 0) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - OutputStreamWriter out = new OutputStreamWriter(bos); - fromFile.write(out); - out.flush(); - return bos.toByteArray(); - } else { - return EMPTY_DATA; - } - } catch (IOException ioe) { - Log.w(TAG, "Couldn't backup " + filename); - return EMPTY_DATA; - } finally { - IoUtils.closeQuietly(br); - } - } - - private void restoreWifiSupplicant(String filename, byte[] bytes, int size) { - try { - WifiNetworkSettings supplicantImage = new WifiNetworkSettings(); - - File supplicantFile = new File(FILE_WIFI_SUPPLICANT); - if (supplicantFile.exists()) { - // Retain the existing APs; we'll append the restored ones to them - BufferedReader in = new BufferedReader(new FileReader(FILE_WIFI_SUPPLICANT)); - supplicantImage.readNetworks(in, null, true); - in.close(); - - supplicantFile.delete(); - } - - // Incorporate the restore AP information - if (size > 0) { - char[] restoredAsBytes = new char[size]; - for (int i = 0; i < size; i++) restoredAsBytes[i] = (char) bytes[i]; - BufferedReader in = new BufferedReader(new CharArrayReader(restoredAsBytes)); - supplicantImage.readNetworks(in, null, false); - - if (DEBUG_BACKUP) { - Log.v(TAG, "Final AP list:"); - supplicantImage.dump(); - } - } - - // Install the correct default template - BufferedWriter bw = new BufferedWriter(new FileWriter(FILE_WIFI_SUPPLICANT)); - copyWifiSupplicantTemplate(bw); - - // Write the restored supplicant config and we're done - supplicantImage.write(bw); - bw.close(); - } catch (IOException ioe) { - Log.w(TAG, "Couldn't restore " + filename); - } - } - - private void copyWifiSupplicantTemplate(BufferedWriter bw) { - try { - BufferedReader br = new BufferedReader(new FileReader(FILE_WIFI_SUPPLICANT_TEMPLATE)); - char[] temp = new char[1024]; - int size; - while ((size = br.read(temp)) > 0) { - bw.write(temp, 0, size); - } - br.close(); - } catch (IOException ioe) { - Log.w(TAG, "Couldn't copy wpa_supplicant file"); + private void restoreSupplicantWifiConfigData(byte[] supplicant_bytes, int supplicant_size, + byte[] ipconfig_bytes, int ipconfig_size) { + if (DEBUG_BACKUP) { + Log.v(TAG, "Applying restored supplicant wifi data"); } + mWifiManager.restoreSupplicantBackupData(supplicant_bytes, ipconfig_bytes); } private byte[] getSoftAPConfiguration() { - WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); try { - return wifiManager.getWifiApConfiguration().getBytesForBackup(); + return mWifiManager.getWifiApConfiguration().getBytesForBackup(); } catch (IOException ioe) { Log.e(TAG, "Failed to marshal SoftAPConfiguration" + ioe.getMessage()); return new byte[0]; @@ -1261,12 +770,11 @@ public class SettingsBackupAgent extends BackupAgentHelper { } private void restoreSoftApConfiguration(byte[] data) { - WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); try { WifiConfiguration config = WifiConfiguration .getWifiConfigFromBackup(new DataInputStream(new ByteArrayInputStream(data))); if (DEBUG) Log.d(TAG, "Successfully unMarshaled WifiConfiguration "); - wifiManager.setWifiApConfiguration(config); + mWifiManager.setWifiApConfiguration(config); } catch (IOException | BackupUtils.BadVersionException e) { Log.e(TAG, "Failed to unMarshal SoftAPConfiguration " + e.getMessage()); } @@ -1300,6 +808,17 @@ public class SettingsBackupAgent extends BackupAgentHelper { return baos.toByteArray(); } + private byte[] getNewWifiConfigData() { + return mWifiManager.retrieveBackupData(); + } + + private void restoreNewWifiConfigData(byte[] bytes, int size) { + if (DEBUG_BACKUP) { + Log.v(TAG, "Applying restored wifi data"); + } + mWifiManager.restoreBackupData(bytes); + } + private void restoreNetworkPolicies(byte[] data) { NetworkPolicyManager networkPolicyManager = (NetworkPolicyManager) getSystemService(NETWORK_POLICY_SERVICE); @@ -1358,18 +877,4 @@ public class SettingsBackupAgent extends BackupAgentHelper { | ((in[pos + 3] & 0xFF) << 0); return result; } - - private int enableWifi(boolean enable) { - if (mWfm == null) { - mWfm = (WifiManager) getSystemService(Context.WIFI_SERVICE); - } - if (mWfm != null) { - int state = mWfm.getWifiState(); - mWfm.setWifiEnabled(enable); - return state; - } else { - Log.e(TAG, "Failed to fetch WifiManager instance"); - } - return WifiManager.WIFI_STATE_UNKNOWN; - } }