From e4c56c9655bf936454e2f3ee434aacb403876c7d Mon Sep 17 00:00:00 2001 From: Irfan Sheriff Date: Wed, 12 Jan 2011 16:33:58 -0800 Subject: Fix WPS to provides immediate feedback If WPS is already active, we drop user's request and convey an in progress message If WPS fails to start, a failure indication is conveyed to the user Bug: 3316078 Change-Id: I238c55973cb29cf5c1be66197ffcb4978316cb89 --- wifi/java/android/net/wifi/IWifiManager.aidl | 3 +- wifi/java/android/net/wifi/WifiConfigStore.java | 36 ++++++---- wifi/java/android/net/wifi/WifiManager.java | 6 +- wifi/java/android/net/wifi/WifiStateMachine.java | 30 ++++---- wifi/java/android/net/wifi/WpsResult.aidl | 19 +++++ wifi/java/android/net/wifi/WpsResult.java | 90 ++++++++++++++++++++++++ wifi/java/android/net/wifi/WpsStateMachine.java | 24 ++++--- 7 files changed, 167 insertions(+), 41 deletions(-) create mode 100644 wifi/java/android/net/wifi/WpsResult.aidl create mode 100644 wifi/java/android/net/wifi/WpsResult.java (limited to 'wifi/java') diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 9dbba20..847577f 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -19,6 +19,7 @@ package android.net.wifi; import android.net.wifi.WifiInfo; import android.net.wifi.WifiConfiguration; import android.net.wifi.WpsConfiguration; +import android.net.wifi.WpsResult; import android.net.wifi.ScanResult; import android.net.DhcpInfo; @@ -109,6 +110,6 @@ interface IWifiManager void forgetNetwork(int networkId); - String startWps(in WpsConfiguration config); + WpsResult startWps(in WpsConfiguration config); } diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java index 56bc5d7..73c24cf 100644 --- a/wifi/java/android/net/wifi/WifiConfigStore.java +++ b/wifi/java/android/net/wifi/WifiConfigStore.java @@ -370,44 +370,52 @@ class WifiConfigStore { * Start WPS pin method configuration with pin obtained * from the access point */ - static boolean startWpsWithPinFromAccessPoint(WpsConfiguration config) { + static WpsResult startWpsWithPinFromAccessPoint(WpsConfiguration config) { + WpsResult result = new WpsResult(); if (WifiNative.startWpsWithPinFromAccessPointCommand(config.BSSID, config.pin)) { /* WPS leaves all networks disabled */ markAllNetworksDisabled(); - return true; + result.status = WpsResult.Status.SUCCESS; + } else { + Log.e(TAG, "Failed to start WPS pin method configuration"); + result.status = WpsResult.Status.FAILURE; } - Log.e(TAG, "Failed to start WPS pin method configuration"); - return false; + return result; } /** * Start WPS pin method configuration with pin obtained * from the device - * @return empty string on failure. null is never returned. + * @return WpsResult indicating status and pin */ - static String startWpsWithPinFromDevice(WpsConfiguration config) { - String pin = WifiNative.startWpsWithPinFromDeviceCommand(config.BSSID); + static WpsResult startWpsWithPinFromDevice(WpsConfiguration config) { + WpsResult result = new WpsResult(); + result.pin = WifiNative.startWpsWithPinFromDeviceCommand(config.BSSID); /* WPS leaves all networks disabled */ - if (!TextUtils.isEmpty(pin)) { + if (!TextUtils.isEmpty(result.pin)) { markAllNetworksDisabled(); + result.status = WpsResult.Status.SUCCESS; } else { Log.e(TAG, "Failed to start WPS pin method configuration"); - pin = ""; + result.status = WpsResult.Status.FAILURE; } - return pin; + return result; } /** * Start WPS push button configuration */ - static boolean startWpsPbc(WpsConfiguration config) { + static WpsResult startWpsPbc(WpsConfiguration config) { + WpsResult result = new WpsResult(); if (WifiNative.startWpsPbcCommand(config.BSSID)) { /* WPS leaves all networks disabled */ markAllNetworksDisabled(); - return true; + result.status = WpsResult.Status.SUCCESS; + } else { + Log.e(TAG, "Failed to start WPS push button configuration"); + result.status = WpsResult.Status.FAILURE; } - Log.e(TAG, "Failed to start WPS push button configuration"); - return false; + return result; } /** diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 4623721..54887d7 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -1074,15 +1074,15 @@ public class WifiManager { * Start Wi-fi Protected Setup * * @param config WPS configuration - * @return pin generated by device, if any + * @return WpsResult containing pin and status * @hide * TODO: with use of AsyncChannel, return value should go away */ - public String startWps(WpsConfiguration config) { + public WpsResult startWps(WpsConfiguration config) { try { return mService.startWps(config); } catch (RemoteException e) { - return null; + return new WpsResult(WpsResult.Status.FAILURE); } } diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 8718117..d7d86f0 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -47,6 +47,7 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo.DetailedState; import android.net.LinkProperties; import android.net.wifi.NetworkUpdateResult; +import android.net.wifi.WpsResult.Status; import android.os.Binder; import android.os.Message; import android.os.IBinder; @@ -302,10 +303,11 @@ public class WifiStateMachine extends HierarchicalStateMachine { /* Reset the supplicant state tracker */ static final int CMD_RESET_SUPPLICANT_STATE = 111; - /* Commands/events reported by WpsStateMachine */ /* Indicates the completion of WPS activity */ static final int WPS_COMPLETED_EVENT = 121; + /* Reset the WPS state machine */ + static final int CMD_RESET_WPS_STATE = 122; private static final int CONNECT_MODE = 1; private static final int SCAN_ONLY_MODE = 2; @@ -793,18 +795,19 @@ public class WifiStateMachine extends HierarchicalStateMachine { sendMessage(obtainMessage(CMD_FORGET_NETWORK, netId, 0)); } - public String startWps(AsyncChannel channel, WpsConfiguration config) { - String result = null; + public WpsResult startWps(AsyncChannel channel, WpsConfiguration config) { + WpsResult result; switch (config.setup) { case PIN_FROM_DEVICE: + case PBC: + case PIN_FROM_ACCESS_POINT: //TODO: will go away with AsyncChannel use from settings Message resultMsg = channel.sendMessageSynchronously(CMD_START_WPS, config); - result = (String) resultMsg.obj; + result = (WpsResult) resultMsg.obj; resultMsg.recycle(); break; - case PBC: - case PIN_FROM_ACCESS_POINT: - sendMessage(obtainMessage(CMD_START_WPS, config)); + default: + result = new WpsResult(Status.FAILURE); break; } return result; @@ -1511,13 +1514,9 @@ public class WifiStateMachine extends HierarchicalStateMachine { case CMD_ENABLE_ALL_NETWORKS: break; case CMD_START_WPS: - WpsConfiguration config = (WpsConfiguration) message.obj; - switch (config.setup) { - case PIN_FROM_DEVICE: - String pin = ""; - mReplyChannel.replyToMessage(message, message.what, pin); - break; - } + /* Return failure when the state machine cannot handle WPS initiation*/ + mReplyChannel.replyToMessage(message, message.what, + new WpsResult(Status.FAILURE)); break; default: Log.e(TAG, "Error! unhandled message" + message); @@ -1803,6 +1802,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { /* 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 = -1; @@ -1884,6 +1884,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { setWifiState(WIFI_STATE_DISABLING); sendSupplicantConnectionChangedBroadcast(false); mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE); + mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE); transitionTo(mSupplicantStoppingState); break; case SUP_DISCONNECTION_EVENT: /* Supplicant connection lost */ @@ -1894,6 +1895,7 @@ public class WifiStateMachine extends HierarchicalStateMachine { 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; diff --git a/wifi/java/android/net/wifi/WpsResult.aidl b/wifi/java/android/net/wifi/WpsResult.aidl new file mode 100644 index 0000000..eb4c4f5 --- /dev/null +++ b/wifi/java/android/net/wifi/WpsResult.aidl @@ -0,0 +1,19 @@ +/** + * 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; + +parcelable WpsResult; diff --git a/wifi/java/android/net/wifi/WpsResult.java b/wifi/java/android/net/wifi/WpsResult.java new file mode 100644 index 0000000..d4fd3e2 --- /dev/null +++ b/wifi/java/android/net/wifi/WpsResult.java @@ -0,0 +1,90 @@ +/* + * 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 android.os.Parcel; +import android.os.Parcelable; + +/** + * A class representing the result of a WPS request + * @hide + */ +public class WpsResult implements Parcelable { + + public enum Status { + SUCCESS, + FAILURE, + IN_PROGRESS, + } + + public Status status; + + public String pin; + + public WpsResult() { + status = Status.FAILURE; + pin = null; + } + + public WpsResult(Status s) { + status = s; + pin = null; + } + + public String toString() { + StringBuffer sbuf = new StringBuffer(); + sbuf.append(" status: ").append(status.toString()); + sbuf.append('\n'); + sbuf.append(" pin: ").append(pin); + sbuf.append("\n"); + return sbuf.toString(); + } + + /** Implement the Parcelable interface {@hide} */ + public int describeContents() { + return 0; + } + + /** copy constructor {@hide} */ + public WpsResult(WpsResult source) { + if (source != null) { + status = source.status; + pin = source.pin; + } + } + + /** Implement the Parcelable interface {@hide} */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(status.name()); + dest.writeString(pin); + } + + /** Implement the Parcelable interface {@hide} */ + public static final Creator CREATOR = + new Creator() { + public WpsResult createFromParcel(Parcel in) { + WpsResult result = new WpsResult(); + result.status = Status.valueOf(in.readString()); + result.pin = in.readString(); + return result; + } + + public WpsResult[] newArray(int size) { + return new WpsResult[size]; + } + }; +} diff --git a/wifi/java/android/net/wifi/WpsStateMachine.java b/wifi/java/android/net/wifi/WpsStateMachine.java index 381444c..92f9f57 100644 --- a/wifi/java/android/net/wifi/WpsStateMachine.java +++ b/wifi/java/android/net/wifi/WpsStateMachine.java @@ -23,6 +23,7 @@ import com.android.internal.util.HierarchicalStateMachine; import android.content.Context; import android.content.Intent; import android.net.wifi.WifiStateMachine.StateChangeResult; +import android.net.wifi.WpsResult.Status; import android.os.Handler; import android.os.Message; import android.os.Parcelable; @@ -93,29 +94,32 @@ class WpsStateMachine extends HierarchicalStateMachine { switch (message.what) { case WifiStateMachine.CMD_START_WPS: mWpsConfig = (WpsConfiguration) message.obj; - boolean success = false; + WpsResult result; switch (mWpsConfig.setup) { case PBC: - success = WifiConfigStore.startWpsPbc(mWpsConfig); + result = WifiConfigStore.startWpsPbc(mWpsConfig); break; case PIN_FROM_ACCESS_POINT: - success = WifiConfigStore.startWpsWithPinFromAccessPoint(mWpsConfig); + result = WifiConfigStore.startWpsWithPinFromAccessPoint(mWpsConfig); break; case PIN_FROM_DEVICE: - String pin = WifiConfigStore.startWpsWithPinFromDevice(mWpsConfig); - success = (pin != null); - mReplyChannel.replyToMessage(message, message.what, pin); + result = WifiConfigStore.startWpsWithPinFromDevice(mWpsConfig); break; default: + result = new WpsResult(Status.FAILURE); Log.e(TAG, "Invalid setup for WPS"); break; } - if (success) { + mReplyChannel.replyToMessage(message, message.what, result); + if (result.status == Status.SUCCESS) { transitionTo(mActiveState); } else { Log.e(TAG, "Failed to start WPS with config " + mWpsConfig.toString()); } break; + case WifiStateMachine.CMD_RESET_WPS_STATE: + transitionTo(mInactiveState); + break; default: Log.e(TAG, "Failed to handle " + message); break; @@ -167,7 +171,9 @@ class WpsStateMachine extends HierarchicalStateMachine { } break; case WifiStateMachine.CMD_START_WPS: - deferMessage(message); + /* Ignore request and send an in progress message */ + mReplyChannel.replyToMessage(message, message.what, + new WpsResult(Status.IN_PROGRESS)); break; default: retValue = NOT_HANDLED; @@ -197,4 +203,4 @@ class WpsStateMachine extends HierarchicalStateMachine { } } -} \ No newline at end of file +} -- cgit v1.1