summaryrefslogtreecommitdiffstats
path: root/wifi
diff options
context:
space:
mode:
authorIrfan Sheriff <isheriff@google.com>2011-11-07 10:34:54 -0800
committerIrfan Sheriff <isheriff@google.com>2011-11-08 15:45:42 -0800
commit9575a1bea1787efe1686bd8562bcc70c72d01721 (patch)
tree5c6eb3d5cf0965492a86b3188f509e5e86d4cf1b /wifi
parent19c86cacb2f0ba04cc93084ba474662afb17d88f (diff)
downloadframeworks_base-9575a1bea1787efe1686bd8562bcc70c72d01721.zip
frameworks_base-9575a1bea1787efe1686bd8562bcc70c72d01721.tar.gz
frameworks_base-9575a1bea1787efe1686bd8562bcc70c72d01721.tar.bz2
Convert soft ap config store to state machine
- Create thread when needed - asynchronous interaction with wifi state machine Bug: 5587391 Change-Id: Ie6d01b5a6b398a3fa12c384920a473e242443131
Diffstat (limited to 'wifi')
-rw-r--r--wifi/java/android/net/wifi/WifiApConfigStore.java245
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java109
2 files changed, 200 insertions, 154 deletions
diff --git a/wifi/java/android/net/wifi/WifiApConfigStore.java b/wifi/java/android/net/wifi/WifiApConfigStore.java
index bb5427d..0531ca3 100644
--- a/wifi/java/android/net/wifi/WifiApConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiApConfigStore.java
@@ -19,11 +19,16 @@ package android.net.wifi;
import android.content.Context;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.os.Environment;
-import android.os.Message;
import android.os.Handler;
-import android.os.HandlerThread;
+import android.os.Message;
+import android.os.Messenger;
import android.util.Log;
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.R;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
@@ -34,16 +39,13 @@ import java.io.IOException;
import java.net.InetAddress;
import java.util.UUID;
-import com.android.internal.R;
-
-
/**
* Provides API to the WifiStateMachine for doing read/write access
* to soft access point configuration
*/
-class WifiApConfigStore {
+class WifiApConfigStore extends StateMachine {
- private static Context sContext;
+ private Context mContext;
private static final String TAG = "WifiApConfigStore";
private static final String AP_CONFIG_FILE = Environment.getDataDirectory() +
@@ -51,131 +53,160 @@ class WifiApConfigStore {
private static final int AP_CONFIG_FILE_VERSION = 1;
- private static WifiConfiguration sApConfig = new WifiConfiguration();
- private static final Object sApConfigLock = new Object();
+ private State mDefaultState = new DefaultState();
+ private State mInactiveState = new InactiveState();
+ private State mActiveState = new ActiveState();
+
+ private WifiConfiguration mWifiApConfig = null;
+ private AsyncChannel mReplyChannel = new AsyncChannel();
- private static FileReadWriteHandler sFileReadWriteHandler;
- private static final int READ_AP_CONFIG = 1;
- private static final int WRITE_AP_CONFIG = 2;
+ WifiApConfigStore(Context context, Handler target) {
+ super(TAG, target.getLooper());
- static void initialize(Context context) {
- sContext = context;
+ mContext = context;
+ addState(mDefaultState);
+ addState(mInactiveState, mDefaultState);
+ addState(mActiveState, mDefaultState);
- /* File operations happen on a seperate thread */
- HandlerThread configThread = new HandlerThread("WifiApConfigStore");
- configThread.start();
- sFileReadWriteHandler = new FileReadWriteHandler(configThread.getLooper());
- Message.obtain(sFileReadWriteHandler, READ_AP_CONFIG).sendToTarget();
+ setInitialState(mInactiveState);
}
+ public static WifiApConfigStore makeWifiApConfigStore(Context context, Handler target) {
+ WifiApConfigStore s = new WifiApConfigStore(context, target);
+ s.start();
+ return s;
+ }
- static void setApConfiguration(WifiConfiguration config) {
- synchronized (sApConfigLock) {
- sApConfig = config;
+ class DefaultState extends State {
+ public boolean processMessage(Message message) {
+ switch (message.what) {
+ case WifiStateMachine.CMD_SET_AP_CONFIG:
+ case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED:
+ Log.e(TAG, "Unexpected message: " + message);
+ break;
+ case WifiStateMachine.CMD_REQUEST_AP_CONFIG:
+ mReplyChannel.replyToMessage(message,
+ WifiStateMachine.CMD_RESPONSE_AP_CONFIG, mWifiApConfig);
+ break;
+ default:
+ Log.e(TAG, "Failed to handle " + message);
+ break;
+ }
+ return HANDLED;
}
- Message.obtain(sFileReadWriteHandler, WRITE_AP_CONFIG, new WifiConfiguration(config))
- .sendToTarget();
}
- static WifiConfiguration getApConfiguration() {
- synchronized (sApConfigLock) {
- return new WifiConfiguration(sApConfig);
+ class InactiveState extends State {
+ public boolean processMessage(Message message) {
+ switch (message.what) {
+ case WifiStateMachine.CMD_SET_AP_CONFIG:
+ mWifiApConfig = (WifiConfiguration) message.obj;
+ transitionTo(mActiveState);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
}
}
- /**
- * File read/write handler
- */
- private static class FileReadWriteHandler extends Handler {
-
- public FileReadWriteHandler(android.os.Looper looper) {
- super(looper);
+ class ActiveState extends State {
+ public void enter() {
+ new Thread(new Runnable() {
+ public void run() {
+ writeApConfiguration(mWifiApConfig);
+ sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED);
+ }
+ }).start();
}
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case WRITE_AP_CONFIG:
- writeApConfiguration((WifiConfiguration) msg.obj);
+ public boolean processMessage(Message message) {
+ switch (message.what) {
+ //TODO: have feedback to the user when we do this
+ //to indicate the write is currently in progress
+ case WifiStateMachine.CMD_SET_AP_CONFIG:
+ deferMessage(message);
break;
- case READ_AP_CONFIG:
- readApConfiguration();
+ case WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED:
+ transitionTo(mInactiveState);
break;
default:
- Log.e(TAG, "Unknown command in FileReadWriteHandler: " + msg);
- break;
+ return NOT_HANDLED;
}
+ return HANDLED;
}
+ }
- private static void writeApConfiguration(final WifiConfiguration config) {
- DataOutputStream out = null;
- try {
- out = new DataOutputStream(new BufferedOutputStream(
- new FileOutputStream(AP_CONFIG_FILE)));
-
- out.writeInt(AP_CONFIG_FILE_VERSION);
- out.writeUTF(config.SSID);
- int authType = config.getAuthType();
- out.writeInt(authType);
- if(authType != KeyMgmt.NONE) {
- out.writeUTF(config.preSharedKey);
- }
- } catch (IOException e) {
- Log.e(TAG, "Error writing hotspot configuration" + e);
- } finally {
- if (out != null) {
- try {
- out.close();
- } catch (IOException e) {}
- }
- }
- }
+ void loadApConfiguration() {
+ DataInputStream in = null;
+ try {
+ WifiConfiguration config = new WifiConfiguration();
+ in = new DataInputStream(new BufferedInputStream(new FileInputStream(
+ AP_CONFIG_FILE)));
- private static void readApConfiguration() {
- DataInputStream in = null;
- try {
- WifiConfiguration config = new WifiConfiguration();
- in = new DataInputStream(new BufferedInputStream(new FileInputStream(
- AP_CONFIG_FILE)));
-
- int version = in.readInt();
- if (version != 1) {
- Log.e(TAG, "Bad version on hotspot configuration file, set defaults");
- setDefaultApConfiguration();
- return;
- }
- config.SSID = in.readUTF();
- int authType = in.readInt();
- config.allowedKeyManagement.set(authType);
- if (authType != KeyMgmt.NONE) {
- config.preSharedKey = in.readUTF();
- }
- synchronized (sApConfigLock) {
- sApConfig = config;
- }
- } catch (IOException ignore) {
+ int version = in.readInt();
+ if (version != 1) {
+ Log.e(TAG, "Bad version on hotspot configuration file, set defaults");
setDefaultApConfiguration();
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {}
- }
+ return;
+ }
+ config.SSID = in.readUTF();
+ int authType = in.readInt();
+ config.allowedKeyManagement.set(authType);
+ if (authType != KeyMgmt.NONE) {
+ config.preSharedKey = in.readUTF();
+ }
+ mWifiApConfig = config;
+ } catch (IOException ignore) {
+ setDefaultApConfiguration();
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {}
}
}
+ }
- /* Generate a default WPA2 based configuration with a random password.
- We are changing the Wifi Ap configuration storage from secure settings to a
- flat file accessible only by the system. A WPA2 based default configuration
- will keep the device secure after the update */
- private static void setDefaultApConfiguration() {
- WifiConfiguration config = new WifiConfiguration();
- config.SSID = sContext.getString(R.string.wifi_tether_configure_ssid_default);
- config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
- String randomUUID = UUID.randomUUID().toString();
- //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
- config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9,13);
- setApConfiguration(config);
+ Messenger getMessenger() {
+ return new Messenger(getHandler());
+ }
+
+ private void writeApConfiguration(final WifiConfiguration config) {
+ DataOutputStream out = null;
+ try {
+ out = new DataOutputStream(new BufferedOutputStream(
+ new FileOutputStream(AP_CONFIG_FILE)));
+
+ out.writeInt(AP_CONFIG_FILE_VERSION);
+ out.writeUTF(config.SSID);
+ int authType = config.getAuthType();
+ out.writeInt(authType);
+ if(authType != KeyMgmt.NONE) {
+ out.writeUTF(config.preSharedKey);
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Error writing hotspot configuration" + e);
+ } finally {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {}
+ }
}
}
+
+ /* Generate a default WPA2 based configuration with a random password.
+ We are changing the Wifi Ap configuration storage from secure settings to a
+ flat file accessible only by the system. A WPA2 based default configuration
+ will keep the device secure after the update */
+ private void setDefaultApConfiguration() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.SSID = mContext.getString(R.string.wifi_tether_configure_ssid_default);
+ config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
+ String randomUUID = UUID.randomUUID().toString();
+ //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
+ config.preSharedKey = randomUUID.substring(0, 8) + randomUUID.substring(9,13);
+ sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG, config);
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 00fae2e..aadcaad 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -184,6 +184,7 @@ public class WifiStateMachine extends StateMachine {
private WifiP2pManager mWifiP2pManager;
//Used to initiate a connection with WifiP2pService
private AsyncChannel mWifiP2pChannel = new AsyncChannel();
+ private AsyncChannel mWifiApConfigChannel = new AsyncChannel();
// Event log tags (must be in sync with event-log-tags)
private static final int EVENTLOG_WIFI_STATE_CHANGED = 50021;
@@ -233,12 +234,16 @@ public class WifiStateMachine extends StateMachine {
static final int CMD_STOP_AP = BASE + 24;
/* Set the soft access point configuration */
static final int CMD_SET_AP_CONFIG = BASE + 25;
- /* Get the soft access point configuration */
- static final int CMD_GET_AP_CONFIG = BASE + 26;
+ /* Soft access point configuration set completed */
+ static final int CMD_SET_AP_CONFIG_COMPLETED = BASE + 26;
+ /* Request the soft access point configuration */
+ static final int CMD_REQUEST_AP_CONFIG = BASE + 27;
+ /* Response to access point configuration request */
+ static final int CMD_RESPONSE_AP_CONFIG = BASE + 28;
/* Set configuration on tether interface */
- static final int CMD_TETHER_INTERFACE = BASE + 27;
+ static final int CMD_TETHER_INTERFACE = BASE + 29;
- static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 28;
+ static final int CMD_BLUETOOTH_ADAPTER_STATE_CHANGE = BASE + 30;
/* Supplicant commands */
/* Is supplicant alive ? */
@@ -530,6 +535,11 @@ public class WifiStateMachine extends StateMachine {
mWpsStateMachine = new WpsStateMachine(context, this, getHandler());
mLinkProperties = new LinkProperties();
+ WifiApConfigStore wifiApConfigStore = WifiApConfigStore.makeWifiApConfigStore(
+ context, getHandler());
+ wifiApConfigStore.loadApConfiguration();
+ mWifiApConfigChannel.connectSync(mContext, getHandler(), wifiApConfigStore.getMessenger());
+
mNetworkInfo.setIsAvailable(false);
mLinkProperties.clear();
mLastBssid = null;
@@ -659,11 +669,11 @@ public class WifiStateMachine extends StateMachine {
}
public void setWifiApConfiguration(WifiConfiguration config) {
- sendMessage(obtainMessage(CMD_SET_AP_CONFIG, config));
+ mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);
}
- public WifiConfiguration syncGetWifiApConfiguration(AsyncChannel channel) {
- Message resultMsg = channel.sendMessageSynchronously(CMD_GET_AP_CONFIG);
+ public WifiConfiguration syncGetWifiApConfiguration() {
+ Message resultMsg = mWifiApConfigChannel.sendMessageSynchronously(CMD_REQUEST_AP_CONFIG);
WifiConfiguration ret = (WifiConfiguration) resultMsg.obj;
resultMsg.recycle();
return ret;
@@ -1714,25 +1724,27 @@ public class WifiStateMachine extends StateMachine {
* TODO: Add control channel setup through hostapd that allows changing config
* on a running daemon
*/
- private boolean startSoftApWithConfig(WifiConfiguration config) {
- if (config == null) {
- config = WifiApConfigStore.getApConfiguration();
- } else {
- WifiApConfigStore.setApConfiguration(config);
- }
- try {
- mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
- } catch (Exception e) {
- loge("Exception in softap start " + e);
- try {
- mNwService.stopAccessPoint(mInterfaceName);
- mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
- } catch (Exception e1) {
- loge("Exception in softap re-start " + e1);
- return false;
+ private void startSoftApWithConfig(final WifiConfiguration config) {
+ // start hostapd on a seperate thread
+ new Thread(new Runnable() {
+ public void run() {
+ try {
+ mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
+ } catch (Exception e) {
+ loge("Exception in softap start " + e);
+ try {
+ mNwService.stopAccessPoint(mInterfaceName);
+ mNwService.startAccessPoint(config, mInterfaceName, SOFTAP_IFACE);
+ } catch (Exception e1) {
+ loge("Exception in softap re-start " + e1);
+ sendMessage(CMD_START_AP_FAILURE);
+ return;
+ }
+ }
+ if (DBG) log("Soft AP start successful");
+ sendMessage(CMD_START_AP_SUCCESS);
}
- }
- return true;
+ }).start();
}
/********************************************************
@@ -1775,13 +1787,6 @@ public class WifiStateMachine extends StateMachine {
case CMD_ENABLE_BACKGROUND_SCAN:
mEnableBackgroundScan = (message.arg1 == 1);
break;
- case CMD_SET_AP_CONFIG:
- WifiApConfigStore.setApConfiguration((WifiConfiguration) message.obj);
- break;
- case CMD_GET_AP_CONFIG:
- WifiConfiguration config = WifiApConfigStore.getApConfiguration();
- mReplyChannel.replyToMessage(message, message.what, config);
- break;
/* Discard */
case CMD_LOAD_DRIVER:
case CMD_UNLOAD_DRIVER:
@@ -1823,6 +1828,11 @@ public class WifiStateMachine extends StateMachine {
case CMD_ENABLE_ALL_NETWORKS:
case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
case DhcpStateMachine.CMD_POST_DHCP_ACTION:
+ /* Handled by WifiApConfigStore */
+ case CMD_SET_AP_CONFIG:
+ case CMD_SET_AP_CONFIG_COMPLETED:
+ case CMD_REQUEST_AP_CONFIG:
+ case CMD_RESPONSE_AP_CONFIG:
break;
case WifiMonitor.DRIVER_HUNG_EVENT:
setWifiEnabled(false);
@@ -1856,8 +1866,6 @@ public class WifiStateMachine extends StateMachine {
// 50021 wifi_state_changed (custom|1|5)
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- WifiApConfigStore.initialize(mContext);
-
if (WifiNative.isDriverLoaded()) {
transitionTo(mDriverLoadedState);
}
@@ -3243,21 +3251,19 @@ public class WifiStateMachine extends StateMachine {
if (DBG) log(getName() + "\n");
EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
- final Message message = Message.obtain(getCurrentMessage());
- final WifiConfiguration config = (WifiConfiguration) message.obj;
+ final Message message = getCurrentMessage();
+ if (message.what == CMD_START_AP) {
+ final WifiConfiguration config = (WifiConfiguration) message.obj;
- // start hostapd on a seperate thread
- new Thread(new Runnable() {
- public void run() {
- if (startSoftApWithConfig(config)) {
- if (DBG) log("Soft AP start successful");
- sendMessage(CMD_START_AP_SUCCESS);
- } else {
- loge("Soft AP start failed");
- sendMessage(CMD_START_AP_FAILURE);
- }
+ if (config == null) {
+ mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG);
+ } else {
+ mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);
+ startSoftApWithConfig(config);
}
- }).start();
+ } else {
+ throw new RuntimeException("Illegal transition to SoftApStartingState: " + message);
+ }
}
@Override
public boolean processMessage(Message message) {
@@ -3282,6 +3288,15 @@ public class WifiStateMachine extends StateMachine {
case WifiP2pService.P2P_ENABLE_PENDING:
deferMessage(message);
break;
+ case WifiStateMachine.CMD_RESPONSE_AP_CONFIG:
+ WifiConfiguration config = (WifiConfiguration) message.obj;
+ if (config != null) {
+ startSoftApWithConfig(config);
+ } else {
+ loge("Softap config is null!");
+ sendMessage(CMD_START_AP_FAILURE);
+ }
+ break;
case CMD_START_AP_SUCCESS:
setWifiApState(WIFI_AP_STATE_ENABLED);
transitionTo(mSoftApStartedState);