wifi: Add AP interface idx mechanism & predefine interface support.

SAP Interface idx mechanism.
STA+STA support, AP+AP will use wlan2 & wlan3, single AP use wlan2
STA+STA doesn't support, AP+AP use wlan1 & wlan 2, single AP use
wlan 1
STA+AP doesn't support, AP + AP will take wlan0 & wlan 1 but single AP
use wlan0 (Ideally it should not happen)

Add predefine interface support for bridged AP interface.
(property: ro.vendor.sap.concurrent.interface)

PS: Rename: getApIfaceName to getPredefinedApIfaceName since it
duplicates public HAL API: getApIfaceName

AP+AP Part 4 includes:
1. Support API to indicate Bridged AP supported or not
2. SAP Interface idx mechanism.

Bug: 162686273
Bug: 173999527
Test: atest -c VtsHalWifiApV1_0TargetTest
Test: atest -c VtsHalWifiApV1_4TargetTest
Test: atest -c VtsHalWifiApV1_5TargetTest
Change-Id: I115e294ac2be201cfa3a58cfa0a8a98b481b29de
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 5d9d315..dd39551 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -103,24 +103,36 @@
     return "wlan" + std::to_string(idx);
 }
 
-// Returns the dedicated iface name if one is defined.
-std::string getApIfaceName() {
+// Returns the dedicated iface name if defined.
+// Returns two ifaces in bridged mode.
+std::vector<std::string> getPredefinedApIfaceNames(bool is_bridged) {
+    std::vector<std::string> ifnames;
     std::array<char, PROPERTY_VALUE_MAX> buffer;
+    buffer.fill(0);
     if (property_get("ro.vendor.wifi.sap.interface", buffer.data(), nullptr) ==
         0) {
-        return {};
+        return ifnames;
     }
-    return buffer.data();
+    ifnames.push_back(buffer.data());
+    if (is_bridged) {
+        buffer.fill(0);
+        if (property_get("ro.vendor.wifi.sap.concurrent.interface",
+                         buffer.data(), nullptr) == 0) {
+            return ifnames;
+        }
+        ifnames.push_back(buffer.data());
+    }
+    return ifnames;
 }
 
-std::string getP2pIfaceName() {
+std::string getPredefinedP2pIfaceName() {
     std::array<char, PROPERTY_VALUE_MAX> buffer;
     property_get("wifi.direct.interface", buffer.data(), "p2p0");
     return buffer.data();
 }
 
 // Returns the dedicated iface name if one is defined.
-std::string getNanIfaceName() {
+std::string getPredefinedNanIfaceName() {
     std::array<char, PROPERTY_VALUE_MAX> buffer;
     if (property_get("wifi.aware.interface", buffer.data(), nullptr) == 0) {
         return {};
@@ -931,22 +943,22 @@
     if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
-    std::string br_ifname = kApBridgeIfacePrefix + allocateApIfaceName();
-    std::vector<std::string> ap_instances;
+    std::vector<std::string> ap_instances = allocateBridgedApInstanceNames();
+    if (ap_instances.size() < 2) {
+        LOG(ERROR) << "Fail to allocate two instances";
+        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+    }
+    std::string br_ifname = kApBridgeIfacePrefix + ap_instances[0];
     for (int i = 0; i < 2; i++) {
-        // TODO: b/173999527, it should use idx from 2 when STA+STA support, but
-        // need to check vendor support or not.
-        std::string ifaceInstanceName = allocateApOrStaIfaceName(
-            IfaceType::AP, isStaApConcurrencyAllowedInCurrentMode() ? 1 : 0);
-        WifiStatus status = createVirtualApInterface(ifaceInstanceName);
+        WifiStatus status = createVirtualApInterface(ap_instances[i]);
         if (status.code != WifiStatusCode::SUCCESS) {
-            if (ap_instances.size() != 0) {
+            if (i != 0) {  // The failure happened when creating second virtual
+                           // iface.
                 legacy_hal_.lock()->deleteVirtualInterface(
-                    ap_instances.front());
+                    ap_instances.front());  // Remove the first virtual iface.
             }
             return {status, {}};
         }
-        ap_instances.push_back(ifaceInstanceName);
     }
     br_ifaces_ap_instances_[br_ifname] = ap_instances;
     if (!iface_util_.lock()->createBridge(br_ifname)) {
@@ -1048,7 +1060,7 @@
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
     bool is_dedicated_iface = true;
-    std::string ifname = getNanIfaceName();
+    std::string ifname = getPredefinedNanIfaceName();
     if (ifname.empty() || !iface_util_.lock()->ifNameToIndex(ifname)) {
         // Use the first shared STA iface (wlan0) if a dedicated aware iface is
         // not defined.
@@ -1101,7 +1113,7 @@
     if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::P2P)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
-    std::string ifname = getP2pIfaceName();
+    std::string ifname = getPredefinedP2pIfaceName();
     sp<WifiP2pIface> iface = new WifiP2pIface(ifname, legacy_hal_);
     p2p_ifaces_.push_back(iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -1720,7 +1732,7 @@
 //    ChipIfaceCombination.
 // b) Check if the requested iface type can be added to the current mode.
 bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType requested_type) {
-    // Check if we can support atleast 1 iface of type.
+    // Check if we can support at least 1 iface of type.
     std::map<IfaceType, size_t> req_iface_combo;
     req_iface_combo[requested_type] = 1;
     return canCurrentModeSupportIfaceCombo(req_iface_combo);
@@ -1736,17 +1748,17 @@
 }
 
 bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() {
-    // Check if we can support atleast 1 STA & 1 AP concurrently.
+    // Check if we can support at least 1 STA & 1 AP concurrently.
     std::map<IfaceType, size_t> req_iface_combo;
     req_iface_combo[IfaceType::AP] = 1;
     req_iface_combo[IfaceType::STA] = 1;
     return canCurrentModeSupportIfaceCombo(req_iface_combo);
 }
 
-bool WifiChip::isDualApAllowedInCurrentMode() {
-    // Check if we can support atleast 1 STA & 1 AP concurrently.
+bool WifiChip::isDualStaConcurrencyAllowedInCurrentMode() {
+    // Check if we can support at least 2 STA concurrently.
     std::map<IfaceType, size_t> req_iface_combo;
-    req_iface_combo[IfaceType::AP] = 2;
+    req_iface_combo[IfaceType::STA] = 2;
     return canCurrentModeSupportIfaceCombo(req_iface_combo);
 }
 
@@ -1776,19 +1788,46 @@
     return {};
 }
 
+uint32_t WifiChip::startIdxOfApIface() {
+    if (isDualStaConcurrencyAllowedInCurrentMode()) {
+        // When the HAL support dual STAs, AP should start with idx 2.
+        return 2;
+    } else if (isStaApConcurrencyAllowedInCurrentMode()) {
+        //  When the HAL support STA + AP but it doesn't support dual STAs.
+        //  AP should start with idx 1.
+        return 1;
+    }
+    // No concurrency support.
+    return 0;
+}
+
 // AP iface names start with idx 1 for modes supporting
 // concurrent STA and not dual AP, else start with idx 0.
 std::string WifiChip::allocateApIfaceName() {
     // Check if we have a dedicated iface for AP.
-    std::string ifname = getApIfaceName();
-    if (!ifname.empty()) {
-        return ifname;
+    std::vector<std::string> ifnames = getPredefinedApIfaceNames(false);
+    if (!ifnames.empty()) {
+        return ifnames[0];
     }
-    return allocateApOrStaIfaceName(IfaceType::AP,
-                                    (isStaApConcurrencyAllowedInCurrentMode() &&
-                                     !isDualApAllowedInCurrentMode())
-                                        ? 1
-                                        : 0);
+    return allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface());
+}
+
+std::vector<std::string> WifiChip::allocateBridgedApInstanceNames() {
+    // Check if we have a dedicated iface for AP.
+    std::vector<std::string> instances = getPredefinedApIfaceNames(true);
+    if (instances.size() == 2) {
+        return instances;
+    } else {
+        int num_ifaces_need_to_allocate = 2 - instances.size();
+        for (int i = 0; i < num_ifaces_need_to_allocate; i++) {
+            std::string instance_name =
+                allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface());
+            if (!instance_name.empty()) {
+                instances.push_back(instance_name);
+            }
+        }
+    }
+    return instances;
 }
 
 // STA iface names start with idx 0.
diff --git a/wifi/1.5/default/wifi_chip.h b/wifi/1.5/default/wifi_chip.h
index 70b221d..bff8d68 100644
--- a/wifi/1.5/default/wifi_chip.h
+++ b/wifi/1.5/default/wifi_chip.h
@@ -276,10 +276,12 @@
     bool canCurrentModeSupportIfaceOfType(IfaceType requested_type);
     bool isValidModeId(ChipModeId mode_id);
     bool isStaApConcurrencyAllowedInCurrentMode();
-    bool isDualApAllowedInCurrentMode();
+    bool isDualStaConcurrencyAllowedInCurrentMode();
+    uint32_t startIdxOfApIface();
     std::string getFirstActiveWlanIfaceName();
     std::string allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx);
     std::string allocateApIfaceName();
+    std::vector<std::string> allocateBridgedApInstanceNames();
     std::string allocateStaIfaceName();
     bool writeRingbufferFilesInternal();
     std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx);