diff options
author | Irfan Sheriff <isheriff@google.com> | 2012-12-13 12:33:42 -0800 |
---|---|---|
committer | Irfan Sheriff <isheriff@google.com> | 2012-12-14 14:48:10 -0800 |
commit | f118043ca726c65f04cddc6321c9e820b577fc6f (patch) | |
tree | 25c0a688b56e0b64d9858e0f52ccf84005f53629 /wifi/java/android/net/wifi/p2p | |
parent | 3a67e2515bff73fab57621b1f9966662e83b7881 (diff) | |
download | frameworks_base-f118043ca726c65f04cddc6321c9e820b577fc6f.zip frameworks_base-f118043ca726c65f04cddc6321c9e820b577fc6f.tar.gz frameworks_base-f118043ca726c65f04cddc6321c9e820b577fc6f.tar.bz2 |
P2p cleanup
- Clean up handling of mSavedPeerConfig
- Add argument protection
- Split out WPS handling on GO into a separate API. This was almost hacky
right now for applications and was working in an undocumented way
- Refactor connect function call and fix updating group capability
Change-Id: I26211c72ad60c6b6c939ad7473fcf2fc633f3010
Diffstat (limited to 'wifi/java/android/net/wifi/p2p')
-rw-r--r-- | wifi/java/android/net/wifi/p2p/WifiP2pConfig.java | 6 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java | 36 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/p2p/WifiP2pManager.java | 108 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/p2p/WifiP2pService.java | 344 |
4 files changed, 296 insertions, 198 deletions
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java index b1501ed..482d9cb 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java @@ -30,7 +30,7 @@ public class WifiP2pConfig implements Parcelable { /** * The device MAC address uniquely identifies a Wi-Fi p2p device */ - public String deviceAddress; + public String deviceAddress = ""; /** * Wi-Fi Protected Setup information @@ -60,6 +60,10 @@ public class WifiP2pConfig implements Parcelable { wps.setup = WpsInfo.PBC; } + void invalidate() { + deviceAddress = ""; + } + /** P2P-GO-NEG-REQUEST 42:fc:89:a8:96:09 dev_passwd_id=4 {@hide}*/ public WifiP2pConfig(String supplicantEvent) throws IllegalArgumentException { String[] tokens = supplicantEvent.split(" "); diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java index f7bceac..4f40ebc 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java @@ -58,6 +58,19 @@ public class WifiP2pDeviceList implements Parcelable { } } + private void validateDevice(WifiP2pDevice device) { + if (device == null) throw new IllegalArgumentException("Null device"); + if (TextUtils.isEmpty(device.deviceAddress)) { + throw new IllegalArgumentException("Empty deviceAddress"); + } + } + + private void validateDeviceAddress(String deviceAddress) { + if (TextUtils.isEmpty(deviceAddress)) { + throw new IllegalArgumentException("Empty deviceAddress"); + } + } + /** Clear the list @hide */ public boolean clear() { if (mDevices.isEmpty()) return false; @@ -72,14 +85,13 @@ public class WifiP2pDeviceList implements Parcelable { * @hide */ public void update(WifiP2pDevice device) { - if (device == null || device.deviceAddress == null) return; updateSupplicantDetails(device); mDevices.get(device.deviceAddress).status = device.status; } /** Only updates details fetched from the supplicant @hide */ void updateSupplicantDetails(WifiP2pDevice device) { - if (device == null || device.deviceAddress == null) return; + validateDevice(device); WifiP2pDevice d = mDevices.get(device.deviceAddress); if (d != null) { d.deviceName = device.deviceName; @@ -97,7 +109,7 @@ public class WifiP2pDeviceList implements Parcelable { /** @hide */ void updateGroupCapability(String deviceAddress, int groupCapab) { - if (TextUtils.isEmpty(deviceAddress)) return; + validateDeviceAddress(deviceAddress); WifiP2pDevice d = mDevices.get(deviceAddress); if (d != null) { d.groupCapability = groupCapab; @@ -106,7 +118,7 @@ public class WifiP2pDeviceList implements Parcelable { /** @hide */ void updateStatus(String deviceAddress, int status) { - if (TextUtils.isEmpty(deviceAddress)) return; + validateDeviceAddress(deviceAddress); WifiP2pDevice d = mDevices.get(deviceAddress); if (d != null) { d.status = status; @@ -119,14 +131,13 @@ public class WifiP2pDeviceList implements Parcelable { * @return WifiP2pDevice device found, or null if none found */ public WifiP2pDevice get(String deviceAddress) { - if (deviceAddress == null) return null; - + validateDeviceAddress(deviceAddress); return mDevices.get(deviceAddress); } /** @hide */ public boolean remove(WifiP2pDevice device) { - if (device == null || device.deviceAddress == null) return false; + validateDevice(device); return mDevices.remove(device.deviceAddress) != null; } @@ -137,7 +148,7 @@ public class WifiP2pDeviceList implements Parcelable { * @hide */ public WifiP2pDevice remove(String deviceAddress) { - if (deviceAddress == null) return null; + validateDeviceAddress(deviceAddress); return mDevices.remove(deviceAddress); } @@ -157,11 +168,12 @@ public class WifiP2pDeviceList implements Parcelable { /** @hide */ public boolean isGroupOwner(String deviceAddress) { - if (deviceAddress != null) { - WifiP2pDevice device = mDevices.get(deviceAddress); - if (device != null) return device.isGroupOwner(); + validateDeviceAddress(deviceAddress); + WifiP2pDevice device = mDevices.get(deviceAddress); + if (device == null) { + throw new IllegalArgumentException("Device not found " + deviceAddress); } - return false; + return device.isGroupOwner(); } public String toString() { diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java index 5bd0349..2e80064 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java @@ -21,6 +21,7 @@ import android.annotation.SdkConstant.SdkConstantType; import android.content.Context; import android.net.ConnectivityManager; import android.net.IConnectivityManager; +import android.net.wifi.WpsInfo; import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo; import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceResponse; import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; @@ -37,6 +38,7 @@ import android.os.Messenger; import android.os.RemoteException; import android.os.ServiceManager; import android.os.WorkSource; +import android.text.TextUtils; import android.util.Log; import com.android.internal.util.AsyncChannel; @@ -421,6 +423,13 @@ public class WifiP2pManager { /** @hide */ public static final int SET_WFD_INFO_SUCCEEDED = BASE + 61; + /** @hide */ + public static final int START_WPS = BASE + 62; + /** @hide */ + public static final int START_WPS_FAILED = BASE + 63; + /** @hide */ + public static final int START_WPS_SUCCEEDED = BASE + 64; + /** * Create a new WifiP2pManager instance. Applications use * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve @@ -641,70 +650,72 @@ public class WifiP2pManager { } break; /* ActionListeners grouped together */ - case WifiP2pManager.DISCOVER_PEERS_FAILED: - case WifiP2pManager.STOP_DISCOVERY_FAILED: - case WifiP2pManager.DISCOVER_SERVICES_FAILED: - case WifiP2pManager.CONNECT_FAILED: - case WifiP2pManager.CANCEL_CONNECT_FAILED: - case WifiP2pManager.CREATE_GROUP_FAILED: - case WifiP2pManager.REMOVE_GROUP_FAILED: - case WifiP2pManager.ADD_LOCAL_SERVICE_FAILED: - case WifiP2pManager.REMOVE_LOCAL_SERVICE_FAILED: - case WifiP2pManager.CLEAR_LOCAL_SERVICES_FAILED: - case WifiP2pManager.ADD_SERVICE_REQUEST_FAILED: - case WifiP2pManager.REMOVE_SERVICE_REQUEST_FAILED: - case WifiP2pManager.CLEAR_SERVICE_REQUESTS_FAILED: - case WifiP2pManager.SET_DEVICE_NAME_FAILED: - case WifiP2pManager.DELETE_PERSISTENT_GROUP_FAILED: - case WifiP2pManager.SET_WFD_INFO_FAILED: + case DISCOVER_PEERS_FAILED: + case STOP_DISCOVERY_FAILED: + case DISCOVER_SERVICES_FAILED: + case CONNECT_FAILED: + case CANCEL_CONNECT_FAILED: + case CREATE_GROUP_FAILED: + case REMOVE_GROUP_FAILED: + case ADD_LOCAL_SERVICE_FAILED: + case REMOVE_LOCAL_SERVICE_FAILED: + case CLEAR_LOCAL_SERVICES_FAILED: + case ADD_SERVICE_REQUEST_FAILED: + case REMOVE_SERVICE_REQUEST_FAILED: + case CLEAR_SERVICE_REQUESTS_FAILED: + case SET_DEVICE_NAME_FAILED: + case DELETE_PERSISTENT_GROUP_FAILED: + case SET_WFD_INFO_FAILED: + case START_WPS_FAILED: if (listener != null) { ((ActionListener) listener).onFailure(message.arg1); } break; /* ActionListeners grouped together */ - case WifiP2pManager.DISCOVER_PEERS_SUCCEEDED: - case WifiP2pManager.STOP_DISCOVERY_SUCCEEDED: - case WifiP2pManager.DISCOVER_SERVICES_SUCCEEDED: - case WifiP2pManager.CONNECT_SUCCEEDED: - case WifiP2pManager.CANCEL_CONNECT_SUCCEEDED: - case WifiP2pManager.CREATE_GROUP_SUCCEEDED: - case WifiP2pManager.REMOVE_GROUP_SUCCEEDED: - case WifiP2pManager.ADD_LOCAL_SERVICE_SUCCEEDED: - case WifiP2pManager.REMOVE_LOCAL_SERVICE_SUCCEEDED: - case WifiP2pManager.CLEAR_LOCAL_SERVICES_SUCCEEDED: - case WifiP2pManager.ADD_SERVICE_REQUEST_SUCCEEDED: - case WifiP2pManager.REMOVE_SERVICE_REQUEST_SUCCEEDED: - case WifiP2pManager.CLEAR_SERVICE_REQUESTS_SUCCEEDED: - case WifiP2pManager.SET_DEVICE_NAME_SUCCEEDED: - case WifiP2pManager.DELETE_PERSISTENT_GROUP_SUCCEEDED: - case WifiP2pManager.SET_WFD_INFO_SUCCEEDED: + case DISCOVER_PEERS_SUCCEEDED: + case STOP_DISCOVERY_SUCCEEDED: + case DISCOVER_SERVICES_SUCCEEDED: + case CONNECT_SUCCEEDED: + case CANCEL_CONNECT_SUCCEEDED: + case CREATE_GROUP_SUCCEEDED: + case REMOVE_GROUP_SUCCEEDED: + case ADD_LOCAL_SERVICE_SUCCEEDED: + case REMOVE_LOCAL_SERVICE_SUCCEEDED: + case CLEAR_LOCAL_SERVICES_SUCCEEDED: + case ADD_SERVICE_REQUEST_SUCCEEDED: + case REMOVE_SERVICE_REQUEST_SUCCEEDED: + case CLEAR_SERVICE_REQUESTS_SUCCEEDED: + case SET_DEVICE_NAME_SUCCEEDED: + case DELETE_PERSISTENT_GROUP_SUCCEEDED: + case SET_WFD_INFO_SUCCEEDED: + case START_WPS_SUCCEEDED: if (listener != null) { ((ActionListener) listener).onSuccess(); } break; - case WifiP2pManager.RESPONSE_PEERS: + case RESPONSE_PEERS: WifiP2pDeviceList peers = (WifiP2pDeviceList) message.obj; if (listener != null) { ((PeerListListener) listener).onPeersAvailable(peers); } break; - case WifiP2pManager.RESPONSE_CONNECTION_INFO: + case RESPONSE_CONNECTION_INFO: WifiP2pInfo wifiP2pInfo = (WifiP2pInfo) message.obj; if (listener != null) { ((ConnectionInfoListener) listener).onConnectionInfoAvailable(wifiP2pInfo); } break; - case WifiP2pManager.RESPONSE_GROUP_INFO: + case RESPONSE_GROUP_INFO: WifiP2pGroup group = (WifiP2pGroup) message.obj; if (listener != null) { ((GroupInfoListener) listener).onGroupInfoAvailable(group); } break; - case WifiP2pManager.RESPONSE_SERVICE: + case RESPONSE_SERVICE: WifiP2pServiceResponse resp = (WifiP2pServiceResponse) message.obj; handleServiceResponse(resp); break; - case WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO: + case RESPONSE_PERSISTENT_GROUP_INFO: WifiP2pGroupList groups = (WifiP2pGroupList) message.obj; if (listener != null) { ((PersistentGroupInfoListener) listener). @@ -790,6 +801,13 @@ public class WifiP2pManager { if (req == null) throw new IllegalArgumentException("service request is null"); } + private static void checkP2pConfig(WifiP2pConfig c) { + if (c == null) throw new IllegalArgumentException("config cannot be null"); + if (TextUtils.isEmpty(c.deviceAddress)) { + throw new IllegalArgumentException("deviceAddress cannot be empty"); + } + } + /** * Registers the application with the Wi-Fi framework. This function * must be the first to be called before any p2p operations are performed. @@ -876,6 +894,7 @@ public class WifiP2pManager { */ public void connect(Channel c, WifiP2pConfig config, ActionListener listener) { checkChannel(c); + checkP2pConfig(config); c.mAsyncChannel.sendMessage(CONNECT, 0, c.putListener(listener), config); } @@ -937,6 +956,21 @@ public class WifiP2pManager { } /** + * Start a Wi-Fi Protected Setup (WPS) session. + * + * <p> The function call immediately returns after sending a request to start a + * WPS session. Currently, this is only valid if the current device is running + * as a group owner to allow any new clients to join the group. The application + * is notified of a success or failure to initiate WPS through listener callbacks + * {@link ActionListener#onSuccess} or {@link ActionListener#onFailure}. + * @hide + */ + public void startWps(Channel c, WpsInfo wps, ActionListener listener) { + checkChannel(c); + c.mAsyncChannel.sendMessage(START_WPS, 0, c.putListener(listener), wps); + } + + /** * Register a local service for service discovery. If a local service is registered, * the framework automatically responds to a service discovery request from a peer. * diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index c1d177d..debf988 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -114,16 +114,9 @@ public class WifiP2pService extends IWifiP2pManager.Stub { private static final Boolean JOIN_GROUP = true; private static final Boolean FORM_GROUP = false; - private static final Boolean TRY_REINVOCATION = true;; - private static final Boolean NO_REINVOCATION = false; - private static final Boolean RELOAD = true; private static final Boolean NO_RELOAD = false; - private static final int CONNECT_FAILURE = -1; - private static final int CONNECT_SUCCESS = 0; - private static final int NEEDS_PROVISION_REQ = 1; - /* Two minutes comes from the wpa_supplicant setting */ private static final int GROUP_CREATING_WAIT_TIME_MS = 120 * 1000; private static int mGroupCreatingTimeoutIndex = 0; @@ -361,8 +354,10 @@ public class WifiP2pService extends IWifiP2pManager.Stub { // Inactive is when p2p is enabled with no connectivity private InactiveState mInactiveState = new InactiveState(); private GroupCreatingState mGroupCreatingState = new GroupCreatingState(); - private UserAuthorizingInvitationState mUserAuthorizingInvitationState - = new UserAuthorizingInvitationState(); + private UserAuthorizingInviteRequestState mUserAuthorizingInviteRequestState + = new UserAuthorizingInviteRequestState(); + private UserAuthorizingNegotiationRequestState mUserAuthorizingNegotiationRequestState + = new UserAuthorizingNegotiationRequestState(); private ProvisionDiscoveryState mProvisionDiscoveryState = new ProvisionDiscoveryState(); private GroupNegotiationState mGroupNegotiationState = new GroupNegotiationState(); private FrequencyConflictState mFrequencyConflictState =new FrequencyConflictState(); @@ -397,8 +392,10 @@ public class WifiP2pService extends IWifiP2pManager.Stub { private final WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo(); private WifiP2pGroup mGroup; - // Saved WifiP2pConfig for a peer connection - private WifiP2pConfig mSavedPeerConfig; + // Saved WifiP2pConfig for an ongoing peer connection. This will never be null. + // The deviceAddress will be an empty string when the device is inactive + // or if it is connected without any ongoing join request + private WifiP2pConfig mSavedPeerConfig = new WifiP2pConfig(); // Saved WifiP2pGroup from invitation request private WifiP2pGroup mSavedP2pGroup; @@ -414,7 +411,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub { addState(mP2pEnabledState, mDefaultState); addState(mInactiveState, mP2pEnabledState); addState(mGroupCreatingState, mP2pEnabledState); - addState(mUserAuthorizingInvitationState, mGroupCreatingState); + addState(mUserAuthorizingInviteRequestState, mGroupCreatingState); + addState(mUserAuthorizingNegotiationRequestState, mGroupCreatingState); addState(mProvisionDiscoveryState, mGroupCreatingState); addState(mGroupNegotiationState, mGroupCreatingState); addState(mFrequencyConflictState, mGroupCreatingState); @@ -541,6 +539,10 @@ public class WifiP2pService extends IWifiP2pManager.Stub { replyToMessage(message, WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO, new WifiP2pGroupList(mGroups, null)); break; + case WifiP2pManager.START_WPS: + replyToMessage(message, WifiP2pManager.START_WPS_FAILED, + WifiP2pManager.BUSY); + break; // Ignore case WifiMonitor.P2P_INVITATION_RESULT_EVENT: case WifiMonitor.SCAN_RESULTS_EVENT: @@ -667,6 +669,10 @@ public class WifiP2pService extends IWifiP2pManager.Stub { replyToMessage(message, WifiP2pManager.SET_WFD_INFO_FAILED, WifiP2pManager.P2P_UNSUPPORTED); break; + case WifiP2pManager.START_WPS: + replyToMessage(message, WifiP2pManager.START_WPS_FAILED, + WifiP2pManager.P2P_UNSUPPORTED); + break; default: return NOT_HANDLED; } @@ -943,9 +949,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { @Override public void enter() { if (DBG) logd(getName()); - //Start listening every time we get inactive - //TODO: Fix listen after driver behavior is fixed - //mWifiNative.p2pListen(); + mSavedPeerConfig.invalidate(); } @Override @@ -955,25 +959,23 @@ public class WifiP2pService extends IWifiP2pManager.Stub { case WifiP2pManager.CONNECT: if (DBG) logd(getName() + " sending connect"); WifiP2pConfig config = (WifiP2pConfig) message.obj; - mAutonomousGroup = false; - - /* Update group capability before connect */ - int gc = mWifiNative.getGroupCapability(config.deviceAddress); - mPeers.updateGroupCapability(config.deviceAddress, gc); - int connectRet = connect(config, TRY_REINVOCATION); - if (connectRet == CONNECT_FAILURE) { + if (isConfigInvalid(config)) { + loge("Dropping connect requeset " + config); replyToMessage(message, WifiP2pManager.CONNECT_FAILED); break; } + + mAutonomousGroup = false; + mWifiNative.p2pStopFind(); + if (reinvokePersistentGroup(config)) { + transitionTo(mGroupNegotiationState); + } else { + transitionTo(mProvisionDiscoveryState); + } + mSavedPeerConfig = config; mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED); sendPeersChangedBroadcast(); replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); - if (connectRet == NEEDS_PROVISION_REQ) { - if (DBG) logd("Sending prov disc"); - transitionTo(mProvisionDiscoveryState); - break; - } - transitionTo(mGroupNegotiationState); break; case WifiP2pManager.STOP_DISCOVERY: if (mWifiNative.p2pStopFind()) { @@ -988,22 +990,33 @@ public class WifiP2pService extends IWifiP2pManager.Stub { } break; case WifiMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT: - mSavedPeerConfig = (WifiP2pConfig) message.obj; + config = (WifiP2pConfig) message.obj; + if (isConfigInvalid(config)) { + loge("Dropping GO neg request " + config); + break; + } + mSavedPeerConfig = config; mAutonomousGroup = false; mJoinExistingGroup = false; - transitionTo(mUserAuthorizingInvitationState); + transitionTo(mUserAuthorizingNegotiationRequestState); break; case WifiMonitor.P2P_INVITATION_RECEIVED_EVENT: WifiP2pGroup group = (WifiP2pGroup) message.obj; WifiP2pDevice owner = group.getOwner(); if (owner == null) { - if (DBG) loge("Ignored invitation from null owner"); + loge("Ignored invitation from null owner"); break; } - mSavedPeerConfig = new WifiP2pConfig(); - mSavedPeerConfig.deviceAddress = group.getOwner().deviceAddress; + config = new WifiP2pConfig(); + config.deviceAddress = group.getOwner().deviceAddress; + + if (isConfigInvalid(config)) { + loge("Dropping invitation request " + config); + break; + } + mSavedPeerConfig = config; //Check if we have the owner in peer list and use appropriate //wps method. Default is to use PBC. @@ -1019,7 +1032,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { mAutonomousGroup = false; mJoinExistingGroup = true; - transitionTo(mUserAuthorizingInvitationState); + transitionTo(mUserAuthorizingInviteRequestState); break; case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: @@ -1097,11 +1110,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { break; case WifiMonitor.P2P_DEVICE_LOST_EVENT: WifiP2pDevice device = (WifiP2pDevice) message.obj; - - // If we lose a device during an autonomous group creation, - // mSavedPeerConfig can be empty - if (mSavedPeerConfig != null && - !mSavedPeerConfig.deviceAddress.equals(device.deviceAddress)) { + if (!mSavedPeerConfig.deviceAddress.equals(device.deviceAddress)) { if (DBG) { logd("mSavedPeerConfig " + mSavedPeerConfig.deviceAddress + "device " + device.deviceAddress); @@ -1137,7 +1146,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { } } - class UserAuthorizingInvitationState extends State { + class UserAuthorizingNegotiationRequestState extends State { @Override public void enter() { if (DBG) logd(getName()); @@ -1150,18 +1159,52 @@ public class WifiP2pService extends IWifiP2pManager.Stub { boolean ret = HANDLED; switch (message.what) { case PEER_CONNECTION_USER_ACCEPT: - if (connect(mSavedPeerConfig, TRY_REINVOCATION) == CONNECT_FAILURE) { - handleGroupCreationFailure(); - transitionTo(mInactiveState); - break; - } + mWifiNative.p2pStopFind(); + p2pConnectWithPinDisplay(mSavedPeerConfig); mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED); sendPeersChangedBroadcast(); transitionTo(mGroupNegotiationState); + break; + case PEER_CONNECTION_USER_REJECT: + if (DBG) logd("User rejected negotiation " + mSavedPeerConfig); + transitionTo(mInactiveState); break; + default: + return NOT_HANDLED; + } + return ret; + } + + @Override + public void exit() { + //TODO: dismiss dialog if not already done + } + } + + class UserAuthorizingInviteRequestState extends State { + @Override + public void enter() { + if (DBG) logd(getName()); + notifyInvitationReceived(); + } + + @Override + public boolean processMessage(Message message) { + if (DBG) logd(getName() + message.toString()); + boolean ret = HANDLED; + switch (message.what) { + case PEER_CONNECTION_USER_ACCEPT: + mWifiNative.p2pStopFind(); + if (!reinvokePersistentGroup(mSavedPeerConfig)) { + // Do negotiation when persistence fails + p2pConnectWithPinDisplay(mSavedPeerConfig); + } + mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED); + sendPeersChangedBroadcast(); + transitionTo(mGroupNegotiationState); + break; case PEER_CONNECTION_USER_REJECT: if (DBG) logd("User rejected invitation " + mSavedPeerConfig); - mSavedPeerConfig = null; transitionTo(mInactiveState); break; default: @@ -1176,6 +1219,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub { } } + + class ProvisionDiscoveryState extends State { @Override public void enter() { @@ -1213,7 +1258,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { transitionTo(mGroupNegotiationState); } else { mJoinExistingGroup = false; - transitionTo(mUserAuthorizingInvitationState); + transitionTo(mUserAuthorizingNegotiationRequestState); } } break; @@ -1292,7 +1337,6 @@ public class WifiP2pService extends IWifiP2pManager.Stub { mPeers.updateStatus(groupOwner.deviceAddress, WifiP2pDevice.CONNECTED); sendPeersChangedBroadcast(); } - mSavedPeerConfig = null; transitionTo(mGroupCreatedState); break; case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT: @@ -1323,7 +1367,9 @@ public class WifiP2pService extends IWifiP2pManager.Stub { // invocation was succeeded. // wait P2P_GROUP_STARTED_EVENT. break; - } else if (status == P2pStatus.UNKNOWN_P2P_GROUP) { + } + loge("Invitation result " + status); + if (status == P2pStatus.UNKNOWN_P2P_GROUP) { // target device has already removed the credential. // So, remove this credential accordingly. int netId = mSavedPeerConfig.netId; @@ -1332,12 +1378,9 @@ public class WifiP2pService extends IWifiP2pManager.Stub { removeClientFromList(netId, mSavedPeerConfig.deviceAddress, true); } - // invocation is failed. Try another way to connect. + // Reinvocation has failed, try group negotiation mSavedPeerConfig.netId = WifiP2pGroup.PERSISTENT_NET_ID; - if (connect(mSavedPeerConfig, NO_REINVOCATION) == CONNECT_FAILURE) { - handleGroupCreationFailure(); - transitionTo(mInactiveState); - } + p2pConnectWithPinDisplay(mSavedPeerConfig); } else if (status == P2pStatus.INFORMATION_IS_CURRENTLY_UNAVAILABLE) { // Devices setting persistent_reconnect to 0 in wpa_supplicant @@ -1345,10 +1388,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { // "information is currently unable" error. // So, try another way to connect for interoperability. mSavedPeerConfig.netId = WifiP2pGroup.PERSISTENT_NET_ID; - if (connect(mSavedPeerConfig, NO_REINVOCATION) == CONNECT_FAILURE) { - handleGroupCreationFailure(); - transitionTo(mInactiveState); - } + p2pConnectWithPinDisplay(mSavedPeerConfig); } else if (status == P2pStatus.NO_COMMON_CHANNEL) { transitionTo(mFrequencyConflictState); } else { @@ -1452,6 +1492,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub { @Override public void enter() { if (DBG) logd(getName()); + // Once connected, peer config details are invalid + mSavedPeerConfig.invalidate(); mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); updateThisDevice(WifiP2pDevice.CONNECTED); @@ -1497,7 +1539,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { if (mGroup.removeClient(deviceAddress)) { if (DBG) logd("Removed client " + deviceAddress); if (!mAutonomousGroup && mGroup.isClientListEmpty()) { - Slog.d(TAG, "Client list empty, remove non-persistent p2p group"); + logd("Client list empty, remove non-persistent p2p group"); mWifiNative.p2pGroupRemove(mGroup.getInterface()); // We end up sending connection changed broadcast // when this happens at exit() @@ -1573,50 +1615,61 @@ public class WifiP2pService extends IWifiP2pManager.Stub { sendMessage(WifiP2pManager.REMOVE_GROUP); deferMessage(message); break; - case WifiP2pManager.CONNECT: - WifiP2pConfig config = (WifiP2pConfig) message.obj; // This allows any client to join the GO during the // WPS window - if (config.deviceAddress == null) { - if (config.wps.setup == WpsInfo.PBC) { - mWifiNative.startWpsPbc(mGroup.getInterface(), null); - } else { - if (config.wps.pin == null) { - String pin = mWifiNative.startWpsPinDisplay(mGroup.getInterface()); - try { - Integer.parseInt(pin); - notifyInvitationSent(pin, config.deviceAddress != null ? - config.deviceAddress : "any"); - } catch (NumberFormatException ignore) { - // do nothing if pin is invalid - } - } else { - mWifiNative.startWpsPinKeypad(mGroup.getInterface(), - config.wps.pin); - } - } - replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); + case WifiP2pManager.START_WPS: + WpsInfo wps = (WpsInfo) message.obj; + if (wps == null) { + replyToMessage(message, WifiP2pManager.START_WPS_FAILED); + break; + } + boolean ret = true; + if (wps.setup == WpsInfo.PBC) { + ret = mWifiNative.startWpsPbc(mGroup.getInterface(), null); } else { - logd("Inviting device : " + config.deviceAddress); - mSavedPeerConfig = config; - if (mWifiNative.p2pInvite(mGroup, config.deviceAddress)) { - mPeers.updateStatus(config.deviceAddress, WifiP2pDevice.INVITED); - sendPeersChangedBroadcast(); - replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); + if (wps.pin == null) { + String pin = mWifiNative.startWpsPinDisplay(mGroup.getInterface()); + try { + Integer.parseInt(pin); + notifyInvitationSent(pin, "any"); + } catch (NumberFormatException ignore) { + ret = false; + } } else { - replyToMessage(message, WifiP2pManager.CONNECT_FAILED, - WifiP2pManager.ERROR); + ret = mWifiNative.startWpsPinKeypad(mGroup.getInterface(), + wps.pin); } } + replyToMessage(message, ret ? WifiP2pManager.START_WPS_SUCCEEDED : + WifiP2pManager.START_WPS_FAILED); + break; + case WifiP2pManager.CONNECT: + WifiP2pConfig config = (WifiP2pConfig) message.obj; + if (isConfigInvalid(config)) { + loge("Dropping connect requeset " + config); + replyToMessage(message, WifiP2pManager.CONNECT_FAILED); + break; + } + logd("Inviting device : " + config.deviceAddress); + mSavedPeerConfig = config; + if (mWifiNative.p2pInvite(mGroup, config.deviceAddress)) { + mPeers.updateStatus(config.deviceAddress, WifiP2pDevice.INVITED); + sendPeersChangedBroadcast(); + replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); + } else { + replyToMessage(message, WifiP2pManager.CONNECT_FAILED, + WifiP2pManager.ERROR); + } // TODO: figure out updating the status to declined when invitation is rejected break; case WifiMonitor.P2P_INVITATION_RESULT_EVENT: P2pStatus status = (P2pStatus)message.obj; - logd("===> INVITATION RESULT EVENT : " + status); if (status == P2pStatus.SUCCESS) { // invocation was succeeded. break; - } else if (status == P2pStatus.UNKNOWN_P2P_GROUP) { + } + loge("Invitation result " + status); + if (status == P2pStatus.UNKNOWN_P2P_GROUP) { // target device has already removed the credential. // So, remove this credential accordingly. int netId = mGroup.getNetworkId(); @@ -1625,7 +1678,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { if (!removeClientFromList(netId, mSavedPeerConfig.deviceAddress, false)) { // not found the client on the list - Slog.e(TAG, "Already removed the client, ignore"); + loge("Already removed the client, ignore"); break; } // try invitation. @@ -1650,7 +1703,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { transitionTo(mUserAuthorizingJoinState); break; case WifiMonitor.P2P_GROUP_STARTED_EVENT: - Slog.e(TAG, "Duplicate group creation event notice, ignore"); + loge("Duplicate group creation event notice, ignore"); break; default: return NOT_HANDLED; @@ -1689,12 +1742,10 @@ public class WifiP2pService extends IWifiP2pManager.Stub { mWifiNative.startWpsPinKeypad(mGroup.getInterface(), mSavedPeerConfig.wps.pin); } - mSavedPeerConfig = null; transitionTo(mGroupCreatedState); break; case PEER_CONNECTION_USER_REJECT: if (DBG) logd("User rejected incoming request"); - mSavedPeerConfig = null; transitionTo(mGroupCreatedState); break; default: @@ -2025,30 +2076,52 @@ public class WifiP2pService extends IWifiP2pManager.Stub { } /** - * Try to connect to the target device. - * - * Use the persistent credential if it has been stored. - * - * @param config - * @param tryInvocation if true, try to invoke. Otherwise, never try to invoke. - * @return + * A config is valid if it has a peer address that has already been + * discovered + * @return true if it is invalid, false otherwise */ - private int connect(WifiP2pConfig config, boolean tryInvocation) { + private boolean isConfigInvalid(WifiP2pConfig config) { + if (config == null) return true; + if (TextUtils.isEmpty(config.deviceAddress)) return true; + if (mPeers.get(config.deviceAddress) == null) return true; + return false; + } - if (config == null) { - loge("config is null"); - return CONNECT_FAILURE; - } + /* TODO: The supplicant does not provide group capability changes as an event. + * Having it pushed as an event would avoid polling for this information right + * before a connection + */ + private WifiP2pDevice fetchCurrentDeviceDetails(WifiP2pConfig config) { + /* Fetch & update group capability from supplicant on the device */ + int gc = mWifiNative.getGroupCapability(config.deviceAddress); + mPeers.updateGroupCapability(config.deviceAddress, gc); + return mPeers.get(config.deviceAddress); + } - boolean isResp = (mSavedPeerConfig != null && - config.deviceAddress.equals(mSavedPeerConfig.deviceAddress)); - mSavedPeerConfig = config; + /** + * Start a p2p group negotiation and display pin if necessary + * @param config for the peer + */ + private void p2pConnectWithPinDisplay(WifiP2pConfig config) { + WifiP2pDevice dev = fetchCurrentDeviceDetails(config); - WifiP2pDevice dev = mPeers.get(config.deviceAddress); - if (dev == null) { - loge("target device not found " + config.deviceAddress); - return CONNECT_FAILURE; + String pin = mWifiNative.p2pConnect(config, dev.isGroupOwner()); + try { + Integer.parseInt(pin); + notifyInvitationSent(pin, config.deviceAddress); + } catch (NumberFormatException ignore) { + // do nothing if p2pConnect did not return a pin } + } + + /** + * Reinvoke a persistent group. + * + * @param config for the peer + * @return true on success, false on failure + */ + private boolean reinvokePersistentGroup(WifiP2pConfig config) { + WifiP2pDevice dev = fetchCurrentDeviceDetails(config); boolean join = dev.isGroupOwner(); String ssid = mWifiNative.p2pGetSsid(dev.deviceAddress); @@ -2065,18 +2138,18 @@ public class WifiP2pService extends IWifiP2pManager.Stub { if (netId >= 0) { // Skip WPS and start 4way handshake immediately. if (!mWifiNative.p2pGroupAdd(netId)) { - return CONNECT_FAILURE; + return false; } - return CONNECT_SUCCESS; + return true; } } if (!join && dev.isDeviceLimit()) { loge("target device reaches the device limit."); - return CONNECT_FAILURE; + return false; } - if (!join && tryInvocation && dev.isInvitationCapable()) { + if (!join && dev.isInvitationCapable()) { int netId = WifiP2pGroup.PERSISTENT_NET_ID; if (config.netId >= 0) { if (config.deviceAddress.equals(mGroups.getOwnerAddr(config.netId))) { @@ -2093,25 +2166,17 @@ public class WifiP2pService extends IWifiP2pManager.Stub { // Invoke the persistent group. if (mWifiNative.p2pReinvoke(netId, dev.deviceAddress)) { // Save network id. It'll be used when an invitation result event is received. - mSavedPeerConfig.netId = netId; - return CONNECT_SUCCESS; + config.netId = netId; + return true; } else { loge("p2pReinvoke() failed, update networks"); updatePersistentNetworks(RELOAD); - // continue with negotiation + return false; } } } - //Stop discovery before issuing connect - mWifiNative.p2pStopFind(); - - if (!isResp) { - return NEEDS_PROVISION_REQ; - } - - p2pConnectWithPinDisplay(config); - return CONNECT_SUCCESS; + return false; } /** @@ -2217,22 +2282,6 @@ public class WifiP2pService extends IWifiP2pManager.Stub { return deviceAddress; } - private void p2pConnectWithPinDisplay(WifiP2pConfig config) { - WifiP2pDevice dev = mPeers.get(config.deviceAddress); - if (dev == null) { - loge("target device is not found " + config.deviceAddress); - return; - } - - String pin = mWifiNative.p2pConnect(config, dev.isGroupOwner()); - try { - Integer.parseInt(pin); - notifyInvitationSent(pin, config.deviceAddress); - } catch (NumberFormatException ignore) { - // do nothing if p2pConnect did not return a pin - } - } - private String getPersistedDeviceName() { String deviceName = Settings.Global.getString(mContext.getContentResolver(), Settings.Global.WIFI_P2P_DEVICE_NAME); @@ -2299,7 +2348,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { mThisDevice.deviceAddress = mWifiNative.p2pGetDeviceAddress(); updateThisDevice(WifiP2pDevice.AVAILABLE); - if (DBG) Slog.d(TAG, "DeviceAddress: " + mThisDevice.deviceAddress); + if (DBG) logd("DeviceAddress: " + mThisDevice.deviceAddress); mClientInfoList.clear(); mWifiNative.p2pFlush(); @@ -2323,14 +2372,13 @@ public class WifiP2pService extends IWifiP2pManager.Stub { // Remove only the peer we failed to connect to so that other devices discovered // that have not timed out still remain in list for connection boolean peersChanged = mPeers.remove(mPeersLostDuringConnection); - if (mSavedPeerConfig != null && mPeers.remove(mSavedPeerConfig.deviceAddress) != null) { + if (mPeers.remove(mSavedPeerConfig.deviceAddress) != null) { peersChanged = true; } if (peersChanged) { sendPeersChangedBroadcast(); } - mSavedPeerConfig = null; mPeersLostDuringConnection.clear(); mServiceDiscReqId = null; sendMessage(WifiP2pManager.DISCOVER_PEERS); |