liyujie
2025-08-28 b3810562527858a3b3d98ffa6e9c9c5b0f4a9a8e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
 * Copyright 2019 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 <time.h>
#include <mutex>
 
#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvider.h>
#include <android/hardware/bluetooth/audio/2.0/types.h>
#include <fmq/MessageQueue.h>
#include <hardware/audio.h>
 
#include "common/message_loop_thread.h"
 
#define BLUETOOTH_AUDIO_HAL_PROP_DISABLED "persist.bluetooth.bluetooth_audio_hal.disabled"
 
namespace bluetooth {
namespace audio {
 
using ::android::hardware::bluetooth::audio::V2_0::AudioCapabilities;
using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
using ::android::hardware::bluetooth::audio::V2_0::CodecType;
using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioProvider;
using ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
using ::android::hardware::bluetooth::audio::V2_0::SampleRate;
using ::android::hardware::bluetooth::audio::V2_0::SessionType;
using ::android::hardware::bluetooth::audio::V2_0::TimeSpec;
using BluetoothAudioStatus =
    ::android::hardware::bluetooth::audio::V2_0::Status;
 
enum class BluetoothAudioCtrlAck : uint8_t {
  SUCCESS_FINISHED = 0,
  PENDING,
  FAILURE_UNSUPPORTED,
  FAILURE_BUSY,
  FAILURE_DISCONNECTING,
  FAILURE
};
 
std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& ack);
 
inline BluetoothAudioStatus BluetoothAudioCtrlAckToHalStatus(
    const BluetoothAudioCtrlAck& ack) {
  switch (ack) {
    case BluetoothAudioCtrlAck::SUCCESS_FINISHED:
      return BluetoothAudioStatus::SUCCESS;
    case BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED:
      return BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION;
    case BluetoothAudioCtrlAck::PENDING:
      return BluetoothAudioStatus::FAILURE;
    case BluetoothAudioCtrlAck::FAILURE_BUSY:
      return BluetoothAudioStatus::FAILURE;
    case BluetoothAudioCtrlAck::FAILURE_DISCONNECTING:
      return BluetoothAudioStatus::FAILURE;
    default:
      return BluetoothAudioStatus::FAILURE;
  }
}
 
// An IBluetoothTransportInstance needs to be implemented by a Bluetooth audio
// transport, such as A2DP or Hearing Aid, to handle callbacks from Audio HAL.
class IBluetoothTransportInstance {
 public:
  IBluetoothTransportInstance(SessionType sessionType,
                              AudioConfiguration audioConfig)
      : session_type_(sessionType), audio_config_(std::move(audioConfig)){};
  virtual ~IBluetoothTransportInstance() = default;
 
  SessionType GetSessionType() const { return session_type_; }
 
  AudioConfiguration GetAudioConfiguration() const { return audio_config_; }
 
  void UpdateAudioConfiguration(const AudioConfiguration& audio_config) {
    audio_config_ = audio_config;
  }
 
  virtual BluetoothAudioCtrlAck StartRequest() = 0;
 
  virtual BluetoothAudioCtrlAck SuspendRequest() = 0;
 
  virtual void StopRequest() = 0;
 
  virtual bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
                                       uint64_t* total_bytes_readed,
                                       timespec* data_position) = 0;
 
  virtual void MetadataChanged(const source_metadata_t& source_metadata) = 0;
 
  // Invoked when the transport is requested to reset presentation position
  virtual void ResetPresentationPosition() = 0;
 
  // Invoked when the transport is requested to log bytes read
  virtual void LogBytesRead(size_t bytes_readed) = 0;
 
 private:
  const SessionType session_type_;
  AudioConfiguration audio_config_;
};
 
// common object is shared between different kind of SessionType
class BluetoothAudioDeathRecipient;
 
// The client interface connects an IBluetoothTransportInstance to
// IBluetoothAudioProvider and helps to route callbacks to
// IBluetoothTransportInstance
class BluetoothAudioClientInterface {
 public:
  // Constructs an BluetoothAudioClientInterface to communicate to
  // BluetoothAudio HAL. |sink| is the implementation for the transport, and
  // |message_loop| is the thread where callbacks are invoked.
  BluetoothAudioClientInterface(
      IBluetoothTransportInstance* sink,
      bluetooth::common::MessageLoopThread* message_loop);
 
  ~BluetoothAudioClientInterface();
 
  bool IsValid() const {
    return provider_ != nullptr;
  }
 
  std::vector<AudioCapabilities> GetAudioCapabilities() const;
 
  bool UpdateAudioConfig(const AudioConfiguration& audioConfig);
 
  int StartSession();
 
  void StreamStarted(const BluetoothAudioCtrlAck& ack);
 
  void StreamSuspended(const BluetoothAudioCtrlAck& ack);
 
  int EndSession();
 
  // Read data from audio  HAL through fmq
  size_t ReadAudioData(uint8_t* p_buf, uint32_t len);
 
  // Write data to audio HAL through fmq
  size_t WriteAudioData(uint8_t* p_buf, uint32_t len);
 
  // Renew the connection and usually is used when HIDL restarted
  void RenewAudioProviderAndSession();
 
  static constexpr PcmParameters kInvalidPcmConfiguration = {
      .sampleRate = SampleRate::RATE_UNKNOWN,
      .bitsPerSample = BitsPerSample::BITS_UNKNOWN,
      .channelMode = ChannelMode::UNKNOWN};
 
 private:
  // Helper function to connect to an IBluetoothAudioProvider
  void fetch_audio_provider();
 
  mutable std::mutex internal_mutex_;
  IBluetoothTransportInstance* sink_;
  android::sp<IBluetoothAudioProvider> provider_;
  std::vector<AudioCapabilities> capabilities_;
  bool session_started_;
  std::unique_ptr<::android::hardware::MessageQueue<
      uint8_t, ::android::hardware::kSynchronizedReadWrite>>
      mDataMQ;
  android::sp<BluetoothAudioDeathRecipient> death_recipient_;
};
 
}  // namespace audio
}  // namespace bluetooth