2626import android .net .Uri ;
2727import android .net .wifi .WifiManager ;
2828import android .os .FileUtils ;
29+ import android .os .Handler ;
2930import android .os .ParcelFileDescriptor ;
3031import android .os .Process ;
3132import android .provider .Settings ;
@@ -61,12 +62,6 @@ public class SettingsBackupAgent extends BackupAgentHelper {
6162 private static final boolean DEBUG = false ;
6263 private static final boolean DEBUG_BACKUP = DEBUG || false ;
6364
64- /* Don't restore wifi config until we have new logic for parsing the
65- * saved wifi config and configuring the new APs without having to
66- * disable and re-enable wifi
67- */
68- private static final boolean NAIVE_WIFI_RESTORE = false ;
69-
7065 private static final String KEY_SYSTEM = "system" ;
7166 private static final String KEY_SECURE = "secure" ;
7267 private static final String KEY_GLOBAL = "global" ;
@@ -127,10 +122,16 @@ public class SettingsBackupAgent extends BackupAgentHelper {
127122 // stored in the full-backup tarfile as well, so should not be changed.
128123 private static final String STAGE_FILE = "flattened-data" ;
129124
125+ // Delay in milliseconds between the restore operation and when we will bounce
126+ // wifi in order to rewrite the supplicant config etc.
127+ private static final long WIFI_BOUNCE_DELAY_MILLIS = 60 * 1000 ; // one minute
128+
130129 private SettingsHelper mSettingsHelper ;
131130 private WifiManager mWfm ;
132131 private static String mWifiConfigFile ;
133132
133+ WifiRestoreRunnable mWifiRestore = null ;
134+
134135 // Class for capturing a network definition from the wifi supplicant config file
135136 static class Network {
136137 String ssid = "" ; // equals() and hashCode() need these to be non-null
@@ -297,6 +298,66 @@ public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
297298 writeNewChecksums (stateChecksums , newState );
298299 }
299300
301+ class WifiRestoreRunnable implements Runnable {
302+ private byte [] restoredSupplicantData ;
303+ private byte [] restoredWifiConfigFile ;
304+
305+ void incorporateWifiSupplicant (BackupDataInput data ) {
306+ restoredSupplicantData = new byte [data .getDataSize ()];
307+ if (restoredSupplicantData .length <= 0 ) return ;
308+ try {
309+ data .readEntityData (restoredSupplicantData , 0 , data .getDataSize ());
310+ } catch (IOException e ) {
311+ Log .w (TAG , "Unable to read supplicant data" );
312+ restoredSupplicantData = null ;
313+ }
314+ }
315+
316+ void incorporateWifiConfigFile (BackupDataInput data ) {
317+ restoredWifiConfigFile = new byte [data .getDataSize ()];
318+ if (restoredWifiConfigFile .length <= 0 ) return ;
319+ try {
320+ data .readEntityData (restoredWifiConfigFile , 0 , data .getDataSize ());
321+ } catch (IOException e ) {
322+ Log .w (TAG , "Unable to read config file" );
323+ restoredWifiConfigFile = null ;
324+ }
325+ }
326+
327+ @ Override
328+ public void run () {
329+ if (restoredSupplicantData != null || restoredWifiConfigFile != null ) {
330+ if (DEBUG_BACKUP ) {
331+ Log .v (TAG , "Starting deferred restore of wifi data" );
332+ }
333+ final int retainedWifiState = enableWifi (false );
334+ if (restoredSupplicantData != null ) {
335+ restoreWifiSupplicant (FILE_WIFI_SUPPLICANT ,
336+ restoredSupplicantData , restoredSupplicantData .length );
337+ FileUtils .setPermissions (FILE_WIFI_SUPPLICANT ,
338+ FileUtils .S_IRUSR | FileUtils .S_IWUSR |
339+ FileUtils .S_IRGRP | FileUtils .S_IWGRP ,
340+ Process .myUid (), Process .WIFI_UID );
341+ }
342+ if (restoredWifiConfigFile != null ) {
343+ restoreFileData (mWifiConfigFile ,
344+ restoredWifiConfigFile , restoredWifiConfigFile .length );
345+ }
346+ // restore the previous WIFI state.
347+ enableWifi (retainedWifiState == WifiManager .WIFI_STATE_ENABLED ||
348+ retainedWifiState == WifiManager .WIFI_STATE_ENABLING );
349+ }
350+ }
351+ }
352+
353+ // Instantiate the wifi-config restore runnable, scheduling it for execution
354+ // a minute hence
355+ void initWifiRestoreIfNecessary () {
356+ if (mWifiRestore == null ) {
357+ mWifiRestore = new WifiRestoreRunnable ();
358+ }
359+ }
360+
300361 @ Override
301362 public void onRestore (BackupDataInput data , int appVersionCode ,
302363 ParcelFileDescriptor newState ) throws IOException {
@@ -315,26 +376,26 @@ public void onRestore(BackupDataInput data, int appVersionCode,
315376 restoreSettings (data , Settings .Secure .CONTENT_URI , movedToGlobal );
316377 } else if (KEY_GLOBAL .equals (key )) {
317378 restoreSettings (data , Settings .Global .CONTENT_URI , null );
318- } else if (NAIVE_WIFI_RESTORE && KEY_WIFI_SUPPLICANT .equals (key )) {
319- int retainedWifiState = enableWifi (false );
320- restoreWifiSupplicant (FILE_WIFI_SUPPLICANT , data );
321- FileUtils .setPermissions (FILE_WIFI_SUPPLICANT ,
322- FileUtils .S_IRUSR | FileUtils .S_IWUSR |
323- FileUtils .S_IRGRP | FileUtils .S_IWGRP ,
324- Process .myUid (), Process .WIFI_UID );
325- // retain the previous WIFI state.
326- enableWifi (retainedWifiState == WifiManager .WIFI_STATE_ENABLED ||
327- retainedWifiState == WifiManager .WIFI_STATE_ENABLING );
379+ } else if (KEY_WIFI_SUPPLICANT .equals (key )) {
380+ initWifiRestoreIfNecessary ();
381+ mWifiRestore .incorporateWifiSupplicant (data );
328382 } else if (KEY_LOCALE .equals (key )) {
329383 byte [] localeData = new byte [size ];
330384 data .readEntityData (localeData , 0 , size );
331385 mSettingsHelper .setLocaleData (localeData , size );
332- } else if (NAIVE_WIFI_RESTORE && KEY_WIFI_CONFIG .equals (key )) {
333- restoreFileData (mWifiConfigFile , data );
386+ } else if (KEY_WIFI_CONFIG .equals (key )) {
387+ initWifiRestoreIfNecessary ();
388+ mWifiRestore .incorporateWifiConfigFile (data );
334389 } else {
335390 data .skipEntityData ();
336391 }
337392 }
393+
394+ // If we have wifi data to restore, post a runnable to perform the
395+ // bounce-and-update operation a little ways in the future.
396+ if (mWifiRestore != null ) {
397+ new Handler (getMainLooper ()).postDelayed (mWifiRestore , WIFI_BOUNCE_DELAY_MILLIS );
398+ }
338399 }
339400
340401 @ Override
@@ -619,7 +680,7 @@ private void restoreSettings(byte[] settings, int bytes, Uri contentUri,
619680 getContentResolver ().insert (destination , contentValues );
620681 }
621682
622- if (DEBUG || true ) {
683+ if (DEBUG ) {
623684 Log .d (TAG , "Restored setting: " + destination + " : " + key + "=" + value );
624685 }
625686 }
@@ -731,17 +792,6 @@ private byte[] getFileData(String filename) {
731792
732793 }
733794
734- private void restoreFileData (String filename , BackupDataInput data ) {
735- byte [] bytes = new byte [data .getDataSize ()];
736- if (bytes .length <= 0 ) return ;
737- try {
738- data .readEntityData (bytes , 0 , data .getDataSize ());
739- restoreFileData (filename , bytes , bytes .length );
740- } catch (IOException e ) {
741- Log .w (TAG , "Unable to read file data for " + filename );
742- }
743- }
744-
745795 private void restoreFileData (String filename , byte [] bytes , int size ) {
746796 try {
747797 File file = new File (filename );
@@ -794,17 +844,6 @@ private byte[] getWifiSupplicant(String filename) {
794844 }
795845 }
796846
797- private void restoreWifiSupplicant (String filename , BackupDataInput data ) {
798- byte [] bytes = new byte [data .getDataSize ()];
799- if (bytes .length <= 0 ) return ;
800- try {
801- data .readEntityData (bytes , 0 , data .getDataSize ());
802- restoreWifiSupplicant (filename , bytes , bytes .length );
803- } catch (IOException e ) {
804- Log .w (TAG , "Unable to read supplicant data" );
805- }
806- }
807-
808847 private void restoreWifiSupplicant (String filename , byte [] bytes , int size ) {
809848 try {
810849 WifiNetworkSettings supplicantImage = new WifiNetworkSettings ();
0 commit comments