AHAL: add API to notify the HAL module about disconnecting device.

When external device is about to disconnect, the audio framework will
notify the HAL module about the coming device disconnection so that the
HAL module could abort any active read/write operations on drivers to
avoid problems with the HW interfaces.

Bug: 279824103
Test: atest VtsHalAudioCoreModuleTargetTest
Change-Id: I9f960b8ae5df11a764e70bd63f98c0f8b8386c34
Merged-In: I9f960b8ae5df11a764e70bd63f98c0f8b8386c34
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 89e3d99..6c4d7ac 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -758,6 +758,28 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Module::prepareToDisconnectExternalDevice(int32_t in_portId) {
+    auto& ports = getConfig().ports;
+    auto portIt = findById<AudioPort>(ports, in_portId);
+    if (portIt == ports.end()) {
+        LOG(ERROR) << __func__ << ": port id " << in_portId << " not found";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    if (portIt->ext.getTag() != AudioPortExt::Tag::device) {
+        LOG(ERROR) << __func__ << ": port id " << in_portId << " is not a device port";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+    auto connectedPortsIt = mConnectedDevicePorts.find(in_portId);
+    if (connectedPortsIt == mConnectedDevicePorts.end()) {
+        LOG(ERROR) << __func__ << ": port id " << in_portId << " is not a connected device port";
+        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+    }
+
+    onPrepareToDisconnectExternalDevice(*portIt);
+
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus Module::getAudioPatches(std::vector<AudioPatch>* _aidl_return) {
     *_aidl_return = getConfig().patches;
     LOG(DEBUG) << __func__ << ": returning " << _aidl_return->size() << " patches";
@@ -1537,6 +1559,11 @@
     LOG(DEBUG) << __func__ << ": do nothing and return";
 }
 
+void Module::onPrepareToDisconnectExternalDevice(
+        const ::aidl::android::media::audio::common::AudioPort& audioPort __unused) {
+    LOG(DEBUG) << __func__ << ": do nothing and return";
+}
+
 ndk::ScopedAStatus Module::onMasterMuteChanged(bool mute __unused) {
     LOG(VERBOSE) << __func__ << ": do nothing and return ok";
     return ndk::ScopedAStatus::ok();
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index caf43f1..572b597 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -70,6 +70,7 @@
             const ::aidl::android::media::audio::common::AudioPort& in_templateIdAndAdditionalData,
             ::aidl::android::media::audio::common::AudioPort* _aidl_return) override;
     ndk::ScopedAStatus disconnectExternalDevice(int32_t in_portId) override;
+    ndk::ScopedAStatus prepareToDisconnectExternalDevice(int32_t in_portId) override;
     ndk::ScopedAStatus getAudioPatches(std::vector<AudioPatch>* _aidl_return) override;
     ndk::ScopedAStatus getAudioPort(
             int32_t in_portId,
@@ -195,6 +196,8 @@
             const std::vector<::aidl::android::media::audio::common::AudioPortConfig*>& sinks);
     virtual void onExternalDeviceConnectionChanged(
             const ::aidl::android::media::audio::common::AudioPort& audioPort, bool connected);
+    virtual void onPrepareToDisconnectExternalDevice(
+            const ::aidl::android::media::audio::common::AudioPort& audioPort);
     virtual ndk::ScopedAStatus onMasterMuteChanged(bool mute);
     virtual ndk::ScopedAStatus onMasterVolumeChanged(float volume);
     virtual std::vector<::aidl::android::media::audio::common::MicrophoneInfo> getMicrophoneInfos();