Pass sink metadata to Bluetooth

When just microphone is enabled, i.e. for recording audio, we will
receive just sink metadata update.

Bug: 150670922
Change-Id: I795385d19e64ec5c6bc0a8549beda52da27d25a1
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index 19d2d92..4f712bf 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -22,6 +22,7 @@
     export_include_dirs: ["session/"],
     header_libs: ["libhardware_headers"],
     shared_libs: [
+        "android.hardware.audio.common@5.0",
         "android.hardware.bluetooth.audio@2.0",
         "android.hardware.bluetooth.audio@2.1",
         "android.hardware.bluetooth.audio@2.2",
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
index e20914e..b4ba8cf 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
@@ -132,6 +132,15 @@
     }
   }
 
+  static void UpdateSinkMetadata(const SessionType_2_1& session_type,
+                                 const struct sink_metadata* sink_metadata) {
+    std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
+        BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->UpdateSinkMetadata(sink_metadata);
+    }
+  }
+
   // The control API writes stream to FMQ
   static size_t OutWritePcmData(const SessionType_2_1& session_type,
                                 const void* buffer, size_t bytes) {
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
index 5a6b2e7..80df5d9 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
@@ -20,10 +20,16 @@
 
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
+#include <android/hardware/bluetooth/audio/2.2/IBluetoothAudioPort.h>
 
 namespace android {
 namespace bluetooth {
 namespace audio {
+
+using ::android::hardware::audio::common::V5_0::AudioSource;
+using ::android::hardware::audio::common::V5_0::RecordTrackMetadata;
+using ::android::hardware::audio::common::V5_0::SinkMetadata;
+
 using SessionType_2_1 =
     ::android::hardware::bluetooth::audio::V2_1::SessionType;
 using SessionType_2_0 =
@@ -37,6 +43,9 @@
 ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
     BluetoothAudioSession_2_2::invalidOffloadAudioConfiguration = {};
 
+using IBluetoothAudioPort_2_2 =
+    ::android::hardware::bluetooth::audio::V2_2::IBluetoothAudioPort;
+
 namespace {
 bool is_2_0_session_type(
     const ::android::hardware::bluetooth::audio::V2_1::SessionType&
@@ -84,6 +93,54 @@
   return audio_session_2_1;
 }
 
+void BluetoothAudioSession_2_2::UpdateSinkMetadata(
+    const struct sink_metadata* sink_metadata) {
+  std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+               << " has NO session";
+    return;
+  }
+
+  ssize_t track_count = sink_metadata->track_count;
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+            << ", " << track_count << " track(s)";
+  if (session_type_2_1_ == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+      session_type_2_1_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+    return;
+  }
+
+  struct record_track_metadata* track = sink_metadata->tracks;
+  SinkMetadata sinkMetadata;
+  RecordTrackMetadata* halMetadata;
+
+  sinkMetadata.tracks.resize(track_count);
+  halMetadata = sinkMetadata.tracks.data();
+  while (track_count && track) {
+    halMetadata->source = static_cast<AudioSource>(track->source);
+    halMetadata->gain = track->gain;
+    // halMetadata->destination leave unspecified
+    LOG(INFO) << __func__
+              << " - SessionType=" << toString(GetAudioSession()->session_type_)
+              << ", source=" << track->source
+              << ", dest_device=" << track->dest_device
+              << ", gain=" << track->gain
+              << ", dest_device_address=" << track->dest_device_address;
+    --track_count;
+    ++track;
+    ++halMetadata;
+  }
+
+  /* This is called just for 2.2 sessions, so it's safe to do this casting*/
+  IBluetoothAudioPort_2_2* stack_iface_2_2_ =
+      static_cast<IBluetoothAudioPort_2_2*>(audio_session->stack_iface_.get());
+  auto hal_retval = stack_iface_2_2_->updateSinkMetadata(sinkMetadata);
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_2_1_) << " failed";
+  }
+}
+
 // The control function is for the bluetooth_audio module to get the current
 // AudioConfiguration
 const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
index 7213ede..d6ae3d7 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
@@ -74,6 +74,8 @@
   const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
   GetAudioConfig();
 
+  void UpdateSinkMetadata(const struct sink_metadata* sink_metadata);
+
   static constexpr ::android::hardware::bluetooth::audio::V2_2::
       AudioConfiguration& kInvalidSoftwareAudioConfiguration =
           invalidSoftwareAudioConfiguration;