Merge "P2p fixes" into jb-mr1-dev
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index ab54a15..93ab4a4 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -217,6 +217,8 @@
        pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27
        group_capab=0x0 */
     private static final String P2P_PROV_DISC_SHOW_PIN_STR = "P2P-PROV-DISC-SHOW-PIN";
+    /* P2P-PROV-DISC-FAILURE p2p_dev_addr=42:fc:89:e1:e2:27 */
+    private static final String P2P_PROV_DISC_FAILURE_STR = "P2P-PROV-DISC-FAILURE";
 
     /*
      * Protocol format is as follows.<br>
@@ -319,6 +321,7 @@
     public static final int P2P_PROV_DISC_SHOW_PIN_EVENT         = BASE + 36;
     public static final int P2P_FIND_STOPPED_EVENT               = BASE + 37;
     public static final int P2P_SERV_DISC_RESP_EVENT             = BASE + 38;
+    public static final int P2P_PROV_DISC_FAILURE_EVENT          = BASE + 39;
 
     /* hostap events */
     public static final int AP_STA_DISCONNECTED_EVENT            = BASE + 41;
@@ -615,6 +618,8 @@
             } else if (dataString.startsWith(P2P_PROV_DISC_SHOW_PIN_STR)) {
                 mStateMachine.sendMessage(P2P_PROV_DISC_SHOW_PIN_EVENT,
                         new WifiP2pProvDiscEvent(dataString));
+            } else if (dataString.startsWith(P2P_PROV_DISC_FAILURE_STR)) {
+                mStateMachine.sendMessage(P2P_PROV_DISC_FAILURE_EVENT);
             } else if (dataString.startsWith(P2P_SERV_DISC_RESP_STR)) {
                 List<WifiP2pServiceResponse> list = WifiP2pServiceResponse.newInstance(dataString);
                 if (list != null) {
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
index 863a055..7d71539 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
@@ -260,6 +260,18 @@
         return (groupCapability & GROUP_CAPAB_GROUP_LIMIT) != 0;
     }
 
+    /** @hide */
+    public void update(WifiP2pDevice device) {
+        if (device == null || device.deviceAddress == null) return;
+        deviceName = device.deviceName;
+        primaryDeviceType = device.primaryDeviceType;
+        secondaryDeviceType = device.secondaryDeviceType;
+        wpsConfigMethodsSupported = device.wpsConfigMethodsSupported;
+        deviceCapability = device.deviceCapability;
+        groupCapability = device.groupCapability;
+        wfdInfo = device.wfdInfo;
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (this == obj) return true;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index b317f3f..8f0d8f0 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -346,6 +346,7 @@
 
         private GroupCreatedState mGroupCreatedState = new GroupCreatedState();
         private UserAuthorizingJoinState mUserAuthorizingJoinState = new UserAuthorizingJoinState();
+        private OngoingGroupRemovalState mOngoingGroupRemovalState = new OngoingGroupRemovalState();
 
         private WifiNative mWifiNative = new WifiNative(mInterface);
         private WifiMonitor mWifiMonitor = new WifiMonitor(this, mWifiNative);
@@ -389,6 +390,7 @@
                         addState(mGroupNegotiationState, mGroupCreatingState);
                     addState(mGroupCreatedState, mP2pEnabledState);
                         addState(mUserAuthorizingJoinState, mGroupCreatedState);
+                        addState(mOngoingGroupRemovalState, mGroupCreatedState);
 
             if (p2pSupported) {
                 setInitialState(mP2pDisabledState);
@@ -545,6 +547,7 @@
                 case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
                 case DhcpStateMachine.CMD_POST_DHCP_ACTION:
                 case DhcpStateMachine.CMD_ON_QUIT:
+                case WifiMonitor.P2P_PROV_DISC_FAILURE_EVENT:
                     break;
                     /* unexpected group created, remove */
                 case WifiMonitor.P2P_GROUP_STARTED_EVENT:
@@ -1183,6 +1186,11 @@
                         transitionTo(mGroupNegotiationState);
                     }
                     break;
+                case WifiMonitor.P2P_PROV_DISC_FAILURE_EVENT:
+                    loge("provision discovery failed");
+                    handleGroupCreationFailure();
+                    transitionTo(mInactiveState);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -1228,6 +1236,8 @@
                                 P2pStateMachine.this, mGroup.getInterface());
                         mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
                         WifiP2pDevice groupOwner = mGroup.getOwner();
+                        /* update group owner details with the ones found at discovery */
+                        groupOwner.update(mPeers.get(groupOwner.deviceAddress));
                         mPeers.updateStatus(groupOwner.deviceAddress, WifiP2pDevice.CONNECTED);
                         sendP2pPeersChangedBroadcast();
                     }
@@ -1303,7 +1313,7 @@
                                 deviceAddress.equals(mSavedProvDiscDevice.deviceAddress)) {
                             mSavedProvDiscDevice = null;
                         }
-                        mGroup.addClient(deviceAddress);
+                        mGroup.addClient(mPeers.get(deviceAddress));
                         mPeers.updateStatus(deviceAddress, WifiP2pDevice.CONNECTED);
                         if (DBG) logd(getName() + " ap sta connected");
                         sendP2pPeersChangedBroadcast();
@@ -1357,6 +1367,7 @@
                 case WifiP2pManager.REMOVE_GROUP:
                     if (DBG) logd(getName() + " remove group");
                     if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) {
+                        transitionTo(mOngoingGroupRemovalState);
                         replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
                     } else {
                         handleGroupRemoved();
@@ -1534,6 +1545,30 @@
         }
     }
 
+    class OngoingGroupRemovalState extends State {
+        @Override
+        public void enter() {
+            if (DBG) logd(getName());
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            if (DBG) logd(getName() + message.toString());
+            switch (message.what) {
+                // Group removal ongoing. Multiple calls
+                // end up removing persisted network. Do nothing.
+                case WifiP2pManager.REMOVE_GROUP:
+                    replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED);
+                    break;
+                // Parent state will transition out of this state
+                // when removal is complete
+                default:
+                    return NOT_HANDLED;
+            }
+            return HANDLED;
+        }
+    }
+
     private void sendP2pStateChangedBroadcast(boolean enabled) {
         final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -1858,15 +1893,16 @@
             }
             if (DBG) logd("netId related with " + dev.deviceAddress + " = " + netId);
             if (netId >= 0) {
-
                 // Invoke the persistent group.
-                if (!mWifiNative.p2pReinvoke(netId, dev.deviceAddress)) {
-                    loge("p2pReinvoke() failed");
-                    return CONNECT_FAILURE;
+                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;
+                } else {
+                    loge("p2pReinvoke() failed, update networks");
+                    updatePersistentNetworks();
+                    // continue with negotiation
                 }
-                // Save network id. It'll be used when an invitation result event is received.
-                mSavedPeerConfig.netId = netId;
-                return CONNECT_SUCCESS;
             }
         }