WiFi: enable any combination of STA/AP/P2P/NAN interfaces.

The total number of interfaces is still limited to 2,
will be addressed in a separate change.

Bug: 36120314
Test: KitchenSink (see go/aae-dual-ap)
Test: b/120081854
Change-Id: I8962c5167fcbe55805fce320f639d37b4b902c5c
diff --git a/wifi/1.3/default/wifi_feature_flags.cpp b/wifi/1.3/default/wifi_feature_flags.cpp
index 8d48c36..17b3bee 100644
--- a/wifi/1.3/default/wifi_feature_flags.cpp
+++ b/wifi/1.3/default/wifi_feature_flags.cpp
@@ -16,25 +16,6 @@
 
 #include "wifi_feature_flags.h"
 
-namespace {
-#ifdef WIFI_HIDL_FEATURE_AWARE
-static const bool wifiHidlFeatureAware = true;
-#else
-static const bool wifiHidlFeatureAware = false;
-#endif  // WIFI_HIDL_FEATURE_AWARE
-#ifdef WIFI_HIDL_FEATURE_DUAL_INTERFACE
-static const bool wifiHidlFeatureDualInterface = true;
-#else
-static const bool wifiHidlFeatureDualInterface = false;
-#endif  // WIFI_HIDL_FEATURE_DUAL_INTERFACE
-#ifdef WIFI_HIDL_FEATURE_DISABLE_AP
-static const bool wifiHidlFeatureDisableAp = true;
-#else
-static const bool wifiHidlFeatureDisableAp = false;
-#endif  // WIFI_HIDL_FEATURE_DISABLE_AP
-
-}  // namespace
-
 namespace android {
 namespace hardware {
 namespace wifi {
@@ -42,12 +23,132 @@
 namespace implementation {
 namespace feature_flags {
 
+using V1_0::ChipModeId;
+using V1_0::IfaceType;
+using V1_0::IWifiChip;
+
+/* The chip may either have a single mode supporting any number of combinations,
+ * or a fixed dual-mode (so it involves firmware loading to switch between
+ * modes) setting. If there is a need to support more modes, it needs to be
+ * implemented manually in WiFi HAL (see changeFirmwareMode in
+ * WifiChip::handleChipConfiguration).
+ *
+ * Supported combinations are defined in device's makefile, for example:
+ *    WIFI_HAL_INTERFACE_COMBINATIONS := {{{STA, AP}, 1}, {{P2P, NAN}, 1}},
+ *    WIFI_HAL_INTERFACE_COMBINATIONS += {{{STA}, 1}, {{AP}, 2}}
+ * What means:
+ *    Interface combination 1: 1 STA or AP and 1 P2P or NAN concurrent iface
+ *                             operations.
+ *    Interface combination 2: 1 STA and 2 AP concurrent iface operations.
+ *
+ * For backward compatibility, the following makefile flags can be used to
+ * generate combinations list:
+ *  - WIFI_HIDL_FEATURE_DUAL_INTERFACE
+ *  - WIFI_HIDL_FEATURE_DISABLE_AP
+ *  - WIFI_HIDL_FEATURE_AWARE
+ * However, they are ignored if WIFI_HAL_INTERFACE_COMBINATIONS was provided.
+ * With WIFI_HIDL_FEATURE_DUAL_INTERFACE flag set, there is a single mode with
+ * two interface combinations:
+ *    Interface Combination 1: Will support 1 STA and 1 P2P or NAN (optional)
+ *                             concurrent iface operations.
+ *    Interface Combination 2: Will support 1 STA and 1 AP concurrent
+ *                             iface operations.
+ *
+ * The only dual-mode configuration supported is for alternating STA and AP
+ * mode, that may involve firmware reloading. In such case, there are 2 separate
+ * modes of operation with 1 interface combination each:
+ *    Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN (optional)
+ *                       concurrent iface operations.
+ *    Mode 2 (AP mode): Will support 1 AP iface operation.
+ *
+ * If Aware is enabled, the iface combination will be modified to support either
+ * P2P or NAN in place of just P2P.
+ */
+// clang-format off
+#ifdef WIFI_HAL_INTERFACE_COMBINATIONS
+constexpr ChipModeId kMainModeId = chip_mode_ids::kV3;
+#elif defined(WIFI_HIDL_FEATURE_DUAL_INTERFACE)
+// former V2 (fixed dual interface) setup expressed as V3
+constexpr ChipModeId kMainModeId = chip_mode_ids::kV3;
+#  ifdef WIFI_HIDL_FEATURE_DISABLE_AP
+#    ifdef WIFI_HIDL_FEATURE_AWARE
+//     1 STA + 1 of (P2P or NAN)
+#      define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P, NAN}, 1}}
+#    else
+//     1 STA + 1 P2P
+#      define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}}
+#    endif
+#  else
+#    ifdef WIFI_HIDL_FEATURE_AWARE
+//     (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN))
+#      define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+                                              {{{STA}, 1}, {{P2P, NAN}, 1}}
+#    else
+//     (1 STA + 1 AP) or (1 STA + 1 P2P)
+#      define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+                                              {{{STA}, 1}, {{P2P}, 1}}
+#    endif
+#  endif
+#else
+// V1 (fixed single interface, dual-mode chip)
+constexpr ChipModeId kMainModeId = chip_mode_ids::kV1Sta;
+#  ifdef WIFI_HIDL_FEATURE_AWARE
+//   1 STA + 1 of (P2P or NAN)
+#    define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P, NAN}, 1}}
+#  else
+//   1 STA + 1 P2P
+#    define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}}
+#  endif
+
+#  ifndef WIFI_HIDL_FEATURE_DISABLE_AP
+#    define WIFI_HAL_INTERFACE_COMBINATIONS_AP {{{AP}, 1}}
+#  endif
+#endif
+// clang-format on
+
+/**
+ * Helper class to convert a collection of combination limits to a combination.
+ *
+ * The main point here is to simplify the syntax required by
+ * WIFI_HAL_INTERFACE_COMBINATIONS.
+ */
+struct ChipIfaceCombination
+    : public hidl_vec<IWifiChip::ChipIfaceCombinationLimit> {
+    ChipIfaceCombination(
+        const std::initializer_list<IWifiChip::ChipIfaceCombinationLimit> list)
+        : hidl_vec(list) {}
+
+    operator IWifiChip::ChipIfaceCombination() const { return {*this}; }
+
+    static hidl_vec<IWifiChip::ChipIfaceCombination> make_vec(
+        const std::initializer_list<ChipIfaceCombination> list) {
+        return hidl_vec<IWifiChip::ChipIfaceCombination>(  //
+            std::begin(list), std::end(list));
+    }
+};
+
+#define STA IfaceType::STA
+#define AP IfaceType::AP
+#define P2P IfaceType::P2P
+#define NAN IfaceType::NAN
+static const std::vector<IWifiChip::ChipMode> kChipModes{
+    {kMainModeId,
+     ChipIfaceCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS})},
+#ifdef WIFI_HAL_INTERFACE_COMBINATIONS_AP
+    {chip_mode_ids::kV1Ap,
+     ChipIfaceCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS_AP})},
+#endif
+};
+#undef STA
+#undef AP
+#undef P2P
+#undef NAN
+
 WifiFeatureFlags::WifiFeatureFlags() {}
-bool WifiFeatureFlags::isAwareSupported() { return wifiHidlFeatureAware; }
-bool WifiFeatureFlags::isDualInterfaceSupported() {
-    return wifiHidlFeatureDualInterface;
+
+std::vector<IWifiChip::ChipMode> WifiFeatureFlags::getChipModes() {
+    return kChipModes;
 }
-bool WifiFeatureFlags::isApDisabled() { return wifiHidlFeatureDisableAp; }
 
 }  // namespace feature_flags
 }  // namespace implementation