diff options
author | Irfan Sheriff <isheriff@google.com> | 2012-02-24 10:54:13 -0800 |
---|---|---|
committer | Irfan Sheriff <isheriff@google.com> | 2012-03-01 13:57:23 -0800 |
commit | d3975a917799b85cacaf382b65c5832813066b51 (patch) | |
tree | 35f249be09330ebf5222b139bd1c2355823e7e88 | |
parent | 5bb59daf42fb24c1131effd4265c2386304feceb (diff) | |
download | frameworks_base-d3975a917799b85cacaf382b65c5832813066b51.zip frameworks_base-d3975a917799b85cacaf382b65c5832813066b51.tar.gz frameworks_base-d3975a917799b85cacaf382b65c5832813066b51.tar.bz2 |
Fix WifiManager async API
Fix the current asynchronous API to use callback like the way
was done with p2p API.
In the process, fix the use of WPS
Change-Id: Ib6f8714cf51b3525b655948268804e7eaaf17587
12 files changed, 538 insertions, 482 deletions
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java index 0cadb16..d462d7f 100644 --- a/core/java/com/android/internal/util/Protocol.java +++ b/core/java/com/android/internal/util/Protocol.java @@ -44,6 +44,7 @@ public class Protocol { public static final int BASE_WIFI_P2P_MANAGER = 0x00022000; public static final int BASE_WIFI_P2P_SERVICE = 0x00023000; public static final int BASE_WIFI_MONITOR = 0x00024000; + public static final int BASE_WIFI_MANAGER = 0x00025000; public static final int BASE_DHCP = 0x00030000; public static final int BASE_DATA_CONNECTION = 0x00040000; public static final int BASE_DATA_CONNECTION_AC = 0x00041000; diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java index d375d4c..259f15f 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java @@ -94,6 +94,7 @@ public class ConnectivityManagerTestActivity extends Activity { * Control Wifi States */ public WifiManager mWifiManager; + public WifiManager.Channel mChannel; /* * Verify connectivity state @@ -240,7 +241,7 @@ public class ConnectivityManagerTestActivity extends Activity { mCM = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); // Get an instance of WifiManager mWifiManager =(WifiManager)getSystemService(Context.WIFI_SERVICE); - mWifiManager.asyncConnect(this, new WifiServiceHandler()); + mChannel = mWifiManager.initialize(mContext, mContext.getMainLooper(), null); initializeNetworkStates(); @@ -594,7 +595,14 @@ public class ConnectivityManagerTestActivity extends Activity { log("found " + ssid + " in the scan result list"); log("retry: " + retry); foundApInScanResults = true; - mWifiManager.connectNetwork(config); + mWifiManager.connect(mChannel, config, + new WifiManager.ActionListener() { + public void onSuccess() { + } + public void onFailure(int reason) { + log("connect failure " + reason); + } + }); break; } } @@ -641,7 +649,13 @@ public class ConnectivityManagerTestActivity extends Activity { for (WifiConfiguration wifiConfig: wifiConfigList) { log("remove wifi configuration: " + wifiConfig.networkId); int netId = wifiConfig.networkId; - mWifiManager.forgetNetwork(netId); + mWifiManager.forget(mChannel, netId, new WifiManager.ActionListener() { + public void onSuccess() { + } + public void onFailure(int reason) { + log("Failed to forget " + reason); + } + }); } return true; } diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java index d33a445..8d73bc0 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java @@ -63,6 +63,7 @@ public class WifiConnectionTest private ConnectivityManagerTestActivity mAct; private ConnectivityManagerTestRunner mRunner; private WifiManager mWifiManager = null; + private WifiManager.Channel mChannel; private Set<WifiConfiguration> enabledNetworks = null; public WifiConnectionTest() { @@ -76,7 +77,8 @@ public class WifiConnectionTest mWifiManager = (WifiManager) mRunner.getContext().getSystemService(Context.WIFI_SERVICE); mAct = getActivity(); - mWifiManager.asyncConnect(mAct, new WifiServiceHandler()); + mChannel = mWifiManager.initialize(mAct, mAct.getMainLooper(), null); + networks = mAct.loadNetworkConfigurations(); if (DEBUG) { printNetworkConfigurations(); diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java index 8d778c4..e799d15 100644 --- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java +++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java @@ -74,6 +74,7 @@ public class ConnectionUtil { private int mWifiState; private NetworkInfo mWifiNetworkInfo; private WifiManager mWifiManager; + private WifiManager.Channel mChannel; private Context mContext; // Verify connectivity state private static final int NUM_NETWORK_TYPES = ConnectivityManager.MAX_NETWORK_TYPE + 1; @@ -114,7 +115,7 @@ public class ConnectionUtil { // Get an instance of WifiManager mWifiManager =(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE); - mWifiManager.asyncConnect(mContext, new WifiServiceHandler()); + mChannel = mWifiManager.initialize(mContext, mContext.getMainLooper(), null); mDownloadManager = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE); @@ -567,7 +568,14 @@ public class ConnectionUtil { Log.v(LOG_TAG, "Found " + ssid + " in the scan result list."); Log.v(LOG_TAG, "Retry: " + retry); foundApInScanResults = true; - mWifiManager.connectNetwork(config); + mWifiManager.connect(mChannel, config, new WifiManager.ActionListener() { + public void onSuccess() { + } + public void onFailure(int reason) { + Log.e(LOG_TAG, "connect failed " + reason); + } + }); + break; } } @@ -614,7 +622,13 @@ public class ConnectionUtil { for (WifiConfiguration wifiConfig: wifiConfigList) { Log.v(LOG_TAG, "Remove wifi configuration: " + wifiConfig.networkId); int netId = wifiConfig.networkId; - mWifiManager.forgetNetwork(netId); + mWifiManager.forget(mChannel, netId, new WifiManager.ActionListener() { + public void onSuccess() { + } + public void onFailure(int reason) { + Log.e(LOG_TAG, "forget failed " + reason); + } + }); } return true; } @@ -723,4 +737,4 @@ public class ConnectionUtil { } return false; } -}
\ No newline at end of file +} diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index f09c43f..6b4c895 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -263,47 +263,42 @@ public class WifiService extends IWifiManager.Stub { ac.connect(mContext, this, msg.replyTo); break; } - case WifiManager.CMD_ENABLE_TRAFFIC_STATS_POLL: { + case WifiManager.ENABLE_TRAFFIC_STATS_POLL: { mEnableTrafficStatsPoll = (msg.arg1 == 1); mTrafficStatsPollToken++; if (mEnableTrafficStatsPoll) { notifyOnDataActivity(); - sendMessageDelayed(Message.obtain(this, WifiManager.CMD_TRAFFIC_STATS_POLL, + sendMessageDelayed(Message.obtain(this, WifiManager.TRAFFIC_STATS_POLL, mTrafficStatsPollToken, 0), POLL_TRAFFIC_STATS_INTERVAL_MSECS); } break; } - case WifiManager.CMD_TRAFFIC_STATS_POLL: { + case WifiManager.TRAFFIC_STATS_POLL: { if (msg.arg1 == mTrafficStatsPollToken) { notifyOnDataActivity(); - sendMessageDelayed(Message.obtain(this, WifiManager.CMD_TRAFFIC_STATS_POLL, + sendMessageDelayed(Message.obtain(this, WifiManager.TRAFFIC_STATS_POLL, mTrafficStatsPollToken, 0), POLL_TRAFFIC_STATS_INTERVAL_MSECS); } break; } - case WifiManager.CMD_CONNECT_NETWORK: { - if (msg.obj != null) { - mWifiStateMachine.connectNetwork((WifiConfiguration)msg.obj); - } else { - mWifiStateMachine.connectNetwork(msg.arg1); - } + case WifiManager.CONNECT_NETWORK: { + mWifiStateMachine.sendMessage(Message.obtain(msg)); break; } - case WifiManager.CMD_SAVE_NETWORK: { - mWifiStateMachine.saveNetwork((WifiConfiguration)msg.obj); + case WifiManager.SAVE_NETWORK: { + mWifiStateMachine.sendMessage(Message.obtain(msg)); break; } - case WifiManager.CMD_FORGET_NETWORK: { - mWifiStateMachine.forgetNetwork(msg.arg1); + case WifiManager.FORGET_NETWORK: { + mWifiStateMachine.sendMessage(Message.obtain(msg)); break; } - case WifiManager.CMD_START_WPS: { - //replyTo has the original source - mWifiStateMachine.startWps(msg.replyTo, (WpsInfo)msg.obj); + case WifiManager.START_WPS: { + mWifiStateMachine.sendMessage(Message.obtain(msg)); break; } - case WifiManager.CMD_DISABLE_NETWORK: { - mWifiStateMachine.disableNetwork(msg.replyTo, msg.arg1, msg.arg2); + case WifiManager.DISABLE_NETWORK: { + mWifiStateMachine.sendMessage(Message.obtain(msg)); break; } default: { @@ -1594,10 +1589,10 @@ public class WifiService extends IWifiManager.Stub { Message msg; if (mNetworkInfo.getDetailedState() == DetailedState.CONNECTED && !mScreenOff) { msg = Message.obtain(mAsyncServiceHandler, - WifiManager.CMD_ENABLE_TRAFFIC_STATS_POLL, 1, 0); + WifiManager.ENABLE_TRAFFIC_STATS_POLL, 1, 0); } else { msg = Message.obtain(mAsyncServiceHandler, - WifiManager.CMD_ENABLE_TRAFFIC_STATS_POLL, 0, 0); + WifiManager.ENABLE_TRAFFIC_STATS_POLL, 0, 0); } msg.sendToTarget(); } diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java index 104a02d..6aeac5f 100644 --- a/wifi/java/android/net/wifi/SupplicantStateTracker.java +++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java @@ -175,7 +175,7 @@ class SupplicantStateTracker extends StateMachine { case WifiStateMachine.CMD_RESET_SUPPLICANT_STATE: transitionTo(mUninitializedState); break; - case WifiStateMachine.CMD_CONNECT_NETWORK: + case WifiManager.CONNECT_NETWORK: mNetworksDisabledDuringConnect = true; break; default: diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java index 5dffa60..8305714 100644 --- a/wifi/java/android/net/wifi/WifiConfigStore.java +++ b/wifi/java/android/net/wifi/WifiConfigStore.java @@ -261,6 +261,7 @@ class WifiConfigStore { * Add/update the specified configuration and save config * * @param config WifiConfiguration to be saved + * @return network update result */ NetworkUpdateResult saveNetwork(WifiConfiguration config) { boolean newNetwork = (config.networkId == INVALID_NETWORK_ID); @@ -298,8 +299,9 @@ class WifiConfigStore { * Forget the specified network and save config * * @param netId network to forget + * @return {@code true} if it succeeds, {@code false} otherwise */ - void forgetNetwork(int netId) { + boolean forgetNetwork(int netId) { if (mWifiNative.removeNetwork(netId)) { mWifiNative.saveConfig(); WifiConfiguration config = mConfiguredNetworks.get(netId); @@ -309,8 +311,10 @@ class WifiConfigStore { } writeIpAndProxyConfigurations(); sendConfiguredNetworksChangedBroadcast(); + return true; } else { loge("Failed to remove network " + netId); + return false; } } @@ -321,6 +325,7 @@ class WifiConfigStore { * state machine * * @param config wifi configuration to add/update + * @return network Id */ int addOrUpdateNetwork(WifiConfiguration config) { NetworkUpdateResult result = addOrUpdateNetworkNative(config); @@ -335,6 +340,7 @@ class WifiConfigStore { * state machine for network removal * * @param netId network to be removed + * @return {@code true} if it succeeds, {@code false} otherwise */ boolean removeNetwork(int netId) { boolean ret = mWifiNative.removeNetwork(netId); @@ -356,6 +362,7 @@ class WifiConfigStore { * state machine for connecting to a network * * @param netId network to be removed + * @return {@code true} if it succeeds, {@code false} otherwise */ boolean enableNetwork(int netId, boolean disableOthers) { boolean ret = enableNetworkWithoutBroadcast(netId, disableOthers); @@ -378,6 +385,7 @@ class WifiConfigStore { /** * Disable a network. Note that there is no saveConfig operation. * @param netId network to be disabled + * @return {@code true} if it succeeds, {@code false} otherwise */ boolean disableNetwork(int netId) { return disableNetwork(netId, WifiConfiguration.DISABLED_UNKNOWN_REASON); @@ -387,6 +395,7 @@ class WifiConfigStore { * Disable a network. Note that there is no saveConfig operation. * @param netId network to be disabled * @param reason reason code network was disabled + * @return {@code true} if it succeeds, {@code false} otherwise */ boolean disableNetwork(int netId, int reason) { boolean ret = mWifiNative.disableNetwork(netId); @@ -402,6 +411,7 @@ class WifiConfigStore { /** * Save the configured networks in supplicant to disk + * @return {@code true} if it succeeds, {@code false} otherwise */ boolean saveConfig() { return mWifiNative.saveConfig(); @@ -410,6 +420,8 @@ class WifiConfigStore { /** * Start WPS pin method configuration with pin obtained * from the access point + * @param config WPS configuration + * @return Wps result containing status and pin */ WpsResult startWpsWithPinFromAccessPoint(WpsInfo config) { WpsResult result = new WpsResult(); @@ -445,6 +457,8 @@ class WifiConfigStore { /** * Start WPS push button configuration + * @param config WPS configuration + * @return WpsResult indicating status and pin */ WpsResult startWpsPbc(WpsInfo config) { WpsResult result = new WpsResult(); @@ -461,6 +475,7 @@ class WifiConfigStore { /** * Fetch the link properties for a given network id + * @return LinkProperties for the given network id */ LinkProperties getLinkProperties(int netId) { WifiConfiguration config = mConfiguredNetworks.get(netId); @@ -474,6 +489,7 @@ class WifiConfigStore { * right now until NetworkUtils is fixed. When we do * that, we should remove handling DhcpInfo and move * to using LinkProperties + * @return DhcpInfoInternal for the given network id */ DhcpInfoInternal getIpConfiguration(int netId) { DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal(); @@ -516,6 +532,7 @@ class WifiConfigStore { /** * clear IP configuration for a given network id + * @param network id */ void clearIpConfiguration(int netId) { WifiConfiguration config = mConfiguredNetworks.get(netId); @@ -530,6 +547,8 @@ class WifiConfigStore { /** * Fetch the proxy properties for a given network id + * @param network id + * @return ProxyProperties for the network id */ ProxyProperties getProxyProperties(int netId) { LinkProperties linkProperties = getLinkProperties(netId); @@ -541,6 +560,8 @@ class WifiConfigStore { /** * Return if the specified network is using static IP + * @param network id + * @return {@code true} if using static ip for netId */ boolean isUsingStaticIp(int netId) { WifiConfiguration config = mConfiguredNetworks.get(netId); @@ -599,16 +620,6 @@ class WifiConfigStore { sendConfiguredNetworksChangedBroadcast(); } - void updateIpAndProxyFromWpsConfig(int netId, WpsInfo wpsConfig) { - WifiConfiguration config = mConfiguredNetworks.get(netId); - if (config != null) { - config.ipAssignment = wpsConfig.ipAssignment; - config.proxySettings = wpsConfig.proxySettings; - config.linkProperties = wpsConfig.linkProperties; - writeIpAndProxyConfigurations(); - } - } - /* Mark all networks except specified netId as disabled */ private void markAllNetworksDisabledExcept(int netId) { for(WifiConfiguration config : mConfiguredNetworks.values()) { diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 1acfd3a..bdee12a 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -23,11 +23,15 @@ import android.net.DhcpInfo; import android.os.Binder; import android.os.IBinder; import android.os.Handler; +import android.os.Looper; +import android.os.Message; import android.os.RemoteException; import android.os.WorkSource; import android.os.Messenger; +import android.util.SparseArray; import com.android.internal.util.AsyncChannel; +import com.android.internal.util.Protocol; import java.util.List; @@ -289,24 +293,6 @@ public class WifiManager { public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError"; /** - * Broadcast intent action for reporting errors - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ERROR_ACTION = "android.net.wifi.ERROR"; - /** - * The type of error being reported - * @hide - */ - public static final String EXTRA_ERROR_CODE = "errorCode"; - - /** - * Valid error codes - * @hide - */ - public static final int WPS_OVERLAP_ERROR = 1; - - /** * Broadcast intent action indicating that the configured networks changed. * This can be as a result of adding/updating/deleting a network * @hide @@ -466,9 +452,6 @@ public class WifiManager { /* Number of currently active WifiLocks and MulticastLocks */ private int mActiveLockCount; - /* For communication with WifiService */ - private AsyncChannel mAsyncChannel = new AsyncChannel(); - /** * Create a new WifiManager instance. * Applications will almost always want to use @@ -622,17 +605,6 @@ public class WifiManager { } /** - * Disable a configured network asynchronously. This call is for abnormal network - * events, and the user may be notified of network change, if they recently attempted - * to connect to the specified network. - * @param netId the ID of the network as returned by {@link #addNetwork}. - * @hide - */ - public void disableNetwork(int netId, int reason) { - mAsyncChannel.sendMessage(CMD_DISABLE_NETWORK, netId, reason); - } - - /** * Disassociate from the currently active access point. This may result * in the asynchronous delivery of state change events. * @return {@code true} if the operation succeeded @@ -1067,37 +1039,237 @@ public class WifiManager { /* TODO: deprecate synchronous API and open up the following API */ + private static final int BASE = Protocol.BASE_WIFI_MANAGER; + /* Commands to WifiService */ /** @hide */ - public static final int CMD_CONNECT_NETWORK = 1; + public static final int CONNECT_NETWORK = BASE + 1; + /** @hide */ + public static final int CONNECT_NETWORK_FAILED = BASE + 2; + /** @hide */ + public static final int CONNECT_NETWORK_SUCCEEDED = BASE + 3; + + /** @hide */ + public static final int FORGET_NETWORK = BASE + 4; + /** @hide */ + public static final int FORGET_NETWORK_FAILED = BASE + 5; + /** @hide */ + public static final int FORGET_NETWORK_SUCCEEDED = BASE + 6; + + /** @hide */ + public static final int SAVE_NETWORK = BASE + 7; + /** @hide */ + public static final int SAVE_NETWORK_FAILED = BASE + 8; /** @hide */ - public static final int CMD_FORGET_NETWORK = 2; + public static final int SAVE_NETWORK_SUCCEEDED = BASE + 9; + /** @hide */ - public static final int CMD_SAVE_NETWORK = 3; + public static final int START_WPS = BASE + 10; /** @hide */ - public static final int CMD_START_WPS = 4; + public static final int START_WPS_SUCCEEDED = BASE + 11; /** @hide */ - public static final int CMD_DISABLE_NETWORK = 5; + public static final int WPS_FAILED = BASE + 12; + /** @hide */ + public static final int WPS_COMPLETED = BASE + 13; - /* Events from WifiService */ /** @hide */ - public static final int CMD_WPS_COMPLETED = 11; + public static final int DISABLE_NETWORK = BASE + 14; + /** @hide */ + public static final int DISABLE_NETWORK_FAILED = BASE + 15; + /** @hide */ + public static final int DISABLE_NETWORK_SUCCEEDED = BASE + 16; /* For system use only */ /** @hide */ - public static final int CMD_ENABLE_TRAFFIC_STATS_POLL = 21; + public static final int ENABLE_TRAFFIC_STATS_POLL = BASE + 21; /** @hide */ - public static final int CMD_TRAFFIC_STATS_POLL = 22; + public static final int TRAFFIC_STATS_POLL = BASE + 22; + + + /** + * Passed with {@link ActionListener#onFailure}. + * Indicates that the operation failed due to an internal error. + * @hide + */ + public static final int ERROR = 0; + + /** + * Passed with {@link ActionListener#onFailure}. + * Indicates that the operation is already in progress + * @hide + */ + public static final int IN_PROGRESS = 1; /** - * Initiate an asynchronous channel connection setup + * Passed with {@link ActionListener#onFailure}. + * Indicates that the operation failed because the framework is busy and + * unable to service the request + * @hide + */ + public static final int BUSY = 2; + + /* WPS specific errors */ + /** WPS overlap detected {@hide} */ + public static final int WPS_OVERLAP_ERROR = 3; + + /** Interface for callback invocation when framework channel is lost {@hide} */ + public interface ChannelListener { + /** + * The channel to the framework has been disconnected. + * Application could try re-initializing using {@link #initialize} + */ + public void onChannelDisconnected(); + } + + /** Interface for callback invocation on an application action {@hide} */ + public interface ActionListener { + /** The operation succeeded */ + public void onSuccess(); + /** + * The operation failed + * @param reason The reason for failure could be one of + * {@link #ERROR}, {@link #IN_PROGRESS} or {@link #BUSY} + */ + public void onFailure(int reason); + } + + /** Interface for callback invocation on a start WPS action {@hide} */ + public interface WpsListener { + /** WPS start succeeded */ + public void onStartSuccess(String pin); + + /** WPS operation completed succesfully */ + public void onCompletion(); + + /** + * WPS operation failed + * @param reason The reason for failure could be one of + * {@link #IN_PROGRESS}, {@link #WPS_OVERLAP_ERROR},{@link #ERROR} or {@link #BUSY} + */ + public void onFailure(int reason); + } + + /** + * A channel that connects the application to the Wifi framework. + * Most operations require a Channel as an argument. An instance of Channel is obtained + * by doing a call on {@link #initialize} + * @hide + */ + public static class Channel { + Channel(Looper looper, ChannelListener l) { + mAsyncChannel = new AsyncChannel(); + mHandler = new WifiHandler(looper); + mChannelListener = l; + } + private ChannelListener mChannelListener; + private SparseArray<Object> mListenerMap = new SparseArray<Object>(); + private Object mListenerMapLock = new Object(); + private int mListenerKey = 0; + + AsyncChannel mAsyncChannel; + WifiHandler mHandler; + class WifiHandler extends Handler { + WifiHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message message) { + Object listener = removeListener(message.arg2); + switch (message.what) { + case AsyncChannel.CMD_CHANNEL_DISCONNECTED: + if (mChannelListener != null) { + mChannelListener.onChannelDisconnected(); + mChannelListener = null; + } + break; + /* ActionListeners grouped together */ + case WifiManager.CONNECT_NETWORK_FAILED: + case WifiManager.FORGET_NETWORK_FAILED: + case WifiManager.SAVE_NETWORK_FAILED: + case WifiManager.DISABLE_NETWORK_FAILED: + if (listener != null) { + ((ActionListener) listener).onFailure(message.arg1); + } + break; + /* ActionListeners grouped together */ + case WifiManager.CONNECT_NETWORK_SUCCEEDED: + case WifiManager.FORGET_NETWORK_SUCCEEDED: + case WifiManager.SAVE_NETWORK_SUCCEEDED: + case WifiManager.DISABLE_NETWORK_SUCCEEDED: + if (listener != null) { + ((ActionListener) listener).onSuccess(); + } + break; + case WifiManager.START_WPS_SUCCEEDED: + if (listener != null) { + WpsResult result = (WpsResult) message.obj; + ((WpsListener) listener).onStartSuccess(result.pin); + //Listener needs to stay until completion or failure + synchronized(mListenerMapLock) { + mListenerMap.put(message.arg2, listener); + } + } + break; + case WifiManager.WPS_COMPLETED: + if (listener != null) { + ((WpsListener) listener).onCompletion(); + } + break; + case WifiManager.WPS_FAILED: + if (listener != null) { + ((WpsListener) listener).onFailure(message.arg1); + } + break; + default: + //ignore + break; + } + } + } + + int putListener(Object listener) { + if (listener == null) return 0; + int key; + synchronized (mListenerMapLock) { + key = mListenerKey++; + mListenerMap.put(key, listener); + } + return key; + } + + Object removeListener(int key) { + synchronized (mListenerMapLock) { + Object listener = mListenerMap.get(key); + mListenerMap.remove(key); + return listener; + } + } + } + + /** + * Registers the application with the Wi-Fi framework. This function + * must be the first to be called before any Wi-Fi operations are performed. + * * @param srcContext is the context of the source - * @param srcHandler is the handler on which the source receives messages + * @param srcLooper is the Looper on which the callbacks are receivied + * @param listener for callback at loss of framework communication. Can be null. + * @return Channel instance that is necessary for performing any further Wi-Fi operations. + * A null is returned upon failure to initialize. * @hide */ - public void asyncConnect(Context srcContext, Handler srcHandler) { - mAsyncChannel.connect(srcContext, srcHandler, getWifiServiceMessenger()); - } + public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) { + Messenger messenger = getWifiServiceMessenger(); + if (messenger == null) return null; + + Channel c = new Channel(srcLooper, listener); + if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger) + == AsyncChannel.STATUS_SUCCESSFUL) { + return c; + } else { + return null; + } + } /** * Connect to a network with the given configuration. The network also @@ -1107,15 +1279,17 @@ public class WifiManager { * sequence of addNetwork(), enableNetwork(), saveConfiguration() and * reconnect() * + * @param c is the channel created at {@link #initialize} * @param config the set of variables that describe the configuration, * contained in a {@link WifiConfiguration} object. + * @param listener for callbacks on success or failure. Can be null. * @hide */ - public void connectNetwork(WifiConfiguration config) { - if (config == null) { - return; - } - mAsyncChannel.sendMessage(CMD_CONNECT_NETWORK, config); + public void connect(Channel c, WifiConfiguration config, ActionListener listener) { + if (c == null) throw new IllegalArgumentException("Channel needs to be initialized"); + if (config == null) throw new IllegalArgumentException("config cannot be null"); + + c.mAsyncChannel.sendMessage(CONNECT_NETWORK, 0, c.putListener(listener), config); } /** @@ -1124,15 +1298,17 @@ public class WifiManager { * This function is used instead of a enableNetwork(), saveConfiguration() and * reconnect() * + * @param c is the channel created at {@link #initialize} * @param networkId the network id identifiying the network in the * supplicant configuration list + * @param listener for callbacks on success or failure. Can be null. * @hide */ - public void connectNetwork(int networkId) { - if (networkId < 0) { - return; - } - mAsyncChannel.sendMessage(CMD_CONNECT_NETWORK, networkId); + public void connect(Channel c, int networkId, ActionListener listener) { + if (c == null) throw new IllegalArgumentException("Channel needs to be initialized"); + if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative"); + + c.mAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, c.putListener(listener)); } /** @@ -1146,16 +1322,17 @@ public class WifiManager { * For an existing network, it accomplishes the task of updateNetwork() * and saveConfiguration() * + * @param c is the channel created at {@link #initialize} * @param config the set of variables that describe the configuration, * contained in a {@link WifiConfiguration} object. + * @param listener for callbacks on success or failure. Can be null. * @hide */ - public void saveNetwork(WifiConfiguration config) { - if (config == null) { - return; - } + public void save(Channel c, WifiConfiguration config, ActionListener listener) { + if (c == null) throw new IllegalArgumentException("Channel needs to be initialized"); + if (config == null) throw new IllegalArgumentException("config cannot be null"); - mAsyncChannel.sendMessage(CMD_SAVE_NETWORK, config); + c.mAsyncChannel.sendMessage(SAVE_NETWORK, 0, c.putListener(listener), config); } /** @@ -1164,30 +1341,47 @@ public class WifiManager { * This function is used instead of a sequence of removeNetwork() * and saveConfiguration(). * + * @param c is the channel created at {@link #initialize} * @param config the set of variables that describe the configuration, * contained in a {@link WifiConfiguration} object. + * @param listener for callbacks on success or failure. Can be null. * @hide */ - public void forgetNetwork(int netId) { - if (netId < 0) { - return; - } + public void forget(Channel c, int netId, ActionListener listener) { + if (c == null) throw new IllegalArgumentException("Channel needs to be initialized"); + if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); - mAsyncChannel.sendMessage(CMD_FORGET_NETWORK, netId); + c.mAsyncChannel.sendMessage(FORGET_NETWORK, netId, c.putListener(listener)); + } + + /** + * Disable network + * + * @param c is the channel created at {@link #initialize} + * @param netId is the network Id + * @param listener for callbacks on success or failure. Can be null. + * @hide + */ + public void disable(Channel c, int netId, ActionListener listener) { + if (c == null) throw new IllegalArgumentException("Channel needs to be initialized"); + if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); + + c.mAsyncChannel.sendMessage(DISABLE_NETWORK, netId, c.putListener(listener)); } /** * Start Wi-fi Protected Setup * + * @param c is the channel created at {@link #initialize} * @param config WPS configuration + * @param listener for callbacks on success or failure. Can be null. * @hide */ - public void startWps(WpsInfo config) { - if (config == null) { - return; - } + public void startWps(Channel c, WpsInfo config, WpsListener listener) { + if (c == null) throw new IllegalArgumentException("Channel needs to be initialized"); + if (config == null) throw new IllegalArgumentException("config cannot be null"); - mAsyncChannel.sendMessage(CMD_START_WPS, config); + c.mAsyncChannel.sendMessage(START_WPS, 0, c.putListener(listener), config); } /** diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java index d05e0b8..e1cfba3 100644 --- a/wifi/java/android/net/wifi/WifiMonitor.java +++ b/wifi/java/android/net/wifi/WifiMonitor.java @@ -64,7 +64,10 @@ public class WifiMonitor { "pre-shared key may be incorrect"; /* WPS events */ + private static final String WPS_SUCCESS_STR = "WPS-SUCCESS"; + private static final String WPS_FAIL_STR = "WPS-FAIL"; private static final String WPS_OVERLAP_STR = "WPS-OVERLAP-DETECTED"; + private static final String WPS_TIMEOUT_STR = "WPS-TIMEOUT"; /** * Names of events from wpa_supplicant (minus the prefix). In the @@ -221,10 +224,16 @@ public class WifiMonitor { public static final int SUPPLICANT_STATE_CHANGE_EVENT = BASE + 6; /* Password failure and EAP authentication failure */ public static final int AUTHENTICATION_FAILURE_EVENT = BASE + 7; - /* WPS overlap detected */ - public static final int WPS_OVERLAP_EVENT = BASE + 8; + /* WPS success detected */ + public static final int WPS_SUCCESS_EVENT = BASE + 8; + /* WPS failure detected */ + public static final int WPS_FAIL_EVENT = BASE + 9; + /* WPS overlap detected */ + public static final int WPS_OVERLAP_EVENT = BASE + 10; + /* WPS timeout detected */ + public static final int WPS_TIMEOUT_EVENT = BASE + 11; /* Driver was hung */ - public static final int DRIVER_HUNG_EVENT = BASE + 9; + public static final int DRIVER_HUNG_EVENT = BASE + 12; /* P2P events */ public static final int P2P_DEVICE_FOUND_EVENT = BASE + 21; @@ -304,8 +313,14 @@ public class WifiMonitor { if (eventStr.startsWith(WPA_EVENT_PREFIX_STR) && 0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR)) { mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT); + } else if (eventStr.startsWith(WPS_SUCCESS_STR)) { + mStateMachine.sendMessage(WPS_SUCCESS_EVENT); + } else if (eventStr.startsWith(WPS_FAIL_STR)) { + mStateMachine.sendMessage(WPS_FAIL_EVENT); } else if (eventStr.startsWith(WPS_OVERLAP_STR)) { mStateMachine.sendMessage(WPS_OVERLAP_EVENT); + } else if (eventStr.startsWith(WPS_TIMEOUT_STR)) { + mStateMachine.sendMessage(WPS_TIMEOUT_EVENT); } else if (eventStr.startsWith(P2P_EVENT_PREFIX_STR)) { handleP2pEvents(eventStr); } else if (eventStr.startsWith(HOST_AP_EVENT_PREFIX_STR)) { diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index e140d80..d6988cd 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -184,7 +184,6 @@ public class WifiStateMachine extends StateMachine { private WifiInfo mWifiInfo; private NetworkInfo mNetworkInfo; private SupplicantStateTracker mSupplicantStateTracker; - private WpsStateMachine mWpsStateMachine; private DhcpStateMachine mDhcpStateMachine; private AlarmManager mAlarmManager; @@ -275,16 +274,14 @@ public class WifiStateMachine extends StateMachine { static final int CMD_ENABLE_NETWORK = BASE + 54; /* Enable all networks */ static final int CMD_ENABLE_ALL_NETWORKS = BASE + 55; - /* Disable a network. The device does not attempt a connection to the given network. */ - static final int CMD_DISABLE_NETWORK = BASE + 56; /* Blacklist network. De-prioritizes the given BSSID for connection. */ - static final int CMD_BLACKLIST_NETWORK = BASE + 57; + static final int CMD_BLACKLIST_NETWORK = BASE + 56; /* Clear the blacklist network list */ - static final int CMD_CLEAR_BLACKLIST = BASE + 58; + static final int CMD_CLEAR_BLACKLIST = BASE + 57; /* Save configuration */ - static final int CMD_SAVE_CONFIG = BASE + 59; + static final int CMD_SAVE_CONFIG = BASE + 58; /* Get configured networks*/ - static final int CMD_GET_CONFIGURED_NETWORKS = BASE + 60; + static final int CMD_GET_CONFIGURED_NETWORKS = BASE + 59; /* Supplicant commands after driver start*/ /* Initiate a scan */ @@ -328,28 +325,7 @@ public class WifiStateMachine extends StateMachine { static final int MULTICAST_V6 = 1; static final int MULTICAST_V4 = 0; - /* Connect to a specified network (network id - * or WifiConfiguration) This involves increasing - * the priority of the network, enabling the network - * (while disabling others) and issuing a reconnect. - * Note that CMD_RECONNECT just does a reconnect to - * an existing network. All the networks get enabled - * upon a successful connection or a failure. - */ - static final int CMD_CONNECT_NETWORK = BASE + 86; - /* Save the specified network. This involves adding - * an enabled network (if new) and updating the - * config and issuing a save on supplicant config. - */ - static final int CMD_SAVE_NETWORK = BASE + 87; - /* Delete the specified network. This involves - * removing the network and issuing a save on - * supplicant config. - */ - static final int CMD_FORGET_NETWORK = BASE + 88; - /* Start Wi-Fi protected setup */ - static final int CMD_START_WPS = BASE + 89; - /* Set the frequency band */ + /* Set the frequency band */ static final int CMD_SET_FREQUENCY_BAND = BASE + 90; /* Enable background scan for configured networks */ static final int CMD_ENABLE_BACKGROUND_SCAN = BASE + 91; @@ -358,12 +334,6 @@ public class WifiStateMachine extends StateMachine { /* Reset the supplicant state tracker */ static final int CMD_RESET_SUPPLICANT_STATE = BASE + 111; - /* Commands/events reported by WpsStateMachine */ - /* Indicates the completion of WPS activity */ - static final int WPS_COMPLETED_EVENT = BASE + 121; - /* Reset the WPS state machine */ - static final int CMD_RESET_WPS_STATE = BASE + 122; - /* P2p commands */ public static final int CMD_ENABLE_P2P = BASE + 131; public static final int CMD_DISABLE_P2P = BASE + 132; @@ -476,7 +446,7 @@ public class WifiStateMachine extends StateMachine { /* Network is not connected, supplicant assoc+auth is not complete */ private State mDisconnectedState = new DisconnectedState(); /* Waiting for WPS to be completed*/ - private State mWaitForWpsCompletionState = new WaitForWpsCompletionState(); + private State mWpsRunningState = new WpsRunningState(); /* Soft ap is starting up */ private State mSoftApStartingState = new SoftApStartingState(); @@ -570,7 +540,6 @@ public class WifiStateMachine extends StateMachine { mWifiInfo = new WifiInfo(); mSupplicantStateTracker = new SupplicantStateTracker(context, this, mWifiConfigStore, getHandler()); - mWpsStateMachine = new WpsStateMachine(context, this, mWifiConfigStore, getHandler()); mLinkProperties = new LinkProperties(); WifiApConfigStore wifiApConfigStore = WifiApConfigStore.makeWifiApConfigStore( @@ -639,7 +608,7 @@ public class WifiStateMachine extends StateMachine { addState(mConnectedState, mL2ConnectedState); addState(mDisconnectingState, mConnectModeState); addState(mDisconnectedState, mConnectModeState); - addState(mWaitForWpsCompletionState, mConnectModeState); + addState(mWpsRunningState, mConnectModeState); addState(mDriverStoppingState, mSupplicantStartedState); addState(mDriverStoppedState, mSupplicantStartedState); addState(mSupplicantStoppingState, mDefaultState); @@ -908,9 +877,8 @@ public class WifiStateMachine extends StateMachine { * @return {@code true} if the operation succeeds, {@code false} otherwise */ public boolean syncDisableNetwork(AsyncChannel channel, int netId) { - Message resultMsg = channel.sendMessageSynchronously(CMD_DISABLE_NETWORK, netId, - WifiConfiguration.DISABLED_UNKNOWN_REASON); - boolean result = (resultMsg.arg1 != FAILURE); + Message resultMsg = channel.sendMessageSynchronously(WifiManager.DISABLE_NETWORK, netId); + boolean result = (resultMsg.arg1 != WifiManager.DISABLE_NETWORK_FAILED); resultMsg.recycle(); return result; } @@ -933,39 +901,6 @@ public class WifiStateMachine extends StateMachine { sendMessage(obtainMessage(CMD_CLEAR_BLACKLIST)); } - public void connectNetwork(int netId) { - sendMessage(obtainMessage(CMD_CONNECT_NETWORK, netId, 0)); - } - - public void connectNetwork(WifiConfiguration wifiConfig) { - /* arg1 is used to indicate netId, force a netId value of - * WifiConfiguration.INVALID_NETWORK_ID when we are passing - * a configuration since the default value of 0 is a valid netId - */ - sendMessage(obtainMessage(CMD_CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID, - 0, wifiConfig)); - } - - public void saveNetwork(WifiConfiguration wifiConfig) { - sendMessage(obtainMessage(CMD_SAVE_NETWORK, wifiConfig)); - } - - public void forgetNetwork(int netId) { - sendMessage(obtainMessage(CMD_FORGET_NETWORK, netId, 0)); - } - - public void disableNetwork(Messenger replyTo, int netId, int reason) { - Message message = obtainMessage(CMD_DISABLE_NETWORK, netId, reason); - message.replyTo = replyTo; - sendMessage(message); - } - - public void startWps(Messenger replyTo, WpsInfo config) { - Message msg = obtainMessage(CMD_START_WPS, config); - msg.replyTo = replyTo; - sendMessage(msg); - } - public void enableRssiPolling(boolean enabled) { sendMessage(obtainMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0)); } @@ -1563,13 +1498,6 @@ public class WifiStateMachine extends StateMachine { mContext.sendStickyBroadcast(intent); } - private void sendErrorBroadcast(int errorCode) { - Intent intent = new Intent(WifiManager.ERROR_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(WifiManager.EXTRA_ERROR_CODE, errorCode); - mContext.sendBroadcast(intent); - } - private void sendLinkConfigurationChangedBroadcast() { Intent intent = new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); @@ -1626,7 +1554,6 @@ public class WifiStateMachine extends StateMachine { } mSupplicantStateTracker.sendMessage(Message.obtain(message)); - mWpsStateMachine.sendMessage(Message.obtain(message)); return state; } @@ -1836,14 +1763,13 @@ public class WifiStateMachine extends StateMachine { /* Synchronous call returns */ case CMD_PING_SUPPLICANT: case CMD_ENABLE_NETWORK: - case CMD_DISABLE_NETWORK: case CMD_ADD_OR_UPDATE_NETWORK: case CMD_REMOVE_NETWORK: case CMD_SAVE_CONFIG: - mReplyChannel.replyToMessage(message, message.what, FAILURE); + replyToMessage(message, message.what, FAILURE); break; case CMD_GET_CONFIGURED_NETWORKS: - mReplyChannel.replyToMessage(message, message.what, + replyToMessage(message, message.what, mWifiConfigStore.getConfiguredNetworks()); break; case CMD_ENABLE_RSSI_POLL: @@ -1886,9 +1812,6 @@ public class WifiStateMachine extends StateMachine { case CMD_SET_HIGH_PERF_MODE: case CMD_SET_COUNTRY_CODE: case CMD_SET_FREQUENCY_BAND: - case CMD_CONNECT_NETWORK: - case CMD_SAVE_NETWORK: - case CMD_FORGET_NETWORK: case CMD_RSSI_POLL: case CMD_ENABLE_ALL_NETWORKS: case DhcpStateMachine.CMD_PRE_DHCP_ACTION: @@ -1905,10 +1828,25 @@ public class WifiStateMachine extends StateMachine { setWifiEnabled(false); setWifiEnabled(true); break; - case CMD_START_WPS: - /* Return failure when the state machine cannot handle WPS initiation*/ - mReplyChannel.replyToMessage(message, WifiManager.CMD_WPS_COMPLETED, - new WpsResult(Status.FAILURE)); + case WifiManager.CONNECT_NETWORK: + replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, + WifiManager.BUSY); + break; + case WifiManager.FORGET_NETWORK: + replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, + WifiManager.BUSY); + break; + case WifiManager.SAVE_NETWORK: + replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, + WifiManager.BUSY); + break; + case WifiManager.START_WPS: + replyToMessage(message, WifiManager.WPS_FAILED, + WifiManager.BUSY); + break; + case WifiManager.DISABLE_NETWORK: + replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, + WifiManager.BUSY); break; default: loge("Error! unhandled message" + message); @@ -2222,7 +2160,6 @@ public class WifiStateMachine extends StateMachine { /* Reset the supplicant state to indicate the supplicant * state is not known at this time */ mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); - mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE); /* Initialize data structures */ mLastBssid = null; mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID; @@ -2306,7 +2243,6 @@ public class WifiStateMachine extends StateMachine { handleNetworkDisconnect(); sendSupplicantConnectionChangedBroadcast(false); mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); - mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE); transitionTo(mDriverLoadedState); sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); break; @@ -2318,20 +2254,20 @@ public class WifiStateMachine extends StateMachine { break; case CMD_PING_SUPPLICANT: boolean ok = mWifiNative.ping(); - mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); + replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); break; case CMD_ADD_OR_UPDATE_NETWORK: config = (WifiConfiguration) message.obj; - mReplyChannel.replyToMessage(message, CMD_ADD_OR_UPDATE_NETWORK, + replyToMessage(message, CMD_ADD_OR_UPDATE_NETWORK, mWifiConfigStore.addOrUpdateNetwork(config)); break; case CMD_REMOVE_NETWORK: ok = mWifiConfigStore.removeNetwork(message.arg1); - mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); + replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); break; case CMD_ENABLE_NETWORK: ok = mWifiConfigStore.enableNetwork(message.arg1, message.arg2 == 1); - mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); + replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); break; case CMD_ENABLE_ALL_NETWORKS: long time = android.os.SystemClock.elapsedRealtime(); @@ -2340,9 +2276,14 @@ public class WifiStateMachine extends StateMachine { mLastEnableAllNetworksTime = time; } break; - case CMD_DISABLE_NETWORK: - ok = mWifiConfigStore.disableNetwork(message.arg1, message.arg2); - mReplyChannel.replyToMessage(message, message.what, ok ? SUCCESS : FAILURE); + case WifiManager.DISABLE_NETWORK: + if (mWifiConfigStore.disableNetwork(message.arg1, + WifiConfiguration.DISABLED_UNKNOWN_REASON) == true) { + replyToMessage(message, WifiManager.DISABLE_NETWORK_SUCCEEDED); + } else { + replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED, + WifiManager.ERROR); + } break; case CMD_BLACKLIST_NETWORK: mWifiNative.addToBlacklist((String)message.obj); @@ -2352,7 +2293,7 @@ public class WifiStateMachine extends StateMachine { break; case CMD_SAVE_CONFIG: ok = mWifiConfigStore.saveConfig(); - mReplyChannel.replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE); + replyToMessage(message, CMD_SAVE_CONFIG, ok ? SUCCESS : FAILURE); // Inform the backup manager about a data change IBackupManager ibm = IBackupManager.Stub.asInterface( @@ -2373,12 +2314,25 @@ public class WifiStateMachine extends StateMachine { case CMD_SET_SCAN_MODE: mIsScanMode = (message.arg1 == SCAN_ONLY_MODE); break; - case CMD_SAVE_NETWORK: + case WifiManager.SAVE_NETWORK: config = (WifiConfiguration) message.obj; - mWifiConfigStore.saveNetwork(config); + NetworkUpdateResult result = mWifiConfigStore.saveNetwork(config); + if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) { + replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED); + } else { + loge("Failed to save network"); + replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, + WifiManager.ERROR); + } break; - case CMD_FORGET_NETWORK: - mWifiConfigStore.forgetNetwork(message.arg1); + case WifiManager.FORGET_NETWORK: + if (mWifiConfigStore.forgetNetwork(message.arg1)) { + replyToMessage(message, WifiManager.FORGET_NETWORK_SUCCEEDED); + } else { + loge("Failed to forget network"); + replyToMessage(message, WifiManager.FORGET_NETWORK_FAILED, + WifiManager.ERROR); + } break; default: return NOT_HANDLED; @@ -2417,7 +2371,6 @@ public class WifiStateMachine extends StateMachine { setWifiState(WIFI_STATE_DISABLING); sendSupplicantConnectionChangedBroadcast(false); mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); - mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE); } @Override public boolean processMessage(Message message) { @@ -2810,10 +2763,6 @@ public class WifiStateMachine extends StateMachine { case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: mSupplicantStateTracker.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT); break; - case WifiMonitor.WPS_OVERLAP_EVENT: - /* We just need to broadcast the error */ - sendErrorBroadcast(WifiManager.WPS_OVERLAP_ERROR); - break; case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: SupplicantState state = handleSupplicantStateChange(message); // Due to a WEXT bug, during the time of driver start/stop @@ -2850,7 +2799,7 @@ public class WifiStateMachine extends StateMachine { case CMD_REASSOCIATE: mWifiNative.reassociate(); break; - case CMD_CONNECT_NETWORK: + case WifiManager.CONNECT_NETWORK: int netId = message.arg1; WifiConfiguration config = (WifiConfiguration) message.obj; @@ -2868,15 +2817,44 @@ public class WifiStateMachine extends StateMachine { } /* The state tracker handles enabling networks upon completion/failure */ - mSupplicantStateTracker.sendMessage(CMD_CONNECT_NETWORK); + mSupplicantStateTracker.sendMessage(WifiManager.CONNECT_NETWORK); + + if (mWifiNative.reconnect()) { + replyToMessage(message, WifiManager.CONNECT_NETWORK_SUCCEEDED); + } else { + loge("Failed to initiate connection"); + replyToMessage(message, WifiManager.CONNECT_NETWORK_FAILED, + WifiManager.ERROR); + } - mWifiNative.reconnect(); /* Expect a disconnection from the old connection */ transitionTo(mDisconnectingState); break; - case CMD_START_WPS: - mWpsStateMachine.sendMessage(Message.obtain(message)); - transitionTo(mWaitForWpsCompletionState); + case WifiManager.START_WPS: + WpsInfo wpsInfo = (WpsInfo) message.obj; + WpsResult result; + switch (wpsInfo.setup) { + case WpsInfo.PBC: + result = mWifiConfigStore.startWpsPbc(wpsInfo); + break; + case WpsInfo.KEYPAD: + result = mWifiConfigStore.startWpsWithPinFromAccessPoint(wpsInfo); + break; + case WpsInfo.DISPLAY: + result = mWifiConfigStore.startWpsWithPinFromDevice(wpsInfo); + break; + default: + result = new WpsResult(Status.FAILURE); + Log.e(TAG, "Invalid setup for WPS"); + break; + } + if (result.status == Status.SUCCESS) { + replyToMessage(message, WifiManager.START_WPS_SUCCEEDED, result); + transitionTo(mWpsRunningState); + } else { + Log.e(TAG, "Failed to start WPS with config " + wpsInfo.toString()); + replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.ERROR); + } break; case WifiMonitor.SCAN_RESULTS_EVENT: /* Set the scan setting back to "connect" mode */ @@ -2910,7 +2888,6 @@ public class WifiStateMachine extends StateMachine { } } - class L2ConnectedState extends State { @Override public void enter() { @@ -2964,13 +2941,13 @@ public class WifiStateMachine extends StateMachine { /* Have the parent state handle the rest */ return NOT_HANDLED; /* Ignore connection to same network */ - case CMD_CONNECT_NETWORK: + case WifiManager.CONNECT_NETWORK: int netId = message.arg1; if (mWifiInfo.getNetworkId() == netId) { break; } return NOT_HANDLED; - case CMD_SAVE_NETWORK: + case WifiManager.SAVE_NETWORK: WifiConfiguration config = (WifiConfiguration) message.obj; NetworkUpdateResult result = mWifiConfigStore.saveNetwork(config); if (mWifiInfo.getNetworkId() == result.getNetworkId()) { @@ -2984,6 +2961,14 @@ public class WifiStateMachine extends StateMachine { sendLinkConfigurationChangedBroadcast(); } } + + if (result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID) { + replyToMessage(message, WifiManager.SAVE_NETWORK_SUCCEEDED); + } else { + loge("Failed to save network"); + replyToMessage(message, WifiManager.SAVE_NETWORK_FAILED, + WifiManager.ERROR); + } break; /* Ignore */ case WifiMonitor.NETWORK_CONNECTION_EVENT: @@ -3073,7 +3058,7 @@ public class WifiStateMachine extends StateMachine { handleFailedIpConfiguration(); transitionTo(mDisconnectingState); break; - case CMD_SAVE_NETWORK: + case WifiManager.SAVE_NETWORK: deferMessage(message); break; /* Defer any power mode changes since we must keep active power mode at DHCP */ @@ -3309,43 +3294,69 @@ public class WifiStateMachine extends StateMachine { } } - class WaitForWpsCompletionState extends State { + class WpsRunningState extends State { + //Tracks the source to provide a reply + private Message mSourceMessage; @Override public void enter() { if (DBG) log(getName() + "\n"); EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); + mSourceMessage = Message.obtain(getCurrentMessage()); } @Override public boolean processMessage(Message message) { if (DBG) log(getName() + message.toString() + "\n"); switch (message.what) { + case WifiMonitor.WPS_SUCCESS_EVENT: + replyToMessage(mSourceMessage, WifiManager.WPS_COMPLETED); + mSourceMessage.recycle(); + mSourceMessage = null; + transitionTo(mDisconnectedState); + break; + case WifiMonitor.WPS_OVERLAP_EVENT: + replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, + WifiManager.WPS_OVERLAP_ERROR); + mSourceMessage.recycle(); + mSourceMessage = null; + transitionTo(mDisconnectedState); + break; + case WifiMonitor.WPS_FAIL_EVENT: + case WifiMonitor.WPS_TIMEOUT_EVENT: + replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, WifiManager.ERROR); + mSourceMessage.recycle(); + mSourceMessage = null; + transitionTo(mDisconnectedState); + break; + case WifiManager.START_WPS: + replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.IN_PROGRESS); + break; /* Defer all commands that can cause connections to a different network * or put the state machine out of connect mode */ case CMD_STOP_DRIVER: case CMD_SET_SCAN_MODE: - case CMD_CONNECT_NETWORK: + case WifiManager.CONNECT_NETWORK: case CMD_ENABLE_NETWORK: case CMD_RECONNECT: case CMD_REASSOCIATE: - case WifiMonitor.NETWORK_CONNECTION_EVENT: /* Handled after IP & proxy update */ + case WifiMonitor.NETWORK_CONNECTION_EVENT: /* Handled after exiting WPS state */ deferMessage(message); break; case WifiMonitor.NETWORK_DISCONNECTION_EVENT: if (DBG) log("Network connection lost"); handleNetworkDisconnect(); break; - case WPS_COMPLETED_EVENT: - /* we are still disconnected until we see a network connection - * notification */ - transitionTo(mDisconnectedState); - break; default: return NOT_HANDLED; } EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what); return HANDLED; } + + public void exit() { + mWifiConfigStore.enableAllNetworks(); + mWifiConfigStore.loadConfiguredNetworks(); + } } class SoftApStartingState extends State { @@ -3605,6 +3616,43 @@ public class WifiStateMachine extends StateMachine { } } + //State machine initiated requests can have replyTo set to null indicating + //there are no recepients, we ignore those reply actions + private void replyToMessage(Message msg, int what) { + if (msg.replyTo == null) return; + Message dstMsg = obtainMessageWithArg2(msg); + dstMsg.what = what; + mReplyChannel.replyToMessage(msg, dstMsg); + } + + private void replyToMessage(Message msg, int what, int arg1) { + if (msg.replyTo == null) return; + Message dstMsg = obtainMessageWithArg2(msg); + dstMsg.what = what; + dstMsg.arg1 = arg1; + mReplyChannel.replyToMessage(msg, dstMsg); + } + + private void replyToMessage(Message msg, int what, Object obj) { + if (msg.replyTo == null) return; + Message dstMsg = obtainMessageWithArg2(msg); + dstMsg.what = what; + dstMsg.obj = obj; + mReplyChannel.replyToMessage(msg, dstMsg); + } + + /** + * arg2 on the source message has a unique id that needs to be retained in replies + * to match the request + * + * see WifiManager for details + */ + private Message obtainMessageWithArg2(Message srcMsg) { + Message msg = Message.obtain(); + msg.arg2 = srcMsg.arg2; + return msg; + } + private void log(String s) { Log.d(TAG, s); } diff --git a/wifi/java/android/net/wifi/WpsInfo.java b/wifi/java/android/net/wifi/WpsInfo.java index f70e5af..b80df21 100644 --- a/wifi/java/android/net/wifi/WpsInfo.java +++ b/wifi/java/android/net/wifi/WpsInfo.java @@ -16,9 +16,6 @@ package android.net.wifi; -import android.net.LinkProperties; -import android.net.wifi.WifiConfiguration.IpAssignment; -import android.net.wifi.WifiConfiguration.ProxySettings; import android.os.Parcelable; import android.os.Parcel; @@ -51,22 +48,10 @@ public class WpsInfo implements Parcelable { /** Passed with pin method configuration */ public String pin; - /** @hide */ - public IpAssignment ipAssignment; - - /** @hide */ - public ProxySettings proxySettings; - - /** @hide */ - public LinkProperties linkProperties; - public WpsInfo() { setup = INVALID; BSSID = null; pin = null; - ipAssignment = IpAssignment.UNASSIGNED; - proxySettings = ProxySettings.UNASSIGNED; - linkProperties = new LinkProperties(); } public String toString() { @@ -77,12 +62,6 @@ public class WpsInfo implements Parcelable { sbuf.append('\n'); sbuf.append(" pin: ").append(pin); sbuf.append('\n'); - sbuf.append("IP assignment: " + ipAssignment.toString()); - sbuf.append("\n"); - sbuf.append("Proxy settings: " + proxySettings.toString()); - sbuf.append("\n"); - sbuf.append(linkProperties.toString()); - sbuf.append("\n"); return sbuf.toString(); } @@ -97,9 +76,6 @@ public class WpsInfo implements Parcelable { setup = source.setup; BSSID = source.BSSID; pin = source.pin; - ipAssignment = source.ipAssignment; - proxySettings = source.proxySettings; - linkProperties = new LinkProperties(source.linkProperties); } } @@ -108,9 +84,6 @@ public class WpsInfo implements Parcelable { dest.writeInt(setup); dest.writeString(BSSID); dest.writeString(pin); - dest.writeString(ipAssignment.name()); - dest.writeString(proxySettings.name()); - dest.writeParcelable(linkProperties, flags); } /** Implement the Parcelable interface */ @@ -121,9 +94,6 @@ public class WpsInfo implements Parcelable { config.setup = in.readInt(); config.BSSID = in.readString(); config.pin = in.readString(); - config.ipAssignment = IpAssignment.valueOf(in.readString()); - config.proxySettings = ProxySettings.valueOf(in.readString()); - config.linkProperties = in.readParcelable(null); return config; } diff --git a/wifi/java/android/net/wifi/WpsStateMachine.java b/wifi/java/android/net/wifi/WpsStateMachine.java deleted file mode 100644 index 441a3b0..0000000 --- a/wifi/java/android/net/wifi/WpsStateMachine.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.wifi; - -import com.android.internal.util.AsyncChannel; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; - -import android.content.Context; -import android.content.Intent; -import android.net.wifi.StateChangeResult; -import android.net.wifi.WpsResult.Status; -import android.os.Handler; -import android.os.Message; -import android.os.Parcelable; -import android.util.Log; - -/** - * Manages a WPS connection. - * - * WPS consists as a series of EAP exchange triggered - * by a user action that leads to a successful connection - * after automatic creation of configuration in the - * supplicant. We currently support the following methods - * of WPS setup - * 1. Pin method: Pin can be either obtained from the device - * or from the access point to connect to. - * 2. Push button method: This involves pushing a button on - * the access point and the device - * - * After a successful WPS setup, the state machine - * reloads the configuration and updates the IP and proxy - * settings, if any. - */ -class WpsStateMachine extends StateMachine { - - private static final String TAG = "WpsStateMachine"; - private static final boolean DBG = false; - - private WifiStateMachine mWifiStateMachine; - private WifiConfigStore mWifiConfigStore; - - private WpsInfo mWpsInfo; - - private Context mContext; - AsyncChannel mReplyChannel = new AsyncChannel(); - - private State mDefaultState = new DefaultState(); - private State mInactiveState = new InactiveState(); - private State mActiveState = new ActiveState(); - - public WpsStateMachine(Context context, WifiStateMachine wsm, WifiConfigStore wcs, Handler t) { - super(TAG, t.getLooper()); - - mContext = context; - mWifiStateMachine = wsm; - mWifiConfigStore = wcs; - addState(mDefaultState); - addState(mInactiveState, mDefaultState); - addState(mActiveState, mDefaultState); - - setInitialState(mInactiveState); - - //start the state machine - start(); - } - - - /******************************************************** - * HSM states - *******************************************************/ - - class DefaultState extends State { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - @Override - public boolean processMessage(Message message) { - if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); - WpsInfo wpsConfig; - switch (message.what) { - case WifiStateMachine.CMD_START_WPS: - mWpsInfo = (WpsInfo) message.obj; - WpsResult result; - switch (mWpsInfo.setup) { - case WpsInfo.PBC: - result = mWifiConfigStore.startWpsPbc(mWpsInfo); - break; - case WpsInfo.KEYPAD: - result = mWifiConfigStore.startWpsWithPinFromAccessPoint(mWpsInfo); - break; - case WpsInfo.DISPLAY: - result = mWifiConfigStore.startWpsWithPinFromDevice(mWpsInfo); - break; - default: - result = new WpsResult(Status.FAILURE); - Log.e(TAG, "Invalid setup for WPS"); - break; - } - mReplyChannel.replyToMessage(message, WifiManager.CMD_WPS_COMPLETED, result); - if (result.status == Status.SUCCESS) { - transitionTo(mActiveState); - } else { - Log.e(TAG, "Failed to start WPS with config " + mWpsInfo.toString()); - } - break; - case WifiStateMachine.CMD_RESET_WPS_STATE: - transitionTo(mInactiveState); - break; - default: - Log.e(TAG, "Failed to handle " + message); - break; - } - return HANDLED; - } - } - - class ActiveState extends State { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - - @Override - public boolean processMessage(Message message) { - boolean retValue = HANDLED; - if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); - switch (message.what) { - case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: - StateChangeResult stateChangeResult = (StateChangeResult) message.obj; - SupplicantState supState = (SupplicantState) stateChangeResult.state; - switch (supState) { - case COMPLETED: - /* During WPS setup, all other networks are disabled. After - * a successful connect a new config is created in the supplicant. - * - * We need to enable all networks after a successful connection - * and the configuration list needs to be reloaded from the supplicant. - */ - Log.d(TAG, "WPS set up successful"); - mWifiConfigStore.enableAllNetworks(); - mWifiConfigStore.loadConfiguredNetworks(); - mWifiConfigStore.updateIpAndProxyFromWpsConfig( - stateChangeResult.networkId, mWpsInfo); - mWifiStateMachine.sendMessage(WifiStateMachine.WPS_COMPLETED_EVENT); - transitionTo(mInactiveState); - break; - case INACTIVE: - /* A failed WPS connection */ - Log.d(TAG, "WPS set up failed, enabling other networks"); - mWifiConfigStore.enableAllNetworks(); - mWifiStateMachine.sendMessage(WifiStateMachine.WPS_COMPLETED_EVENT); - transitionTo(mInactiveState); - break; - default: - if (DBG) Log.d(TAG, "Ignoring supplicant state " + supState.name()); - break; - } - break; - case WifiStateMachine.CMD_START_WPS: - /* Ignore request and send an in progress message */ - mReplyChannel.replyToMessage(message, WifiManager.CMD_WPS_COMPLETED, - new WpsResult(Status.IN_PROGRESS)); - break; - default: - retValue = NOT_HANDLED; - } - return retValue; - } - } - - class InactiveState extends State { - @Override - public void enter() { - if (DBG) Log.d(TAG, getName() + "\n"); - } - - @Override - public boolean processMessage(Message message) { - boolean retValue = HANDLED; - if (DBG) Log.d(TAG, getName() + message.toString() + "\n"); - switch (message.what) { - //Ignore supplicant state changes - case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: - break; - default: - retValue = NOT_HANDLED; - } - return retValue; - } - } - -} |