Snap for 6412615 from 5780336dd2d84006e6de8e3331b320bb8c2aba83 to rvc-release

Change-Id: Ieb4f3ffc1eb16e07cc60610eec103054ca32c690
diff --git a/qcwcn/wifi_hal/common.h b/qcwcn/wifi_hal/common.h
index c545ca1..43b03ce 100644
--- a/qcwcn/wifi_hal/common.h
+++ b/qcwcn/wifi_hal/common.h
@@ -208,6 +208,10 @@
 wifi_error wifi_set_radio_mode_change_handler(wifi_request_id id, wifi_interface_handle
         iface, wifi_radio_mode_change_handler eh);
 wifi_error mapKernelErrortoWifiHalError(int kern_err);
+void wifi_cleanup_dynamic_ifaces(wifi_handle handle);
+wifi_error wifi_virtual_interface_create(wifi_handle handle, const char* ifname,
+                                         wifi_interface_type iface_type);
+wifi_error wifi_virtual_interface_delete(wifi_handle handle, const char* ifname);
 // some common macros
 
 #define min(x, y)       ((x) < (y) ? (x) : (y))
diff --git a/qcwcn/wifi_hal/wifi_hal.cpp b/qcwcn/wifi_hal/wifi_hal.cpp
index 2bf7937..7b85099 100644
--- a/qcwcn/wifi_hal/wifi_hal.cpp
+++ b/qcwcn/wifi_hal/wifi_hal.cpp
@@ -571,6 +571,8 @@
     fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
     fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
     fn->wifi_set_radio_mode_change_handler = wifi_set_radio_mode_change_handler;
+    fn->wifi_virtual_interface_create = wifi_virtual_interface_create;
+    fn->wifi_virtual_interface_delete = wifi_virtual_interface_delete;
     fn->wifi_set_latency_mode = wifi_set_latency_mode;
     fn->wifi_set_thermal_mitigation_mode = wifi_set_thermal_mitigation_mode;
 
@@ -1042,6 +1044,9 @@
     hal_info *info = getHalInfo(handle);
     info->cleaned_up_handler = handler;
     info->clean_up = true;
+    // Remove the dynamically created interface during wifi cleanup.
+    wifi_cleanup_dynamic_ifaces(handle);
+
 
     TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
     ALOGI("Sent msg on exit sock to unblock poll()");
diff --git a/qcwcn/wifi_hal/wificonfig.cpp b/qcwcn/wifi_hal/wificonfig.cpp
index 7590f62..8ab296a 100644
--- a/qcwcn/wifi_hal/wificonfig.cpp
+++ b/qcwcn/wifi_hal/wificonfig.cpp
@@ -33,6 +33,9 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <string>
+#include <net/if.h>
+#include <vector>
 #include "wificonfigcommand.h"
 
 /* Implementation of the API functions exposed in wifi_config.h */
@@ -788,3 +791,121 @@
     return res;
 }
 
+static std::vector<std::string> added_ifaces;
+
+static bool is_dynamic_interface(const char * ifname)
+{
+    for (const auto& iface : added_ifaces) {
+        if (iface == std::string(ifname))
+            return true;
+    }
+    return false;
+}
+
+void wifi_cleanup_dynamic_ifaces(wifi_handle handle)
+{
+    int len = added_ifaces.size();
+    while (len--) {
+        wifi_virtual_interface_delete(handle, added_ifaces.front().c_str());
+    }
+    added_ifaces.clear(); // could be redundent. But to be on safe side.
+}
+
+wifi_error wifi_virtual_interface_create(wifi_handle handle,
+                                         const char* ifname,
+                                         wifi_interface_type iface_type)
+{
+    wifi_error ret;
+    WiFiConfigCommand *wifiConfigCommand;
+    u32 wlan0_id = if_nametoindex("wlan0");
+    if (!handle || !wlan0_id) {
+        ALOGE("%s: Error wifi_handle NULL or wlan0 not present", __FUNCTION__);
+        return WIFI_ERROR_UNKNOWN;
+    }
+
+    ALOGD("%s: ifname=%s create", __FUNCTION__, ifname);
+    // Do not create interface if already exist.
+    if (if_nametoindex(ifname))
+        return WIFI_SUCCESS;
+
+    wifiConfigCommand = new WiFiConfigCommand(handle, get_requestid(), 0, 0);
+    if (wifiConfigCommand == NULL) {
+        ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+        return WIFI_ERROR_UNKNOWN;
+    }
+
+    nl80211_iftype type;
+    switch(iface_type) {
+        case WIFI_INTERFACE_TYPE_STA:    /* IfaceType:STA */
+            type = NL80211_IFTYPE_STATION;
+            break;
+        case WIFI_INTERFACE_TYPE_AP:    /* IfaceType:AP */
+            type = NL80211_IFTYPE_AP;
+            break;
+        case WIFI_INTERFACE_TYPE_P2P:    /* IfaceType:P2P */
+            type = NL80211_IFTYPE_P2P_DEVICE;
+            break;
+        case WIFI_INTERFACE_TYPE_NAN:    /* IfaceType:NAN */
+            type = NL80211_IFTYPE_NAN;
+            break;
+        default:
+            ALOGE("%s: Wrong interface type %u", __FUNCTION__, iface_type);
+            ret = WIFI_ERROR_UNKNOWN;
+            goto done;
+            break;
+    }
+    wifiConfigCommand->create_generic(NL80211_CMD_NEW_INTERFACE);
+    wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX, wlan0_id);
+    wifiConfigCommand->put_string(NL80211_ATTR_IFNAME, ifname);
+    wifiConfigCommand->put_u32(NL80211_ATTR_IFTYPE, type);
+    /* Send the NL msg. */
+    wifiConfigCommand->waitForRsp(false);
+    ret = wifiConfigCommand->requestEvent();
+        if (ret != WIFI_SUCCESS) {
+            ALOGE("%s: requestEvent Error:%d", __FUNCTION__,ret);
+    }
+    // Update dynamic interface list
+    added_ifaces.push_back(std::string(ifname));
+
+done:
+    delete wifiConfigCommand;
+    return ret;
+}
+
+wifi_error wifi_virtual_interface_delete(wifi_handle handle,
+                                         const char* ifname)
+{
+    wifi_error ret;
+    WiFiConfigCommand *wifiConfigCommand;
+    u32 wlan0_id = if_nametoindex("wlan0");
+
+    if (!handle || !wlan0_id) {
+        ALOGE("%s: Error wifi_handle NULL or wlan0 not present", __FUNCTION__);
+        return WIFI_ERROR_UNKNOWN;
+    }
+
+    ALOGD("%s: ifname=%s delete", __FUNCTION__, ifname);
+    if (if_nametoindex(ifname) && !is_dynamic_interface(ifname)) {
+         // Do not remove interface if it was not added dynamically.
+         return WIFI_SUCCESS;
+    }
+    wifiConfigCommand = new WiFiConfigCommand(handle, get_requestid(), 0, 0);
+    if (wifiConfigCommand == NULL) {
+        ALOGE("%s: Error wifiConfigCommand NULL", __FUNCTION__);
+        return WIFI_ERROR_UNKNOWN;
+    }
+    wifiConfigCommand->create_generic(NL80211_CMD_DEL_INTERFACE);
+    wifiConfigCommand->put_u32(NL80211_ATTR_IFINDEX, if_nametoindex(ifname));
+    /* Send the NL msg. */
+    wifiConfigCommand->waitForRsp(false);
+    ret = wifiConfigCommand->requestEvent();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s: requestEvent Error:%d", __FUNCTION__,ret);
+    }
+    // Update dynamic interface list
+    added_ifaces.erase(std::remove(added_ifaces.begin(), added_ifaces.end(), std::string(ifname)),
+                           added_ifaces.end());
+
+    delete wifiConfigCommand;
+    return ret;
+}