WiFi: support more wlan interfaces than 2

Bug: 36120314
Test: KitchenSink (see go/aae-dual-ap)
Test: ./runtests.sh
Change-Id: I57ec1d3faf78ffc14868a760995496b866b1171a
diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp
index dd6bd7c..b91a946 100644
--- a/wifi/1.3/default/wifi_chip.cpp
+++ b/wifi/1.3/default/wifi_chip.cpp
@@ -41,6 +41,7 @@
 constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60;
 constexpr uint32_t kMaxRingBufferFileNum = 20;
 constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/";
+constexpr unsigned kMaxWlanIfaces = 100;
 
 template <typename Iface>
 void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
@@ -78,16 +79,25 @@
     return nullptr;
 }
 
-std::string getWlan0IfaceName() {
-    std::array<char, PROPERTY_VALUE_MAX> buffer;
-    property_get("wifi.interface", buffer.data(), "wlan0");
-    return buffer.data();
-}
+std::string getWlanIfaceName(unsigned idx) {
+    if (idx >= kMaxWlanIfaces) {
+        CHECK(false) << "Requested interface beyond wlan" << kMaxWlanIfaces;
+        return {};
+    }
 
-std::string getWlan1IfaceName() {
     std::array<char, PROPERTY_VALUE_MAX> buffer;
-    property_get("wifi.concurrent.interface", buffer.data(), "wlan1");
-    return buffer.data();
+    std::string propName = "wifi.interface." + std::to_string(idx);
+    auto res = property_get(propName.c_str(), buffer.data(), nullptr);
+    if (res > 0) return buffer.data();
+
+    if (idx == 0 || idx == 1) {
+        const char* altPropName =
+            (idx == 0) ? "wifi.interface" : "wifi.concurrent.interface";
+        res = property_get(altPropName, buffer.data(), nullptr);
+        if (res > 0) return buffer.data();
+    }
+
+    return "wlan" + std::to_string(idx);
 }
 
 std::string getP2pIfaceName() {
@@ -629,13 +639,14 @@
     legacy_hal::wifi_error legacy_status;
     uint32_t legacy_feature_set;
     uint32_t legacy_logger_feature_set;
+    const auto ifname = getWlanIfaceName(0);
     std::tie(legacy_status, legacy_feature_set) =
-        legacy_hal_.lock()->getSupportedFeatureSet(getWlan0IfaceName());
+        legacy_hal_.lock()->getSupportedFeatureSet(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), 0};
     }
     std::tie(legacy_status, legacy_logger_feature_set) =
-        legacy_hal_.lock()->getLoggerSupportedFeatureSet(getWlan0IfaceName());
+        legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         // some devices don't support querying logger feature set
         legacy_logger_feature_set = 0;
@@ -696,8 +707,9 @@
     IWifiChip::ChipDebugInfo result;
     legacy_hal::wifi_error legacy_status;
     std::string driver_desc;
+    const auto ifname = getWlanIfaceName(0);
     std::tie(legacy_status, driver_desc) =
-        legacy_hal_.lock()->getDriverVersion(getWlan0IfaceName());
+        legacy_hal_.lock()->getDriverVersion(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get driver version: "
                    << legacyErrorToString(legacy_status);
@@ -709,7 +721,7 @@
 
     std::string firmware_desc;
     std::tie(legacy_status, firmware_desc) =
-        legacy_hal_.lock()->getFirmwareVersion(getWlan0IfaceName());
+        legacy_hal_.lock()->getFirmwareVersion(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get firmware version: "
                    << legacyErrorToString(legacy_status);
@@ -727,7 +739,7 @@
     legacy_hal::wifi_error legacy_status;
     std::vector<uint8_t> driver_dump;
     std::tie(legacy_status, driver_dump) =
-        legacy_hal_.lock()->requestDriverMemoryDump(getWlan0IfaceName());
+        legacy_hal_.lock()->requestDriverMemoryDump(getWlanIfaceName(0));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get driver debug dump: "
                    << legacyErrorToString(legacy_status);
@@ -742,7 +754,7 @@
     legacy_hal::wifi_error legacy_status;
     std::vector<uint8_t> firmware_dump;
     std::tie(legacy_status, firmware_dump) =
-        legacy_hal_.lock()->requestFirmwareMemoryDump(getWlan0IfaceName());
+        legacy_hal_.lock()->requestFirmwareMemoryDump(getWlanIfaceName(0));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get firmware debug dump: "
                    << legacyErrorToString(legacy_status);
@@ -802,7 +814,7 @@
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
     // These are still assumed to be based on wlan0.
-    std::string ifname = getWlan0IfaceName();
+    std::string ifname = getWlanIfaceName(0);
     sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_);
     nan_ifaces_.push_back(iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -945,7 +957,7 @@
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
     sp<WifiRttController> rtt =
-        new WifiRttController(getWlan0IfaceName(), bound_iface, legacy_hal_);
+        new WifiRttController(getWlanIfaceName(0), bound_iface, legacy_hal_);
     rtt_controllers_.emplace_back(rtt);
     return {createWifiStatus(WifiStatusCode::SUCCESS), rtt};
 }
@@ -956,7 +968,7 @@
     std::vector<legacy_hal::wifi_ring_buffer_status>
         legacy_ring_buffer_status_vec;
     std::tie(legacy_status, legacy_ring_buffer_status_vec) =
-        legacy_hal_.lock()->getRingBuffersStatus(getWlan0IfaceName());
+        legacy_hal_.lock()->getRingBuffersStatus(getWlanIfaceName(0));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
@@ -978,7 +990,7 @@
     }
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->startRingBufferLogging(
-            getWlan0IfaceName(), ring_name,
+            getWlanIfaceName(0), ring_name,
             static_cast<
                 std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(
                 verbose_level),
@@ -995,7 +1007,7 @@
         return status;
     }
     legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->getRingBufferData(getWlan0IfaceName(), ring_name);
+        legacy_hal_.lock()->getRingBufferData(getWlanIfaceName(0), ring_name);
 
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1003,7 +1015,7 @@
 WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() {
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->deregisterRingBufferCallbackHandler(
-            getWlan0IfaceName());
+            getWlanIfaceName(0));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
@@ -1012,7 +1024,7 @@
     legacy_hal::wifi_error legacy_status;
     legacy_hal::WakeReasonStats legacy_stats;
     std::tie(legacy_status, legacy_stats) =
-        legacy_hal_.lock()->getWakeReasonStats(getWlan0IfaceName());
+        legacy_hal_.lock()->getWakeReasonStats(getWlanIfaceName(0));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
@@ -1044,10 +1056,10 @@
             }
         };
         legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
-            getWlan0IfaceName(), on_alert_callback);
+            getWlanIfaceName(0), on_alert_callback);
     } else {
         legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler(
-            getWlan0IfaceName());
+            getWlanIfaceName(0));
     }
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1055,20 +1067,20 @@
 WifiStatus WifiChip::selectTxPowerScenarioInternal(
     V1_1::IWifiChip::TxPowerScenario scenario) {
     auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
-        getWlan0IfaceName(),
+        getWlanIfaceName(0),
         hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiChip::resetTxPowerScenarioInternal() {
     auto legacy_status =
-        legacy_hal_.lock()->resetTxPowerScenario(getWlan0IfaceName());
+        legacy_hal_.lock()->resetTxPowerScenario(getWlanIfaceName(0));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiChip::setLatencyModeInternal(LatencyMode mode) {
     auto legacy_status = legacy_hal_.lock()->setLatencyMode(
-        getWlan0IfaceName(),
+        getWlanIfaceName(0),
         hidl_struct_util::convertHidlLatencyModeToLegacy(mode));
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1084,7 +1096,7 @@
 WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(
     TxPowerScenario scenario) {
     auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
-        getWlan0IfaceName(),
+        getWlanIfaceName(0),
         hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario));
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1164,7 +1176,7 @@
         };
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->registerRingBufferCallbackHandler(
-            getWlan0IfaceName(), on_ring_buffer_data_callback);
+            getWlanIfaceName(0), on_ring_buffer_data_callback);
 
     if (legacy_status == legacy_hal::WIFI_SUCCESS) {
         debug_ring_buffer_cb_registered_ = true;
@@ -1198,7 +1210,7 @@
         };
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->registerRadioModeChangeCallbackHandler(
-            getWlan0IfaceName(), on_radio_mode_change_callback);
+            getWlanIfaceName(0), on_radio_mode_change_callback);
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
@@ -1315,22 +1327,17 @@
     return false;
 }
 
-// Return "wlan0", if "wlan0" is not already in use, else return "wlan1".
-// This is based on the assumption that we'll have a max of 2 concurrent
-// AP/STA ifaces.
+// Return the first wlan (wlan0, wlan1 etc.) not already in use.
+// This doesn't check the actual presence of these interfaces.
 std::string WifiChip::allocateApOrStaIfaceName() {
-    auto ap_iface = findUsingName(ap_ifaces_, getWlan0IfaceName());
-    auto sta_iface = findUsingName(sta_ifaces_, getWlan0IfaceName());
-    if (!ap_iface.get() && !sta_iface.get()) {
-        return getWlan0IfaceName();
-    }
-    ap_iface = findUsingName(ap_ifaces_, getWlan1IfaceName());
-    sta_iface = findUsingName(sta_ifaces_, getWlan1IfaceName());
-    if (!ap_iface.get() && !sta_iface.get()) {
-        return getWlan1IfaceName();
+    for (unsigned i = 0; i < kMaxWlanIfaces; i++) {
+        const auto ifname = getWlanIfaceName(i);
+        if (findUsingName(ap_ifaces_, ifname)) continue;
+        if (findUsingName(sta_ifaces_, ifname)) continue;
+        return ifname;
     }
     // This should never happen. We screwed up somewhere if it did.
-    CHECK(0) << "wlan0 and wlan1 in use already!";
+    CHECK(false) << "All wlan interfaces in use already!";
     return {};
 }