wifi(implementation): Allow chip reconfiguration

This was previously disallowed because WifiLegacyHal.stop() was non blocking.
WifiLegacyHal.stop() was made blocking using ag/2715673, so reconfiguration
should be supportable now.
Note: This is a partial revert of ag/2125543.

Bug: 65671875
Bug: 70411703
Test: Will send for regression tests.
Test: Reverted the VTS CL: ag/2139830 and ensured that the test works
now. Can't check-in that revert because it would not be backward
compatible.
Change-Id: Ia5f9ccaf5403d171b0def7740d2adece7eb3c157
diff --git a/wifi/1.2/default/wifi_chip.cpp b/wifi/1.2/default/wifi_chip.cpp
index 79fdfdc..4e2191d 100644
--- a/wifi/1.2/default/wifi_chip.cpp
+++ b/wifi/1.2/default/wifi_chip.cpp
@@ -71,6 +71,7 @@
 namespace V1_2 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
+using hidl_return_util::validateAndCallWithLock;
 
 WifiChip::WifiChip(
     ChipId chip_id, const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
@@ -121,9 +122,9 @@
 
 Return<void> WifiChip::configureChip(ChipModeId mode_id,
                                      configureChip_cb hidl_status_cb) {
-    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                           &WifiChip::configureChipInternal, hidl_status_cb,
-                           mode_id);
+    return validateAndCallWithLock(
+        this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+        &WifiChip::configureChipInternal, hidl_status_cb, mode_id);
 }
 
 Return<void> WifiChip::getMode(getMode_cb hidl_status_cb) {
@@ -397,7 +398,9 @@
             {sta_chip_mode, ap_chip_mode}};
 }
 
-WifiStatus WifiChip::configureChipInternal(ChipModeId mode_id) {
+WifiStatus WifiChip::configureChipInternal(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
+    ChipModeId mode_id) {
     if (mode_id != kStaChipModeId && mode_id != kApChipModeId) {
         return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
     }
@@ -405,7 +408,7 @@
         LOG(DEBUG) << "Already in the specified mode " << mode_id;
         return createWifiStatus(WifiStatusCode::SUCCESS);
     }
-    WifiStatus status = handleChipConfiguration(mode_id);
+    WifiStatus status = handleChipConfiguration(lock, mode_id);
     if (status.code != WifiStatusCode::SUCCESS) {
         for (const auto& callback : event_cb_handler_.getCallbacks()) {
             if (!callback->onChipReconfigureFailure(status).isOk()) {
@@ -421,6 +424,7 @@
         }
     }
     current_mode_id_ = mode_id;
+    LOG(INFO) << "Configured chip in mode " << mode_id;
     return status;
 }
 
@@ -792,15 +796,22 @@
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
-WifiStatus WifiChip::handleChipConfiguration(ChipModeId mode_id) {
+WifiStatus WifiChip::handleChipConfiguration(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
+    ChipModeId mode_id) {
     // If the chip is already configured in a different mode, stop
     // the legacy HAL and then start it after firmware mode change.
-    // Currently the underlying implementation has a deadlock issue.
-    // We should return ERROR_NOT_SUPPORTED if chip is already configured in
-    // a different mode.
     if (current_mode_id_ != kInvalidModeId) {
-        // TODO(b/37446050): Fix the deadlock.
-        return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+        LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_
+                  << " to mode " << mode_id;
+        invalidateAndRemoveAllIfaces();
+        legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->stop(lock, []() {});
+        if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+            LOG(ERROR) << "Failed to stop legacy HAL: "
+                       << legacyErrorToString(legacy_status);
+            return createWifiStatusFromLegacyError(legacy_status);
+        }
     }
     bool success;
     if (mode_id == kStaChipModeId) {
diff --git a/wifi/1.2/default/wifi_chip.h b/wifi/1.2/default/wifi_chip.h
index 8cb15bb..ac59d59 100644
--- a/wifi/1.2/default/wifi_chip.h
+++ b/wifi/1.2/default/wifi_chip.h
@@ -141,7 +141,8 @@
         const sp<IWifiChipEventCallback>& event_callback);
     std::pair<WifiStatus, uint32_t> getCapabilitiesInternal();
     std::pair<WifiStatus, std::vector<ChipMode>> getAvailableModesInternal();
-    WifiStatus configureChipInternal(ChipModeId mode_id);
+    WifiStatus configureChipInternal(
+        std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
     std::pair<WifiStatus, uint32_t> getModeInternal();
     std::pair<WifiStatus, IWifiChip::ChipDebugInfo>
     requestChipDebugInfoInternal();
@@ -185,7 +186,8 @@
     WifiStatus selectTxPowerScenarioInternal(TxPowerScenario scenario);
     WifiStatus resetTxPowerScenarioInternal();
 
-    WifiStatus handleChipConfiguration(ChipModeId mode_id);
+    WifiStatus handleChipConfiguration(
+        std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
     WifiStatus registerDebugRingBufferCallback();
 
     ChipId chip_id_;