From 45dc0d03fdcc649f56bfd3a67a1334ced1e2789f Mon Sep 17 00:00:00 2001 From: Christopher Tate Date: Fri, 7 Aug 2015 19:20:05 -0700 Subject: Fix wifi disable during restore The main looper needs to run freely for a moment after disabling wifi in order for various signals (content observers, broadcast) to propagate to all the listeners that need to take action for the wifi stack to shut all the way down. This patch breaks up the disable-and-rewrite-config sequence of wifi AP restore in to two distinct operations separated by a moment so as not to block those necessary messages. Bug 22979342 Change-Id: I271766cad0e454669a194652fb67f835bb022cd1 --- .../providers/settings/SettingsBackupAgent.java | 65 ++++++++++++++++------ 1 file changed, 49 insertions(+), 16 deletions(-) (limited to 'packages/SettingsProvider') diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java index e74334b..b9a9c24 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java @@ -148,7 +148,10 @@ public class SettingsBackupAgent extends BackupAgentHelper { private WifiManager mWfm; private static 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 { @@ -407,9 +410,47 @@ public class SettingsBackupAgent extends BackupAgentHelper { 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()]; @@ -437,20 +478,8 @@ public class SettingsBackupAgent extends BackupAgentHelper { public void run() { if (restoredSupplicantData != null || restoredWifiConfigFile != null) { if (DEBUG_BACKUP) { - Log.v(TAG, "Starting deferred restore of wifi data"); - } - 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); + Log.v(TAG, "Applying restored wifi data"); } - // !!! Give the wifi stack a moment to quiesce. We've observed the - // response to disabling WIFI_SCAN_ALWAYS_AVAILABLE taking more - // than 1500ms, so we wait a generous 2500 here before proceeding. - try { Thread.sleep(2500); } catch (InterruptedException e) {} if (restoredSupplicantData != null) { restoreWifiSupplicant(FILE_WIFI_SUPPLICANT, restoredSupplicantData, restoredSupplicantData.length); @@ -465,7 +494,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { } // restore the previous WIFI state. if (scanAlways != 0) { - Settings.Global.putInt(cr, + Settings.Global.putInt(getContentResolver(), Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, scanAlways); } enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED || @@ -479,6 +508,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { void initWifiRestoreIfNecessary() { if (mWifiRestore == null) { mWifiRestore = new WifiRestoreRunnable(); + mWifiDisable = new WifiDisableRunnable(mWifiRestore); } } @@ -518,13 +548,16 @@ public class SettingsBackupAgent extends BackupAgentHelper { } // If we have wifi data to restore, post a runnable to perform the - // bounce-and-update operation a little ways in the future. + // 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(mWifiRestore, wifiBounceDelayMillis); + new Handler(getMainLooper()).postDelayed(mWifiDisable, wifiBounceDelayMillis); } } -- cgit v1.1