Initialize p2p settings

And fix associated changes from the settings.

With p2p_reconnect setting turned on, it means the p2p group can be
started without a group negotiation. Hence, handle p2p group started in
the P2pEnabledState

Also, reinvocation results in supplicant not reporting device address correctly.
Handle that until supplicant fix is fixed.

Bug: 5002384

Change-Id: I335f6e854acd6839f54da9b460b17ad7505b1098
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8fbb09e..738ef0d 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -189,6 +189,9 @@
 
     <!-- Boolean indicating whether the wifi chipset has p2p support -->
     <bool translatable="false" name="config_wifi_p2p_support">false</bool>
+    <!-- Device type information conforming to Annex B format in WiFi Direct specification.
+         The default represents a dual-mode smartphone -->
+    <string translatable="false" name="config_wifi_p2p_device_type">10-0050F204-5</string>
 
     <!-- Boolean indicating whether the wifi chipset supports background scanning mechanism.
          This mechanism allows the host to remain in suspend state and the dongle to actively
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 8d327d0..2cd54d9 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -217,6 +217,19 @@
         return doBooleanCommand("WPS_PIN any " + pin);
     }
 
+    public static boolean setPersistentReconnect(boolean enabled) {
+        int value = (enabled == true) ? 1 : 0;
+        return WifiNative.doBooleanCommand("SET persistent_reconnect " + value);
+    }
+
+    public static boolean setDeviceName(String name) {
+        return WifiNative.doBooleanCommand("SET device_name " + name);
+    }
+
+    public static boolean setDeviceType(String type) {
+        return WifiNative.doBooleanCommand("SET device_type " + type);
+    }
+
     public static boolean p2pFind() {
         return doBooleanCommand("P2P_FIND");
     }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index bdf0120..f67680d 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -50,6 +50,7 @@
 import android.os.Messenger;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.provider.Settings;
 import android.util.Slog;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -126,6 +127,8 @@
     private static final int WIFI_DISABLE_USER_ACCEPT       =   BASE + 11;
 
     private final boolean mP2pSupported;
+    private final String mDeviceType;
+    private String mDeviceName;
 
     private NetworkInfo mNetworkInfo;
 
@@ -142,6 +145,9 @@
 
         mP2pSupported = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_wifi_p2p_support);
+        mDeviceType = mContext.getResources().getString(
+                com.android.internal.R.string.config_wifi_p2p_device_type);
+        mDeviceName = getDefaultDeviceName();
 
         mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported);
         mP2pStateMachine.start();
@@ -182,6 +188,14 @@
                 "WifiP2pService");
     }
 
+    /* We use the 4 digits of the ANDROID_ID to have a friendly
+     * default that has low likelihood of collision with a peer */
+    private String getDefaultDeviceName() {
+        String id = Settings.Secure.getString(mContext.getContentResolver(),
+                    Settings.Secure.ANDROID_ID);
+        return "Android_" + id.substring(0,4);
+    }
+
     /**
      * Get a reference to handler. This is used by a client to establish
      * an AsyncChannel communication with WifiP2pService
@@ -577,6 +591,7 @@
             mNetworkInfo.setIsAvailable(true);
             //Start listening for new connections
             WifiNative.p2pListen();
+            initializeP2pSettings();
         }
 
         @Override
@@ -637,6 +652,22 @@
                     if (mPeers.clear()) sendP2pPeersChangedBroadcast();
                     transitionTo(mP2pDisabledState);
                     sendMessageDelayed(WifiP2pManager.ENABLE_P2P, P2P_RESTART_INTERVAL_MSECS);
+                    break;
+                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
+                    mGroup = (WifiP2pGroup) message.obj;
+                    if (DBG) logd(getName() + " group started");
+                    if (mGroup.isGroupOwner()) {
+                        startDhcpServer(mGroup.getInterface());
+                    } else {
+                        mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
+                                P2pStateMachine.this, mGroup.getInterface());
+                        mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
+                        WifiP2pDevice groupOwner = mGroup.getOwner();
+                        updateDeviceStatus(groupOwner.deviceAddress, Status.CONNECTED);
+                        sendP2pPeersChangedBroadcast();
+                    }
+                    transitionTo(mGroupCreatedState);
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -708,21 +739,6 @@
                     sendP2pPeersChangedBroadcast();
                     transitionTo(mInactiveState);
                     break;
-                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
-                    mGroup = (WifiP2pGroup) message.obj;
-                    if (DBG) logd(getName() + " group started");
-                    if (mGroup.isGroupOwner()) {
-                        startDhcpServer(mGroup.getInterface());
-                    } else {
-                        mDhcpStateMachine = DhcpStateMachine.makeDhcpStateMachine(mContext,
-                                P2pStateMachine.this, mGroup.getInterface());
-                        mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
-                        WifiP2pDevice groupOwner = mGroup.getOwner();
-                        updateDeviceStatus(groupOwner.deviceAddress, Status.CONNECTED);
-                        sendP2pPeersChangedBroadcast();
-                    }
-                    transitionTo(mGroupCreatedState);
-                    break;
                 case GROUP_NEGOTIATION_TIMED_OUT:
                     if (mGroupNegotiationTimeoutIndex == message.arg1) {
                         if (DBG) logd("Group negotiation timed out");
@@ -760,25 +776,33 @@
                     //After a GO setup, STA connected event comes with interface address
                     String interfaceAddress = (String) message.obj;
                     String deviceAddress = getDeviceAddress(interfaceAddress);
-                    mGroup.addClient(deviceAddress);
-                    updateDeviceStatus(deviceAddress, Status.CONNECTED);
-                    if (DBG) logd(getName() + " ap sta connected");
-                    sendP2pPeersChangedBroadcast();
+                    if (deviceAddress != null) {
+                        mGroup.addClient(deviceAddress);
+                        updateDeviceStatus(deviceAddress, Status.CONNECTED);
+                        if (DBG) logd(getName() + " ap sta connected");
+                        sendP2pPeersChangedBroadcast();
+                    } else {
+                        loge("Connect on unknown device address : " + interfaceAddress);
+                    }
                     break;
                 case WifiMonitor.AP_STA_DISCONNECTED_EVENT:
                     interfaceAddress = (String) message.obj;
                     deviceAddress = getDeviceAddress(interfaceAddress);
-                    updateDeviceStatus(deviceAddress, Status.AVAILABLE);
-                    if (mGroup.removeClient(deviceAddress)) {
-                        if (DBG) logd("Removed client " + deviceAddress);
-                        sendP2pPeersChangedBroadcast();
-                    } else {
-                        if (DBG) logd("Failed to remove client " + deviceAddress);
-                        for (WifiP2pDevice c : mGroup.getClientList()) {
-                            if (DBG) logd("client " + c.deviceAddress);
+                    if (deviceAddress != null) {
+                        updateDeviceStatus(deviceAddress, Status.AVAILABLE);
+                        if (mGroup.removeClient(deviceAddress)) {
+                            if (DBG) logd("Removed client " + deviceAddress);
+                            sendP2pPeersChangedBroadcast();
+                        } else {
+                            if (DBG) logd("Failed to remove client " + deviceAddress);
+                            for (WifiP2pDevice c : mGroup.getClientList()) {
+                                if (DBG) logd("client " + c.deviceAddress);
+                            }
                         }
+                        if (DBG) loge(getName() + " ap sta disconnected");
+                    } else {
+                        loge("Disconnect on unknown device address : " + interfaceAddress);
                     }
-                    if (DBG) loge(getName() + " ap sta disconnected");
                     break;
                 case DhcpStateMachine.CMD_POST_DHCP_ACTION:
                     DhcpInfoInternal dhcpInfo = (DhcpInfoInternal) message.obj;
@@ -857,6 +881,9 @@
                 case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT:
                     notifyP2pProvDiscPinRequest((WifiP2pDevice) message.obj);
                     break;
+                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
+                    Slog.e(TAG, "Duplicate group creation event notice, ignore");
+                    break;
                 case WifiP2pManager.WPS_PBC:
                     WifiNative.wpsPbc();
                     break;
@@ -1117,6 +1144,12 @@
         return null;
     }
 
+    private void initializeP2pSettings() {
+        WifiNative.setPersistentReconnect(true);
+        WifiNative.setDeviceName(mDeviceName);
+        WifiNative.setDeviceType(mDeviceType);
+    }
+
     //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) {