Merge "Enhance WPS"

This commit is contained in:
Irfan Sheriff
2012-03-02 16:33:01 -08:00
committed by Android (Google) Code Review
7 changed files with 154 additions and 26 deletions

View File

@ -286,7 +286,10 @@ class WifiConfigStore {
config.status = Status.CURRENT;
break;
case DISCONNECTED:
config.status = Status.ENABLED;
//If network is already disabled, keep the status
if (config.status == Status.CURRENT) {
config.status = Status.ENABLED;
}
break;
default:
//do nothing, retain the existing state
@ -906,7 +909,7 @@ class WifiConfigStore {
}
}
} else {
loge("Missing id while parsing configuration");
if (DBG) log("Missing id while parsing configuration");
}
}
} catch (EOFException ignore) {

View File

@ -1069,15 +1069,22 @@ public class WifiManager {
public static final int START_WPS_SUCCEEDED = BASE + 11;
/** @hide */
public static final int WPS_FAILED = BASE + 12;
/** @hide */
/** @hide */
public static final int WPS_COMPLETED = BASE + 13;
/** @hide */
public static final int DISABLE_NETWORK = BASE + 14;
public static final int CANCEL_WPS = BASE + 14;
/** @hide */
public static final int DISABLE_NETWORK_FAILED = BASE + 15;
public static final int CANCEL_WPS_FAILED = BASE + 15;
/** @hide */
public static final int DISABLE_NETWORK_SUCCEEDED = BASE + 16;
public static final int CANCEL_WPS_SUCCEDED = BASE + 16;
/** @hide */
public static final int DISABLE_NETWORK = BASE + 17;
/** @hide */
public static final int DISABLE_NETWORK_FAILED = BASE + 18;
/** @hide */
public static final int DISABLE_NETWORK_SUCCEEDED = BASE + 19;
/* For system use only */
/** @hide */
@ -1091,14 +1098,14 @@ public class WifiManager {
* Indicates that the operation failed due to an internal error.
* @hide
*/
public static final int ERROR = 0;
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;
public static final int IN_PROGRESS = 1;
/**
* Passed with {@link ActionListener#onFailure}.
@ -1106,11 +1113,19 @@ public class WifiManager {
* unable to service the request
* @hide
*/
public static final int BUSY = 2;
public static final int BUSY = 2;
/* WPS specific errors */
/** WPS overlap detected {@hide} */
public static final int WPS_OVERLAP_ERROR = 3;
public static final int WPS_OVERLAP_ERROR = 3;
/** WEP on WPS is prohibited {@hide} */
public static final int WPS_WEP_PROHIBITED = 4;
/** TKIP only prohibited {@hide} */
public static final int WPS_TKIP_ONLY_PROHIBITED = 5;
/** Authentication failure on WPS {@hide} */
public static final int WPS_AUTH_FAILURE = 6;
/** WPS timed out {@hide} */
public static final int WPS_TIMED_OUT = 7;
/** Interface for callback invocation when framework channel is lost {@hide} */
public interface ChannelListener {
@ -1165,6 +1180,7 @@ public class WifiManager {
private SparseArray<Object> mListenerMap = new SparseArray<Object>();
private Object mListenerMapLock = new Object();
private int mListenerKey = 0;
private static final int INVALID_KEY = -1;
AsyncChannel mAsyncChannel;
WifiHandler mHandler;
@ -1187,6 +1203,7 @@ public class WifiManager {
case WifiManager.CONNECT_NETWORK_FAILED:
case WifiManager.FORGET_NETWORK_FAILED:
case WifiManager.SAVE_NETWORK_FAILED:
case WifiManager.CANCEL_WPS_FAILED:
case WifiManager.DISABLE_NETWORK_FAILED:
if (listener != null) {
((ActionListener) listener).onFailure(message.arg1);
@ -1196,6 +1213,7 @@ public class WifiManager {
case WifiManager.CONNECT_NETWORK_SUCCEEDED:
case WifiManager.FORGET_NETWORK_SUCCEEDED:
case WifiManager.SAVE_NETWORK_SUCCEEDED:
case WifiManager.CANCEL_WPS_SUCCEDED:
case WifiManager.DISABLE_NETWORK_SUCCEEDED:
if (listener != null) {
((ActionListener) listener).onSuccess();
@ -1229,16 +1247,19 @@ public class WifiManager {
}
int putListener(Object listener) {
if (listener == null) return 0;
if (listener == null) return INVALID_KEY;
int key;
synchronized (mListenerMapLock) {
key = mListenerKey++;
do {
key = mListenerKey++;
} while (key == INVALID_KEY);
mListenerMap.put(key, listener);
}
return key;
}
Object removeListener(int key) {
if (key == INVALID_KEY) return null;
synchronized (mListenerMapLock) {
Object listener = mListenerMap.get(key);
mListenerMap.remove(key);
@ -1387,6 +1408,21 @@ public class WifiManager {
c.mAsyncChannel.sendMessage(START_WPS, 0, c.putListener(listener), config);
}
/**
* Cancel any ongoing Wi-fi Protected Setup
*
* @param c is the channel created at {@link #initialize}
* @param listener for callbacks on success or failure. Can be null.
* @hide
*/
public void cancelWps(Channel c, ActionListener listener) {
if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
c.mAsyncChannel.sendMessage(CANCEL_WPS, 0, c.putListener(listener));
}
/**
* Get a reference to WifiService handler. This is used by a client to establish
* an AsyncChannel communication with WifiService

View File

@ -65,7 +65,20 @@ public class WifiMonitor {
/* WPS events */
private static final String WPS_SUCCESS_STR = "WPS-SUCCESS";
/* Format: WPS-FAIL msg=%d [config_error=%d] [reason=%d (%s)] */
private static final String WPS_FAIL_STR = "WPS-FAIL";
private static final String WPS_FAIL_PATTERN =
"WPS-FAIL msg=\\d+(?: config_error=(\\d+))?(?: reason=(\\d+))?";
/* config error code values for config_error=%d */
private static final int CONFIG_MULTIPLE_PBC_DETECTED = 12;
private static final int CONFIG_AUTH_FAILURE = 18;
/* reason code values for reason=%d */
private static final int REASON_TKIP_ONLY_PROHIBITED = 1;
private static final int REASON_WEP_PROHIBITED = 2;
private static final String WPS_OVERLAP_STR = "WPS-OVERLAP-DETECTED";
private static final String WPS_TIMEOUT_STR = "WPS-TIMEOUT";
@ -316,7 +329,7 @@ public class WifiMonitor {
} else if (eventStr.startsWith(WPS_SUCCESS_STR)) {
mStateMachine.sendMessage(WPS_SUCCESS_EVENT);
} else if (eventStr.startsWith(WPS_FAIL_STR)) {
mStateMachine.sendMessage(WPS_FAIL_EVENT);
handleWpsFailEvent(eventStr);
} else if (eventStr.startsWith(WPS_OVERLAP_STR)) {
mStateMachine.sendMessage(WPS_OVERLAP_EVENT);
} else if (eventStr.startsWith(WPS_TIMEOUT_STR)) {
@ -458,6 +471,43 @@ public class WifiMonitor {
}
}
private void handleWpsFailEvent(String dataString) {
final Pattern p = Pattern.compile(WPS_FAIL_PATTERN);
Matcher match = p.matcher(dataString);
if (match.find()) {
String cfgErr = match.group(1);
String reason = match.group(2);
if (reason != null) {
switch(Integer.parseInt(reason)) {
case REASON_TKIP_ONLY_PROHIBITED:
mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
WifiManager.WPS_TKIP_ONLY_PROHIBITED, 0));
return;
case REASON_WEP_PROHIBITED:
mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
WifiManager.WPS_WEP_PROHIBITED, 0));
return;
}
}
if (cfgErr != null) {
switch(Integer.parseInt(cfgErr)) {
case CONFIG_AUTH_FAILURE:
mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
WifiManager.WPS_AUTH_FAILURE, 0));
return;
case CONFIG_MULTIPLE_PBC_DETECTED:
mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
WifiManager.WPS_OVERLAP_ERROR, 0));
return;
}
}
}
//For all other errors, return a generic internal error
mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
WifiManager.ERROR, 0));
}
/**
* Handle p2p events
*/

View File

@ -388,27 +388,37 @@ public class WifiNative {
return doStringCommand("SIGNAL_POLL");
}
public boolean startWpsPbc() {
return doBooleanCommand("WPS_PBC");
}
public boolean startWpsPbc(String bssid) {
return doBooleanCommand("WPS_PBC " + bssid);
if (TextUtils.isEmpty(bssid)) {
return doBooleanCommand("WPS_PBC");
} else {
return doBooleanCommand("WPS_PBC " + bssid);
}
}
public boolean startWpsPinKeypad(String pin) {
if (TextUtils.isEmpty(pin)) return false;
return doBooleanCommand("WPS_PIN any " + pin);
}
public String startWpsPinDisplay(String bssid) {
return doStringCommand("WPS_PIN " + bssid);
if (TextUtils.isEmpty(bssid)) {
return doStringCommand("WPS_PIN any");
} else {
return doStringCommand("WPS_PIN " + bssid);
}
}
/* Configures an access point connection */
public boolean startWpsRegistrar(String bssid, String pin) {
if (TextUtils.isEmpty(bssid) || TextUtils.isEmpty(pin)) return false;
return doBooleanCommand("WPS_REG " + bssid + " " + pin);
}
public boolean cancelWps() {
return doBooleanCommand("WPS_CANCEL");
}
public boolean setPersistentReconnect(boolean enabled) {
int value = (enabled == true) ? 1 : 0;
return doBooleanCommand("SET persistent_reconnect " + value);
@ -539,7 +549,7 @@ public class WifiNative {
}
public boolean p2pGroupRemove(String iface) {
if (iface == null) return false;
if (TextUtils.isEmpty(iface)) return false;
return doBooleanCommand("P2P_GROUP_REMOVE " + iface);
}
@ -549,7 +559,7 @@ public class WifiNative {
/* Invite a peer to a group */
public boolean p2pInvite(WifiP2pGroup group, String deviceAddress) {
if (deviceAddress == null) return false;
if (TextUtils.isEmpty(deviceAddress)) return false;
if (group == null) {
return doBooleanCommand("P2P_INVITE peer=" + deviceAddress);
@ -561,19 +571,19 @@ public class WifiNative {
/* Reinvoke a persistent connection */
public boolean p2pReinvoke(int netId, String deviceAddress) {
if (deviceAddress == null || netId < 0) return false;
if (TextUtils.isEmpty(deviceAddress) || netId < 0) return false;
return doBooleanCommand("P2P_INVITE persistent=" + netId + " peer=" + deviceAddress);
}
public String p2pGetInterfaceAddress(String deviceAddress) {
if (deviceAddress == null) return null;
if (TextUtils.isEmpty(deviceAddress)) return null;
// "p2p_peer deviceAddress" returns a multi-line result containing
// intended_addr=fa:7b:7a:42:82:13
String peerInfo = p2pPeer(deviceAddress);
if (peerInfo == null) return null;
if (TextUtils.isEmpty(peerInfo)) return null;
String[] tokens= peerInfo.split("\n");
for (String token : tokens) {

View File

@ -1844,6 +1844,10 @@ public class WifiStateMachine extends StateMachine {
replyToMessage(message, WifiManager.WPS_FAILED,
WifiManager.BUSY);
break;
case WifiManager.CANCEL_WPS:
replyToMessage(message, WifiManager.CANCEL_WPS_FAILED,
WifiManager.BUSY);
break;
case WifiManager.DISABLE_NETWORK:
replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED,
WifiManager.BUSY);
@ -3321,8 +3325,15 @@ public class WifiStateMachine extends StateMachine {
transitionTo(mDisconnectedState);
break;
case WifiMonitor.WPS_FAIL_EVENT:
//arg1 has the reason for the failure
replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, message.arg1);
mSourceMessage.recycle();
mSourceMessage = null;
transitionTo(mDisconnectedState);
break;
case WifiMonitor.WPS_TIMEOUT_EVENT:
replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, WifiManager.ERROR);
replyToMessage(mSourceMessage, WifiManager.WPS_FAILED,
WifiManager.WPS_TIMED_OUT);
mSourceMessage.recycle();
mSourceMessage = null;
transitionTo(mDisconnectedState);
@ -3330,6 +3341,14 @@ public class WifiStateMachine extends StateMachine {
case WifiManager.START_WPS:
replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.IN_PROGRESS);
break;
case WifiManager.CANCEL_WPS:
if (mWifiNative.cancelWps()) {
replyToMessage(message, WifiManager.CANCEL_WPS_SUCCEDED);
} else {
replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, WifiManager.ERROR);
}
transitionTo(mDisconnectedState);
break;
/* Defer all commands that can cause connections to a different network
* or put the state machine out of connect mode
*/
@ -3346,6 +3365,11 @@ public class WifiStateMachine extends StateMachine {
if (DBG) log("Network connection lost");
handleNetworkDisconnect();
break;
case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
//Throw away supplicant state changes when WPS is running.
//We will start getting supplicant state changes once we get
//a WPS success or failure
break;
default:
return NOT_HANDLED;
}
@ -3353,6 +3377,7 @@ public class WifiStateMachine extends StateMachine {
return HANDLED;
}
@Override
public void exit() {
mWifiConfigStore.enableAllNetworks();
mWifiConfigStore.loadConfiguredNetworks();

View File

@ -996,7 +996,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
break;
case PEER_CONNECTION_USER_ACCEPT:
if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
mWifiNative.startWpsPbc();
mWifiNative.startWpsPbc(null);
} else {
mWifiNative.startWpsPinKeypad(mSavedPeerConfig.wps.pin);
}