Merge "NNAPI Burst object cleanup -- VTS update"
diff --git a/atrace/1.0/default/AtraceDevice.cpp b/atrace/1.0/default/AtraceDevice.cpp
index 43bcd9a..35d11e9 100644
--- a/atrace/1.0/default/AtraceDevice.cpp
+++ b/atrace/1.0/default/AtraceDevice.cpp
@@ -30,24 +30,25 @@
 
 struct TracingConfig {
     std::string description;
+    // path and if error on failure
     std::vector<std::pair<std::string, bool>> paths;
 };
 
 // This is a map stores categories and their sysfs paths with required flags
 const std::map<std::string, TracingConfig> kTracingMap = {
-    // gfx
-    {
-        "gfx",
-        {"Graphics",
-         {{"/sys/kernel/debug/tracing/events/mdss/enable", false},
-          {"/sys/kernel/debug/tracing/events/sde/enable", false},
-          {"/sys/kernel/debug/tracing/events/mali_systrace/enable", false}}},
-    },
-    {
-        "ion",
-        {"ION allocation",
-         {{"/sys/kernel/debug/tracing/events/kmem/ion_alloc_buffer_start/enable", true}}},
-    },
+        // gfx
+        {
+                "gfx",
+                {"Graphics",
+                 {{"/sys/kernel/debug/tracing/events/mdss/enable", false},
+                  {"/sys/kernel/debug/tracing/events/sde/enable", false},
+                  {"/sys/kernel/debug/tracing/events/mali_systrace/enable", false}}},
+        },
+        {
+                "ion",
+                {"ION allocation",
+                 {{"/sys/kernel/debug/tracing/events/kmem/ion_alloc_buffer_start/enable", false}}},
+        },
 };
 
 // Methods from ::android::hardware::atrace::V1_0::IAtraceDevice follow.
diff --git a/current.txt b/current.txt
index 96c1bbf..458e360 100644
--- a/current.txt
+++ b/current.txt
@@ -396,6 +396,8 @@
 d702fb01dc2a0733aa820b7eb65435ee3334f75632ef880bafd2fb8803a20a58 android.hardware.gnss@1.0::IGnssMeasurementCallback
 7c7721c0f773fcf422b71a4f558545e9e36acc973e58ca51e5bd53905cf46bc0 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer
 d4fea995378bb4f421b4e24ccf68cad2734ab07fe4f874a126ba558b99df5766 android.hardware.graphics.composer@2.1::IComposerClient
+f7d7cb747dc01a9fdb2d39a80003b4d8df9be733d65f5842198802eb6209db69 android.hardware.graphics.mapper@2.0::IMapper
+65a021fa89085b62fc96b2b6d3bef2f9103cf4d63379c68bc154fd9eef672852 android.hardware.health@1.0::types
 b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice
 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel
 417ab60fe1ef786778047e4486f3d868ebce570d91addd8fe4251515213072de android.hardware.neuralnetworks@1.0::types
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
index 3a73f84..1df496c 100644
--- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
@@ -170,7 +170,7 @@
     }
 
     Error lookupCache(uint32_t slot, const native_handle_t** outHandle) {
-        if (slot < mHandles.size()) {
+        if (slot >= 0 && slot < mHandles.size()) {
             *outHandle = mHandles[slot];
             return Error::NONE;
         } else {
@@ -180,7 +180,7 @@
 
     Error updateCache(uint32_t slot, const native_handle_t* handle,
                       const native_handle** outReplacedHandle) {
-        if (slot < mHandles.size()) {
+        if (slot >= 0 && slot < mHandles.size()) {
             auto& cachedHandle = mHandles[slot];
             *outReplacedHandle = cachedHandle;
             cachedHandle = handle;
diff --git a/graphics/mapper/2.0/IMapper.hal b/graphics/mapper/2.0/IMapper.hal
index 4566135..0e18f42 100644
--- a/graphics/mapper/2.0/IMapper.hal
+++ b/graphics/mapper/2.0/IMapper.hal
@@ -147,6 +147,9 @@
      * outside of accessRegion is undefined, except that it must not cause
      * process termination.
      *
+     * An accessRegion of all-zeros means the entire buffer. That is, it is
+     * equivalent to '(0,0)-(buffer width, buffer height)'.
+     *
      * data will be filled with a pointer to the locked buffer memory. This
      * address will represent the top-left corner of the entire buffer, even
      * if accessRegion does not begin at the top-left corner.
diff --git a/health/1.0/types.hal b/health/1.0/types.hal
index 377d1bd..90b8bb1 100644
--- a/health/1.0/types.hal
+++ b/health/1.0/types.hal
@@ -190,7 +190,13 @@
     /** Remaining battery capacity in percent */
     int32_t batteryLevel;
 
-    /** Instantaneous battery voltage in uV */
+    /**
+     * Instantaneous battery voltage in millivolts (mV).
+     *
+     * Historically, the unit of this field is microvolts (uV), but all
+     * clients and implementations uses millivolts in practice, making it
+     * the de-facto standard.
+     */
     int32_t batteryVoltage;
 
     /** Instantaneous battery temperature in tenths of degree celcius */
diff --git a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h
index 65fd115..53fa8d6 100644
--- a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h
+++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h
@@ -43,6 +43,12 @@
                  const std::string& iface_name));
     MOCK_METHOD1(getDriverVersion, std::pair<wifi_error, std::string>(
                  const std::string& iface_name));
+
+    MOCK_METHOD2(selectTxPowerScenario,
+                 wifi_error(const std::string& iface_name,
+                            wifi_power_scenario scenario));
+    MOCK_METHOD1(resetTxPowerScenario,
+                 wifi_error(const std::string& iface_name));
     MOCK_METHOD2(nanRegisterCallbackHandlers,
                  wifi_error(const std::string&, const NanCallbackHandlers&));
     MOCK_METHOD2(nanDisableRequest,
diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
index 134563c..7928328 100644
--- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
@@ -122,7 +122,7 @@
     void setup_MultiIfaceCombination() {
         // clang-format off
         const hidl_vec<V1_0::IWifiChip::ChipIfaceCombination> combinations = {
-            {{{{IfaceType::STA}, 3}}}
+            {{{{IfaceType::STA}, 3}, {{IfaceType::AP}, 1}}}
         };
         const std::vector<V1_0::IWifiChip::ChipMode> modes = {
             {feature_flags::chip_mode_ids::kV3, combinations}
@@ -261,6 +261,17 @@
         return success;
     }
 
+    sp<WifiChip> chip_;
+    ChipId chip_id_ = kFakeChipId;
+    std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
+        new NiceMock<legacy_hal::MockWifiLegacyHal>};
+    std::shared_ptr<NiceMock<mode_controller::MockWifiModeController>>
+        mode_controller_{new NiceMock<mode_controller::MockWifiModeController>};
+    std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
+        new NiceMock<iface_util::MockWifiIfaceUtil>};
+    std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>>
+        feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>};
+
    public:
     void SetUp() override {
         chip_ = new WifiChip(chip_id_, legacy_hal_, mode_controller_,
@@ -272,17 +283,12 @@
             .WillRepeatedly(testing::Return(legacy_hal::WIFI_SUCCESS));
     }
 
-   private:
-    sp<WifiChip> chip_;
-    ChipId chip_id_ = kFakeChipId;
-    std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
-        new NiceMock<legacy_hal::MockWifiLegacyHal>};
-    std::shared_ptr<NiceMock<mode_controller::MockWifiModeController>>
-        mode_controller_{new NiceMock<mode_controller::MockWifiModeController>};
-    std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
-        new NiceMock<iface_util::MockWifiIfaceUtil>};
-    std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>>
-        feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>};
+    void TearDown() override {
+        // Restore default system iface names (This should ideally be using a
+        // mock).
+        property_set("wifi.interface", "wlan0");
+        property_set("wifi.concurrent.interface", "wlan1");
+    }
 };
 
 ////////// V1 Iface Combinations ////////////
@@ -300,7 +306,7 @@
 
 TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
-    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
 }
 
 TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) {
@@ -326,7 +332,7 @@
 
 TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::AP);
-    ASSERT_FALSE(createIface(IfaceType::AP).empty());
+    ASSERT_EQ(createIface(IfaceType::AP), "wlan0");
 }
 
 TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateSta_ShouldFail) {
@@ -359,7 +365,7 @@
 
 TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
-    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
 }
 
 TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) {
@@ -427,7 +433,7 @@
 
 TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::AP);
-    ASSERT_FALSE(createIface(IfaceType::AP).empty());
+    ASSERT_EQ(createIface(IfaceType::AP), "wlan0");
 }
 
 TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateSta_ShouldFail) {
@@ -445,18 +451,18 @@
     ASSERT_TRUE(createIface(IfaceType::NAN).empty());
 }
 
-TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowStaModeNoSta) {
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowStaModeNoSta) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_TRUE(createRttController());
 }
 
-TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowStaModeWithSta) {
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowStaModeWithSta) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_FALSE(createIface(IfaceType::STA).empty());
     ASSERT_TRUE(createRttController());
 }
 
-TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowApToSta) {
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowApToSta) {
     findModeAndConfigureForIfaceType(IfaceType::AP);
     const auto ap_iface_name = createIface(IfaceType::AP);
     ASSERT_FALSE(ap_iface_name.empty());
@@ -468,6 +474,30 @@
     ASSERT_TRUE(createRttController());
 }
 
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, SelectTxScenarioWithOnlySta) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+    EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
+        .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+    chip_->selectTxPowerScenario_1_2(
+        V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
+        [](const WifiStatus& status) {
+            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+        });
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_EQ(createIface(IfaceType::AP), "wlan0");
+    EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
+        .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+    chip_->selectTxPowerScenario_1_2(
+        V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
+        [](const WifiStatus& status) {
+            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+        });
+}
+
 ////////// V2 + Aware Iface Combinations ////////////
 // Mode 1 - STA + STA/AP
 //        - STA + P2P/NAN
@@ -483,7 +513,7 @@
 
 TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateSta_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
-    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
 }
 
 TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateP2p_ShouldSucceed) {
@@ -498,19 +528,25 @@
 
 TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateAp_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::STA);
-    ASSERT_FALSE(createIface(IfaceType::AP).empty());
+    ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
 }
 
 TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaSta_ShouldFail) {
     findModeAndConfigureForIfaceType(IfaceType::AP);
-    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
     ASSERT_TRUE(createIface(IfaceType::STA).empty());
 }
 
 TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaAp_ShouldSucceed) {
     findModeAndConfigureForIfaceType(IfaceType::AP);
-    ASSERT_FALSE(createIface(IfaceType::AP).empty());
-    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+    ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApSta_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
 }
 
 TEST_F(WifiChipV2_AwareIfaceCombinationTest,
@@ -640,6 +676,30 @@
     ASSERT_TRUE(createRttController());
 }
 
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlySta) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+    EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
+        .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+    chip_->selectTxPowerScenario_1_2(
+        V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
+        [](const WifiStatus& status) {
+            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+        });
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
+    EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan1", testing::_))
+        .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+    chip_->selectTxPowerScenario_1_2(
+        V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
+        [](const WifiStatus& status) {
+            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+        });
+}
+
 ////////// V1 Iface Combinations when AP creation is disabled //////////
 class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
    public:
@@ -707,8 +767,8 @@
     property_set("wifi.interface", "bad0");
     property_set("wifi.concurrent.interface", "bad1");
     findModeAndConfigureForIfaceType(IfaceType::STA);
-    ASSERT_EQ(createIface(IfaceType::STA), "test0");
-    ASSERT_EQ(createIface(IfaceType::STA), "test1");
+    ASSERT_EQ(createIface(IfaceType::STA), "bad0");
+    ASSERT_EQ(createIface(IfaceType::STA), "bad1");
     ASSERT_EQ(createIface(IfaceType::STA), "test2");
 }
 
@@ -724,6 +784,16 @@
     ASSERT_EQ(createIface(IfaceType::STA), "wlan2");
 }
 
+TEST_F(WifiChip_MultiIfaceTest, CreateApStartsWithIdx1) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    // First AP will be slotted to wlan1.
+    ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
+    // First STA will be slotted to wlan0.
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+    // All further STA will be slotted to the remaining free indices.
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan2");
+    ASSERT_EQ(createIface(IfaceType::STA), "wlan3");
+}
 }  // namespace implementation
 }  // namespace V1_3
 }  // namespace wifi
diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp
index 3697d50..957b22b 100644
--- a/wifi/1.3/default/wifi_chip.cpp
+++ b/wifi/1.3/default/wifi_chip.cpp
@@ -641,7 +641,7 @@
     legacy_hal::wifi_error legacy_status;
     uint32_t legacy_feature_set;
     uint32_t legacy_logger_feature_set;
-    const auto ifname = getWlanIfaceName(0);
+    const auto ifname = getFirstActiveWlanIfaceName();
     std::tie(legacy_status, legacy_feature_set) =
         legacy_hal_.lock()->getSupportedFeatureSet(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
@@ -709,7 +709,7 @@
     IWifiChip::ChipDebugInfo result;
     legacy_hal::wifi_error legacy_status;
     std::string driver_desc;
-    const auto ifname = getWlanIfaceName(0);
+    const auto ifname = getFirstActiveWlanIfaceName();
     std::tie(legacy_status, driver_desc) =
         legacy_hal_.lock()->getDriverVersion(ifname);
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
@@ -741,7 +741,8 @@
     legacy_hal::wifi_error legacy_status;
     std::vector<uint8_t> driver_dump;
     std::tie(legacy_status, driver_dump) =
-        legacy_hal_.lock()->requestDriverMemoryDump(getWlanIfaceName(0));
+        legacy_hal_.lock()->requestDriverMemoryDump(
+            getFirstActiveWlanIfaceName());
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get driver debug dump: "
                    << legacyErrorToString(legacy_status);
@@ -756,7 +757,8 @@
     legacy_hal::wifi_error legacy_status;
     std::vector<uint8_t> firmware_dump;
     std::tie(legacy_status, firmware_dump) =
-        legacy_hal_.lock()->requestFirmwareMemoryDump(getWlanIfaceName(0));
+        legacy_hal_.lock()->requestFirmwareMemoryDump(
+            getFirstActiveWlanIfaceName());
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         LOG(ERROR) << "Failed to get firmware debug dump: "
                    << legacyErrorToString(legacy_status);
@@ -766,10 +768,10 @@
 }
 
 std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
-    if (!canCurrentModeSupportIfaceOfType(IfaceType::AP)) {
+    if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
-    std::string ifname = allocateApOrStaIfaceName();
+    std::string ifname = allocateApIfaceName();
     sp<WifiApIface> iface =
         new WifiApIface(ifname, legacy_hal_, iface_util_, feature_flags_);
     ap_ifaces_.push_back(iface);
@@ -813,11 +815,11 @@
 }
 
 std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::createNanIfaceInternal() {
-    if (!canCurrentModeSupportIfaceOfType(IfaceType::NAN)) {
+    if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::NAN)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
     // These are still assumed to be based on wlan0.
-    std::string ifname = getWlanIfaceName(0);
+    std::string ifname = getFirstActiveWlanIfaceName();
     sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_);
     nan_ifaces_.push_back(iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -860,7 +862,7 @@
 }
 
 std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::createP2pIfaceInternal() {
-    if (!canCurrentModeSupportIfaceOfType(IfaceType::P2P)) {
+    if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::P2P)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
     std::string ifname = getP2pIfaceName();
@@ -906,10 +908,10 @@
 }
 
 std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() {
-    if (!canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
+    if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::STA)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
-    std::string ifname = allocateApOrStaIfaceName();
+    std::string ifname = allocateStaIfaceName();
     sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_, iface_util_);
     sta_ifaces_.push_back(iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -959,8 +961,8 @@
                       "(and RTT by extension)";
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
-    sp<WifiRttController> rtt =
-        new WifiRttController(getWlanIfaceName(0), bound_iface, legacy_hal_);
+    sp<WifiRttController> rtt = new WifiRttController(
+        getFirstActiveWlanIfaceName(), bound_iface, legacy_hal_);
     rtt_controllers_.emplace_back(rtt);
     return {createWifiStatus(WifiStatusCode::SUCCESS), rtt};
 }
@@ -971,7 +973,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(getWlanIfaceName(0));
+        legacy_hal_.lock()->getRingBuffersStatus(getFirstActiveWlanIfaceName());
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
@@ -993,7 +995,7 @@
     }
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->startRingBufferLogging(
-            getWlanIfaceName(0), ring_name,
+            getFirstActiveWlanIfaceName(), ring_name,
             static_cast<
                 std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(
                 verbose_level),
@@ -1010,7 +1012,8 @@
         return status;
     }
     legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->getRingBufferData(getWlanIfaceName(0), ring_name);
+        legacy_hal_.lock()->getRingBufferData(getFirstActiveWlanIfaceName(),
+                                              ring_name);
 
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1026,7 +1029,7 @@
 WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() {
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->deregisterRingBufferCallbackHandler(
-            getWlanIfaceName(0));
+            getFirstActiveWlanIfaceName());
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
@@ -1035,7 +1038,7 @@
     legacy_hal::wifi_error legacy_status;
     legacy_hal::WakeReasonStats legacy_stats;
     std::tie(legacy_status, legacy_stats) =
-        legacy_hal_.lock()->getWakeReasonStats(getWlanIfaceName(0));
+        legacy_hal_.lock()->getWakeReasonStats(getFirstActiveWlanIfaceName());
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
@@ -1067,10 +1070,10 @@
             }
         };
         legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
-            getWlanIfaceName(0), on_alert_callback);
+            getFirstActiveWlanIfaceName(), on_alert_callback);
     } else {
         legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler(
-            getWlanIfaceName(0));
+            getFirstActiveWlanIfaceName());
     }
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1078,20 +1081,20 @@
 WifiStatus WifiChip::selectTxPowerScenarioInternal(
     V1_1::IWifiChip::TxPowerScenario scenario) {
     auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
-        getWlanIfaceName(0),
+        getFirstActiveWlanIfaceName(),
         hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario));
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiChip::resetTxPowerScenarioInternal() {
     auto legacy_status =
-        legacy_hal_.lock()->resetTxPowerScenario(getWlanIfaceName(0));
+        legacy_hal_.lock()->resetTxPowerScenario(getFirstActiveWlanIfaceName());
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
 WifiStatus WifiChip::setLatencyModeInternal(LatencyMode mode) {
     auto legacy_status = legacy_hal_.lock()->setLatencyMode(
-        getWlanIfaceName(0),
+        getFirstActiveWlanIfaceName(),
         hidl_struct_util::convertHidlLatencyModeToLegacy(mode));
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1107,7 +1110,7 @@
 WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(
     TxPowerScenario scenario) {
     auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
-        getWlanIfaceName(0),
+        getFirstActiveWlanIfaceName(),
         hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario));
     return createWifiStatusFromLegacyError(legacy_status);
 }
@@ -1197,7 +1200,7 @@
         };
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->registerRingBufferCallbackHandler(
-            getWlanIfaceName(0), on_ring_buffer_data_callback);
+            getFirstActiveWlanIfaceName(), on_ring_buffer_data_callback);
 
     if (legacy_status == legacy_hal::WIFI_SUCCESS) {
         debug_ring_buffer_cb_registered_ = true;
@@ -1231,7 +1234,7 @@
         };
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->registerRadioModeChangeCallbackHandler(
-            getWlanIfaceName(0), on_radio_mode_change_callback);
+            getFirstActiveWlanIfaceName(), on_radio_mode_change_callback);
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
@@ -1298,8 +1301,9 @@
     return expanded_combos;
 }
 
-bool WifiChip::canExpandedIfaceCombinationSupportIfaceOfType(
-    const std::map<IfaceType, size_t>& combo, IfaceType requested_type) {
+bool WifiChip::canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces(
+    const std::map<IfaceType, size_t>& expanded_combo,
+    IfaceType requested_type) {
     const auto current_combo = getCurrentIfaceCombination();
 
     // Check if we have space for 1 more iface of |type| in this combo
@@ -1309,7 +1313,7 @@
         if (type == requested_type) {
             num_ifaces_needed++;
         }
-        size_t num_ifaces_allowed = combo.at(type);
+        size_t num_ifaces_allowed = expanded_combo.at(type);
         if (num_ifaces_needed > num_ifaces_allowed) {
             return false;
         }
@@ -1320,8 +1324,10 @@
 // This method does the following:
 // a) Enumerate all possible iface combos by expanding the current
 //    ChipIfaceCombination.
-// b) Check if the requested iface type can be added to the current mode.
-bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType type) {
+// b) Check if the requested iface type can be added to the current mode
+//    with the iface combination that is already active.
+bool WifiChip::canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(
+    IfaceType requested_type) {
     if (!isValidModeId(current_mode_id_)) {
         LOG(ERROR) << "Chip not configured in a mode yet";
         return false;
@@ -1330,8 +1336,8 @@
     for (const auto& combination : combinations) {
         const auto expanded_combos = expandIfaceCombinations(combination);
         for (const auto& expanded_combo : expanded_combos) {
-            if (canExpandedIfaceCombinationSupportIfaceOfType(expanded_combo,
-                                                              type)) {
+            if (canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces(
+                    expanded_combo, requested_type)) {
                 return true;
             }
         }
@@ -1339,6 +1345,62 @@
     return false;
 }
 
+// Note: This does not consider ifaces already active. It only checks if the
+// provided expanded iface combination can support the requested combo.
+bool WifiChip::canExpandedIfaceComboSupportIfaceCombo(
+    const std::map<IfaceType, size_t>& expanded_combo,
+    const std::map<IfaceType, size_t>& req_combo) {
+    // Check if we have space for 1 more iface of |type| in this combo
+    for (const auto type :
+         {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
+        if (req_combo.count(type) == 0) {
+            // Iface of "type" not in the req_combo.
+            continue;
+        }
+        size_t num_ifaces_needed = req_combo.at(type);
+        size_t num_ifaces_allowed = expanded_combo.at(type);
+        if (num_ifaces_needed > num_ifaces_allowed) {
+            return false;
+        }
+    }
+    return true;
+}
+// This method does the following:
+// a) Enumerate all possible iface combos by expanding the current
+//    ChipIfaceCombination.
+// b) Check if the requested iface combo can be added to the current mode.
+// Note: This does not consider ifaces already active. It only checks if the
+// current mode can support the requested combo.
+bool WifiChip::canCurrentModeSupportIfaceCombo(
+    const std::map<IfaceType, size_t>& req_combo) {
+    if (!isValidModeId(current_mode_id_)) {
+        LOG(ERROR) << "Chip not configured in a mode yet";
+        return false;
+    }
+    const auto combinations = getCurrentModeIfaceCombinations();
+    for (const auto& combination : combinations) {
+        const auto expanded_combos = expandIfaceCombinations(combination);
+        for (const auto& expanded_combo : expanded_combos) {
+            if (canExpandedIfaceComboSupportIfaceCombo(expanded_combo,
+                                                       req_combo)) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+// This method does the following:
+// a) Enumerate all possible iface combos by expanding the current
+//    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.
+    std::map<IfaceType, size_t> req_iface_combo;
+    req_iface_combo[requested_type] = 1;
+    return canCurrentModeSupportIfaceCombo(req_iface_combo);
+}
+
 bool WifiChip::isValidModeId(ChipModeId mode_id) {
     for (const auto& mode : modes_) {
         if (mode.id == mode_id) {
@@ -1348,11 +1410,32 @@
     return false;
 }
 
-// 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() {
-    for (unsigned i = 0; i < kMaxWlanIfaces; i++) {
-        const auto ifname = getWlanIfaceName(i);
+bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() {
+    // Check if we can support atleast 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);
+}
+
+std::string WifiChip::getFirstActiveWlanIfaceName() {
+    for (unsigned idx = 0; idx < kMaxWlanIfaces; idx++) {
+        const auto ifname = getWlanIfaceName(idx);
+        if (findUsingName(sta_ifaces_, ifname)) return ifname;
+        if (findUsingName(ap_ifaces_, ifname)) return ifname;
+    }
+    // This could happen if the chip call is made before any STA/AP
+    // iface is created. Default to wlan0 for such cases.
+    LOG(WARNING) << "No active wlan interfaces in use!";
+    return getWlanIfaceName(0);
+}
+
+// Return the first wlan (wlan0, wlan1 etc.) starting from |start_idx|
+// not already in use.
+// Note: This doesn't check the actual presence of these interfaces.
+std::string WifiChip::allocateApOrStaIfaceName(uint32_t start_idx) {
+    for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) {
+        const auto ifname = getWlanIfaceName(idx);
         if (findUsingName(ap_ifaces_, ifname)) continue;
         if (findUsingName(sta_ifaces_, ifname)) continue;
         return ifname;
@@ -1362,6 +1445,19 @@
     return {};
 }
 
+// AP iface names start with idx 1 for modes supporting
+// concurrent STA, else start with idx 0.
+std::string WifiChip::allocateApIfaceName() {
+    return allocateApOrStaIfaceName(
+        isStaApConcurrencyAllowedInCurrentMode() ? 1 : 0);
+}
+
+// STA iface names start with idx 0.
+// Primary STA iface will always be 0.
+std::string WifiChip::allocateStaIfaceName() {
+    return allocateApOrStaIfaceName(0);
+}
+
 bool WifiChip::writeRingbufferFilesInternal() {
     if (!removeOldFilesInternal()) {
         LOG(ERROR) << "Error occurred while deleting old tombstone files";
diff --git a/wifi/1.3/default/wifi_chip.h b/wifi/1.3/default/wifi_chip.h
index 3eb0aee..3d12f4c 100644
--- a/wifi/1.3/default/wifi_chip.h
+++ b/wifi/1.3/default/wifi_chip.h
@@ -224,11 +224,23 @@
     std::map<IfaceType, size_t> getCurrentIfaceCombination();
     std::vector<std::map<IfaceType, size_t>> expandIfaceCombinations(
         const IWifiChip::ChipIfaceCombination& combination);
-    bool canExpandedIfaceCombinationSupportIfaceOfType(
-        const std::map<IfaceType, size_t>& combo, IfaceType type);
-    bool canCurrentModeSupportIfaceOfType(IfaceType type);
+    bool canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces(
+        const std::map<IfaceType, size_t>& expanded_combo,
+        IfaceType requested_type);
+    bool canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(
+        IfaceType requested_type);
+    bool canExpandedIfaceComboSupportIfaceCombo(
+        const std::map<IfaceType, size_t>& expanded_combo,
+        const std::map<IfaceType, size_t>& req_combo);
+    bool canCurrentModeSupportIfaceCombo(
+        const std::map<IfaceType, size_t>& req_combo);
+    bool canCurrentModeSupportIfaceOfType(IfaceType requested_type);
     bool isValidModeId(ChipModeId mode_id);
-    std::string allocateApOrStaIfaceName();
+    bool isStaApConcurrencyAllowedInCurrentMode();
+    std::string getFirstActiveWlanIfaceName();
+    std::string allocateApOrStaIfaceName(uint32_t start_idx);
+    std::string allocateApIfaceName();
+    std::string allocateStaIfaceName();
     bool writeRingbufferFilesInternal();
 
     ChipId chip_id_;
diff --git a/wifi/1.3/default/wifi_legacy_hal.h b/wifi/1.3/default/wifi_legacy_hal.h
index 4d6beb3..5df9487 100644
--- a/wifi/1.3/default/wifi_legacy_hal.h
+++ b/wifi/1.3/default/wifi_legacy_hal.h
@@ -254,9 +254,9 @@
                                           uint32_t cmd_id);
     wifi_error setScanningMacOui(const std::string& iface_name,
                                  const std::array<uint8_t, 3>& oui);
-    wifi_error selectTxPowerScenario(const std::string& iface_name,
-                                     wifi_power_scenario scenario);
-    wifi_error resetTxPowerScenario(const std::string& iface_name);
+    virtual wifi_error selectTxPowerScenario(const std::string& iface_name,
+                                             wifi_power_scenario scenario);
+    virtual wifi_error resetTxPowerScenario(const std::string& iface_name);
     wifi_error setLatencyMode(const std::string& iface_name,
                               wifi_latency_mode mode);
     // Logger/debug functions.