1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <iomanip> 20 #include <sstream> 21 #include <vector> 22 23 #include "a2dp_codec_api.h" 24 #include "a2dp_constants.h" 25 #include "avdt_api.h" 26 #include "common/message_loop_thread.h" 27 #include "hardware/bt_av.h" 28 29 namespace bluetooth { 30 namespace audio { 31 namespace a2dp { 32 33 /// Loosely copied after the definition from the Bluetooth Audio interface: 34 /// audio/aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.aidl 35 enum class Status { 36 SUCCESS = 0, 37 UNKNOWN, 38 UNSUPPORTED_CODEC_CONFIGURATION, 39 FAILURE, 40 PENDING, 41 }; 42 43 /// Loosely copied after the definition from the Bluetooth Audio interface: 44 /// audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl 45 /// 46 /// Implements callbacks for the BT Audio HAL to start, suspend and configure 47 /// the audio stream. Completion of the requested operation is indicated 48 /// by the methods ack_stream_started, ack_stream_suspended. 49 /// 50 /// The callbacks are always invoked from one of the binder threads. 51 class StreamCallbacks { 52 public: ~StreamCallbacks()53 virtual ~StreamCallbacks() {} StartStream(bool)54 virtual Status StartStream(bool /*low_latency*/) const { return Status::FAILURE; } SuspendStream()55 virtual Status SuspendStream() const { return Status::FAILURE; } StopStream()56 virtual Status StopStream() const { return SuspendStream(); } SetLatencyMode(bool)57 virtual Status SetLatencyMode(bool /*low_latency*/) const { return Status::FAILURE; } 58 }; 59 60 bool update_codec_offloading_capabilities( 61 const std::vector<btav_a2dp_codec_config_t>& framework_preference, 62 bool supports_a2dp_hw_offload_v2); 63 64 // Check if new bluetooth_audio is enabled 65 bool is_hal_enabled(); 66 67 // Check if new bluetooth_audio is running with offloading encoders 68 bool is_hal_offloading(); 69 70 // Initialize BluetoothAudio HAL: openProvider 71 bool init(bluetooth::common::MessageLoopThread* message_loop, 72 StreamCallbacks const* strean_callbacks, bool offload_enabled); 73 74 // Clean up BluetoothAudio HAL 75 void cleanup(); 76 77 // Set up the codec into BluetoothAudio HAL 78 bool setup_codec(A2dpCodecConfig* a2dp_config, uint16_t peer_mtu, 79 int preferred_encoding_interval_us); 80 81 // Set low latency buffer mode allowed or disallowed 82 void set_audio_low_latency_mode_allowed(bool allowed); 83 84 // Send command to the BluetoothAudio HAL: StartSession, EndSession, 85 // StreamStarted, StreamSuspended 86 void start_session(); 87 void end_session(); 88 void ack_stream_started(Status status); 89 void ack_stream_suspended(Status status); 90 91 // Read from the FMQ of BluetoothAudio HAL 92 size_t read(uint8_t* p_buf, uint32_t len); 93 94 // Update A2DP delay report to BluetoothAudio HAL 95 void set_remote_delay(uint16_t delay_report); 96 97 // Check whether OPUS is supported 98 bool is_opus_supported(); 99 100 // Definitions for A2DP hardware offload codec extensibility. 101 namespace provider { 102 103 // Lookup the codec info in the list of supported offloaded sink codecs. 104 std::optional<btav_a2dp_codec_index_t> sink_codec_index(const uint8_t* p_codec_info); 105 106 // Lookup the codec info in the list of supported offloaded source codecs. 107 std::optional<btav_a2dp_codec_index_t> source_codec_index(const uint8_t* p_codec_info); 108 109 // Return the name of the codec which is assigned to the input index. 110 // The codec index must be in the ranges 111 // BTAV_A2DP_CODEC_INDEX_SINK_EXT_MIN..BTAV_A2DP_CODEC_INDEX_SINK_EXT_MAX or 112 // BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MIN..BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MAX. 113 // Returns nullopt if the codec_index is not assigned or codec extensibility 114 // is not supported or enabled. 115 std::optional<const char*> codec_index_str(btav_a2dp_codec_index_t codec_index); 116 117 // Return true if the codec is supported for the session type 118 // A2DP_HARDWARE_ENCODING_DATAPATH or A2DP_HARDWARE_DECODING_DATAPATH. 119 bool supports_codec(btav_a2dp_codec_index_t codec_index); 120 121 // Return the A2DP capabilities for the selected codec. 122 // `codec_info` returns the OTA codec capabilities, `codec_config` 123 // returns the supported capabilities in a generic format. 124 bool codec_info(btav_a2dp_codec_index_t codec_index, bluetooth::a2dp::CodecId* codec_id, 125 uint8_t* codec_info, btav_a2dp_codec_config_t* codec_config); 126 127 struct a2dp_configuration { 128 int remote_seid; 129 uint8_t codec_config[AVDT_CODEC_SIZE]; 130 btav_a2dp_codec_config_t codec_parameters; 131 std::vector<uint8_t> vendor_specific_parameters; 132 toStringa2dp_configuration133 inline std::string toString() const { 134 std::ostringstream os; 135 os << "A2dpConfiguration{"; 136 os << "remote_seid: " << remote_seid; 137 os << ", codec_index: " << codec_parameters.codec_type; 138 os << ", codec_config: {"; 139 for (int i = 0; i < AVDT_CODEC_SIZE; i++) { 140 os << "0x" << std::hex << std::setw(2) << std::setfill('0') 141 << static_cast<int>(codec_config[i]); 142 if (i != AVDT_CODEC_SIZE - 1) { 143 os << ","; 144 } 145 } 146 os << "}"; 147 os << "}"; 148 return os.str(); 149 } 150 }; 151 152 struct a2dp_remote_capabilities { 153 int seid; 154 uint8_t const* capabilities; 155 toStringa2dp_remote_capabilities156 inline std::string toString() const { 157 std::ostringstream os; 158 os << "A2dpRemoteCapabilities{"; 159 os << "seid: " << seid; 160 os << ", capabilities: {"; 161 if (capabilities != nullptr) { 162 for (int i = 0; i < AVDT_CODEC_SIZE; i++) { 163 os << "0x" << std::hex << std::setw(2) << std::setfill('0') 164 << static_cast<int>(capabilities[i]); 165 if (i != AVDT_CODEC_SIZE - 1) { 166 os << ","; 167 } 168 } 169 } 170 os << "}"; 171 os << "}"; 172 return os.str(); 173 } 174 }; 175 176 // Query the codec selection fromt the audio HAL. 177 // The HAL is expected to pick the best audio configuration based on the 178 // discovered remote SEPs. 179 std::optional<a2dp_configuration> get_a2dp_configuration( 180 RawAddress peer_address, std::vector<a2dp_remote_capabilities> const& remote_seps, 181 btav_a2dp_codec_config_t const& user_preferences); 182 183 // Query the codec parameters from the audio HAL. 184 // The HAL is expected to parse the codec configuration 185 // received from the peer and decide whether accept 186 // the it or not. 187 tA2DP_STATUS parse_a2dp_configuration(btav_a2dp_codec_index_t codec_index, 188 const uint8_t* codec_info, 189 btav_a2dp_codec_config_t* codec_parameters, 190 std::vector<uint8_t>* vendor_specific_parameters); 191 192 } // namespace provider 193 } // namespace a2dp 194 } // namespace audio 195 } // namespace bluetooth 196 197 namespace std { 198 template <> 199 struct formatter<::bluetooth::audio::a2dp::Status> 200 : enum_formatter<::bluetooth::audio::a2dp::Status> {}; 201 } // namespace std 202