Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 840ecc1c authored by Bao Do's avatar Bao Do Committed by Gerrit Code Review
Browse files

Merge "HFP Audio client - header functions and client interface" into main

parents c723823c f4672191
Loading
Loading
Loading
Loading
+27 −9
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include "client_interface_aidl.h"

#include <android/binder_manager.h>
#include <android_bluetooth_flags.h>

namespace bluetooth {
namespace audio {
@@ -155,8 +156,8 @@ BluetoothAudioSinkClientInterface::BluetoothAudioSinkClientInterface(

BluetoothAudioSinkClientInterface::~BluetoothAudioSinkClientInterface() {
  if (provider_factory_ != nullptr) {
    AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(),
                           nullptr);
    AIBinder_unlinkToDeath(provider_factory_->asBinder().get(),
                           death_recipient_.get(), nullptr);
  }
}

@@ -169,8 +170,8 @@ BluetoothAudioSourceClientInterface::BluetoothAudioSourceClientInterface(

BluetoothAudioSourceClientInterface::~BluetoothAudioSourceClientInterface() {
  if (provider_factory_ != nullptr) {
    AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(),
                           nullptr);
    AIBinder_unlinkToDeath(provider_factory_->asBinder().get(),
                           death_recipient_.get(), nullptr);
  }
}

@@ -196,7 +197,12 @@ bool BluetoothAudioClientInterface::UpdateAudioConfig(
       transport_->GetSessionType() ==
           SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
       transport_->GetSessionType() ==
           SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
           SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
       (IS_FLAG_ENABLED(is_sco_managed_by_audio) &&
        (transport_->GetSessionType() ==
             SessionType::HFP_SOFTWARE_ENCODING_DATAPATH ||
         transport_->GetSessionType() ==
             SessionType::HFP_SOFTWARE_DECODING_DATAPATH)));
  bool is_a2dp_offload_session =
      (transport_->GetSessionType() ==
       SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
@@ -221,9 +227,15 @@ bool BluetoothAudioClientInterface::UpdateAudioConfig(
  bool is_leaudio_broadcast_offload_audio_config =
      (is_leaudio_broadcast_offload_session &&
       audio_config_tag == AudioConfiguration::leAudioBroadcastConfig);
  bool is_hfp_offload_audio_config =
      (IS_FLAG_ENABLED(is_sco_managed_by_audio) &&
       transport_->GetSessionType() ==
           SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH &&
       audio_config_tag == AudioConfiguration::hfpConfig);
  if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
      !is_leaudio_unicast_offload_audio_config &&
      !is_leaudio_broadcast_offload_audio_config) {
      !is_leaudio_broadcast_offload_audio_config &&
      !is_hfp_offload_audio_config) {
    return false;
  }
  transport_->UpdateAudioConfiguration(audio_config);
@@ -315,7 +327,10 @@ int BluetoothAudioClientInterface::StartSession() {
                 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
             transport_->GetSessionType() ==
                 SessionType::
                     LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
                     LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
             (IS_FLAG_ENABLED(is_sco_managed_by_audio) &&
              transport_->GetSessionType() ==
                  SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH)) {
    transport_->ResetPresentationPosition();
    session_started_ = true;
    return 0;
@@ -406,7 +421,10 @@ void BluetoothAudioClientInterface::FlushAudioData() {
      transport_->GetSessionType() ==
          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
      transport_->GetSessionType() ==
          SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
          SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
      (IS_FLAG_ENABLED(is_sco_managed_by_audio) &&
       transport_->GetSessionType() ==
           SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH)) {
    return;
  }

+166 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <cstdint>

#include "client_interface_aidl.h"
#include "common/message_loop_thread.h"

namespace bluetooth {
namespace audio {
namespace aidl {
namespace hfp {

using ::aidl::android::hardware::bluetooth::audio::LatencyMode;

typedef enum {
  HFP_CTRL_CMD_NONE,
  HFP_CTRL_CMD_CHECK_READY,
  HFP_CTRL_CMD_START,
  HFP_CTRL_CMD_STOP,
  HFP_CTRL_CMD_SUSPEND,
  HFP_CTRL_GET_INPUT_AUDIO_CONFIG,
  HFP_CTRL_GET_OUTPUT_AUDIO_CONFIG,
  HFP_CTRL_SET_OUTPUT_AUDIO_CONFIG,
  HFP_CTRL_GET_PRESENTATION_POSITION,
} tHFP_CTRL_CMD;

// Provide call-in APIs for the Bluetooth Audio HAL
class HfpTransport {
 public:
  HfpTransport();

  BluetoothAudioCtrlAck StartRequest();

  BluetoothAudioCtrlAck SuspendRequest();

  void StopRequest();

  void SetLatencyMode(LatencyMode latency_mode);

  bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
                               uint64_t* total_bytes_read,
                               timespec* data_position);

  void SourceMetadataChanged(const source_metadata_v7_t& source_metadata);

  void SinkMetadataChanged(const sink_metadata_v7_t&);

  void ResetPresentationPosition();

  uint8_t GetPendingCmd() const;

  void ResetPendingCmd();

  void LogBytesProcessed(size_t bytes_read);

 private:
  tHFP_CTRL_CMD hfp_pending_cmd_;
};

// Sink transport implementation
class HfpDecodingTransport
    : public ::bluetooth::audio::aidl::IBluetoothSinkTransportInstance {
 public:
  HfpDecodingTransport(SessionType sessionType);

  ~HfpDecodingTransport();

  BluetoothAudioCtrlAck StartRequest(bool is_low_latency);

  BluetoothAudioCtrlAck SuspendRequest();

  void StopRequest();

  void SetLatencyMode(LatencyMode latency_mode);

  bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
                               uint64_t* total_bytes_read,
                               timespec* data_position);

  void SourceMetadataChanged(const source_metadata_v7_t& source_metadata);

  void SinkMetadataChanged(const sink_metadata_v7_t& sink_metadata);

  void ResetPresentationPosition();

  void LogBytesRead(size_t bytes_read) override;

  uint8_t GetPendingCmd() const;

  void ResetPendingCmd();

  static inline HfpDecodingTransport* instance_ = nullptr;
  static inline BluetoothAudioSinkClientInterface* software_hal_interface =
      nullptr;
  static inline BluetoothAudioSinkClientInterface* offloading_hal_interface =
      nullptr;
  static inline BluetoothAudioSinkClientInterface* active_hal_interface =
      nullptr;

 private:
  HfpTransport* transport_;
};

class HfpEncodingTransport
    : public ::bluetooth::audio::aidl::IBluetoothSourceTransportInstance {
 public:
  HfpEncodingTransport(SessionType sessionType);

  ~HfpEncodingTransport();

  BluetoothAudioCtrlAck StartRequest(bool is_low_latency);

  BluetoothAudioCtrlAck SuspendRequest();

  void StopRequest();

  void SetLatencyMode(LatencyMode latency_mode);

  bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
                               uint64_t* total_bytes_read,
                               timespec* data_position);

  void SourceMetadataChanged(const source_metadata_v7_t& source_metadata);

  void SinkMetadataChanged(const sink_metadata_v7_t& sink_metadata);

  void ResetPresentationPosition();

  void LogBytesWritten(size_t bytes_written) override;

  uint8_t GetPendingCmd() const;

  void ResetPendingCmd();

  static inline HfpEncodingTransport* instance_ = nullptr;
  static inline BluetoothAudioSourceClientInterface* software_hal_interface =
      nullptr;
  static inline BluetoothAudioSourceClientInterface* offloading_hal_interface =
      nullptr;
  static inline BluetoothAudioSourceClientInterface* active_hal_interface =
      nullptr;

 private:
  HfpTransport* transport_;
};

}  // namespace hfp
}  // namespace aidl
}  // namespace audio
}  // namespace bluetooth
+84 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include "bta/ag/bta_ag_int.h"
#include "common/message_loop_thread.h"

namespace bluetooth {
namespace audio {
namespace hfp {

class HfpClientInterface {
 private:
  class IClientInterfaceEndpoint {
   public:
    virtual ~IClientInterfaceEndpoint() = default;
    virtual void Cleanup() = 0;
    virtual void StartSession() = 0;
    virtual void StopSession() = 0;
    virtual void UpdateAudioConfigToHal(
        const ::hfp::offload_config& config) = 0;
  };

 public:
  class Decode : public IClientInterfaceEndpoint {
   public:
    Decode(){};
    virtual ~Decode() = default;

    void Cleanup() override;
    void StartSession() override;
    void StopSession() override;
    void UpdateAudioConfigToHal(const ::hfp::offload_config& config) override;
    size_t Read(uint8_t* p_buf, uint32_t len);
  };

  class Encode : public IClientInterfaceEndpoint {
   public:
    virtual ~Encode() = default;

    void Cleanup() override;
    void StartSession() override;
    void StopSession() override;
    void UpdateAudioConfigToHal(const ::hfp::offload_config& config) override;
    size_t Write(const uint8_t* p_buf, uint32_t len);
  };

  // Get HFP sink client interface if it's not previously acquired and not
  // yet released.
  Decode* GetDecode(bluetooth::common::MessageLoopThread* message_loop);
  // Release sink interface if belongs to HFP client interface
  bool ReleaseDecode(Decode* sink);

  // Get HFP source client interface if it's not previously acquired and
  // not yet released.
  Encode* GetEncode(bluetooth::common::MessageLoopThread* message_loop);
  // Release source interface if belongs to HFP client interface
  bool ReleaseEncode(Encode* source);

  // Get interface, if previously not initialized - it'll initialize singleton.
  static HfpClientInterface* Get();

 private:
  static HfpClientInterface* interface;
  Decode* decode_ = nullptr;
  Encode* encode_ = nullptr;
};
}  // namespace hfp
}  // namespace audio
}  // namespace bluetooth
+11 −0
Original line number Diff line number Diff line
@@ -292,6 +292,17 @@ typedef uint16_t tBTA_AG_PEER_CODEC;
#define BTA_AG_AT_MAX_LEN 256
#endif

// Define hfp offload config structure
namespace hfp {

struct offload_config {
  tBTA_AG_PEER_CODEC sco_codec;
  int32_t connection_handle;
  bool is_controller_codec;
  bool is_nrec;
};

}  // namespace hfp
/* data associated with BTA_AG_IND_RES */
typedef struct {
  uint16_t id;