| /* |
| * Copyright (C) 2012 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. |
| */ |
| |
| #ifndef ANDROID_INCLUDE_BT_AV_H |
| #define ANDROID_INCLUDE_BT_AV_H |
| |
| #include <hardware/bluetooth.h> |
| #include <raw_address.h> |
| |
| #include <optional> |
| #include <vector> |
| |
| __BEGIN_DECLS |
| |
| /* Bluetooth AV connection states */ |
| typedef enum { |
| BTAV_CONNECTION_STATE_DISCONNECTED = 0, |
| BTAV_CONNECTION_STATE_CONNECTING, |
| BTAV_CONNECTION_STATE_CONNECTED, |
| BTAV_CONNECTION_STATE_DISCONNECTING |
| } btav_connection_state_t; |
| |
| /* Bluetooth AV datapath states */ |
| typedef enum { |
| BTAV_AUDIO_STATE_REMOTE_SUSPEND = 0, |
| BTAV_AUDIO_STATE_STOPPED, |
| BTAV_AUDIO_STATE_STARTED, |
| } btav_audio_state_t; |
| |
| /* |
| * Enum values for each A2DP supported codec. |
| * There should be a separate entry for each A2DP codec that is supported |
| * for encoding (SRC), and for decoding purpose (SINK). |
| */ |
| typedef enum { |
| BTAV_A2DP_CODEC_INDEX_SOURCE_MIN = 0, |
| |
| // Add an entry for each source codec here. |
| // NOTE: The values should be same as those listed in the following file: |
| // BluetoothCodecConfig.java |
| BTAV_A2DP_CODEC_INDEX_SOURCE_SBC = 0, |
| BTAV_A2DP_CODEC_INDEX_SOURCE_AAC, |
| BTAV_A2DP_CODEC_INDEX_SOURCE_APTX, |
| BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD, |
| BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC, |
| BTAV_A2DP_CODEC_INDEX_SOURCE_LC3, |
| BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS, |
| |
| BTAV_A2DP_CODEC_INDEX_SOURCE_MAX, |
| |
| BTAV_A2DP_CODEC_INDEX_SINK_MIN = BTAV_A2DP_CODEC_INDEX_SOURCE_MAX, |
| |
| // Add an entry for each sink codec here |
| BTAV_A2DP_CODEC_INDEX_SINK_SBC = BTAV_A2DP_CODEC_INDEX_SINK_MIN, |
| BTAV_A2DP_CODEC_INDEX_SINK_AAC, |
| BTAV_A2DP_CODEC_INDEX_SINK_LDAC, |
| BTAV_A2DP_CODEC_INDEX_SINK_OPUS, |
| |
| BTAV_A2DP_CODEC_INDEX_SINK_MAX, |
| |
| BTAV_A2DP_CODEC_INDEX_MIN = BTAV_A2DP_CODEC_INDEX_SOURCE_MIN, |
| BTAV_A2DP_CODEC_INDEX_MAX = BTAV_A2DP_CODEC_INDEX_SINK_MAX |
| } btav_a2dp_codec_index_t; |
| |
| typedef enum { |
| // Disable the codec. |
| // NOTE: This value can be used only during initialization when |
| // function btav_source_interface_t::init() is called. |
| BTAV_A2DP_CODEC_PRIORITY_DISABLED = -1, |
| |
| // Reset the codec priority to its default value. |
| BTAV_A2DP_CODEC_PRIORITY_DEFAULT = 0, |
| |
| // Highest codec priority. |
| BTAV_A2DP_CODEC_PRIORITY_HIGHEST = 1000 * 1000 |
| } btav_a2dp_codec_priority_t; |
| |
| typedef enum { |
| BTAV_A2DP_CODEC_SAMPLE_RATE_NONE = 0x0, |
| BTAV_A2DP_CODEC_SAMPLE_RATE_44100 = 0x1 << 0, |
| BTAV_A2DP_CODEC_SAMPLE_RATE_48000 = 0x1 << 1, |
| BTAV_A2DP_CODEC_SAMPLE_RATE_88200 = 0x1 << 2, |
| BTAV_A2DP_CODEC_SAMPLE_RATE_96000 = 0x1 << 3, |
| BTAV_A2DP_CODEC_SAMPLE_RATE_176400 = 0x1 << 4, |
| BTAV_A2DP_CODEC_SAMPLE_RATE_192000 = 0x1 << 5, |
| BTAV_A2DP_CODEC_SAMPLE_RATE_16000 = 0x1 << 6, |
| BTAV_A2DP_CODEC_SAMPLE_RATE_24000 = 0x1 << 7 |
| } btav_a2dp_codec_sample_rate_t; |
| |
| typedef enum { |
| BTAV_A2DP_CODEC_FRAME_SIZE_NONE = 0x0, |
| BTAV_A2DP_CODEC_FRAME_SIZE_20MS = 0x1 << 0, |
| BTAV_A2DP_CODEC_FRAME_SIZE_15MS = 0x1 << 1, |
| BTAV_A2DP_CODEC_FRAME_SIZE_10MS = 0x1 << 2, |
| BTAV_A2DP_CODEC_FRAME_SIZE_75MS = 0x1 << 3, |
| } btav_a2dp_codec_frame_size_t; |
| |
| typedef enum { |
| BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE = 0x0, |
| BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 = 0x1 << 0, |
| BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24 = 0x1 << 1, |
| BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32 = 0x1 << 2 |
| } btav_a2dp_codec_bits_per_sample_t; |
| |
| typedef enum { |
| BTAV_A2DP_CODEC_CHANNEL_MODE_NONE = 0x0, |
| BTAV_A2DP_CODEC_CHANNEL_MODE_MONO = 0x1 << 0, |
| BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO = 0x1 << 1 |
| } btav_a2dp_codec_channel_mode_t; |
| |
| typedef enum { |
| BTAV_A2DP_SCMST_DISABLED = 0x00, |
| BTAV_A2DP_SCMST_ENABLED = 0x01 |
| } btav_a2dp_scmst_enable_status_t; |
| |
| /* |
| * Structure for representing codec capability or configuration. |
| * It is used for configuring A2DP codec preference, and for reporting back |
| * current configuration or codec capability. |
| * For codec capability, fields "sample_rate", "bits_per_sample" and |
| * "channel_mode" can contain bit-masks with all supported features. |
| */ |
| struct btav_a2dp_codec_config_t { |
| btav_a2dp_codec_index_t codec_type; |
| btav_a2dp_codec_priority_t |
| codec_priority; // Codec selection priority |
| // relative to other codecs: larger value |
| // means higher priority. If 0, reset to |
| // default. |
| btav_a2dp_codec_sample_rate_t sample_rate; |
| btav_a2dp_codec_bits_per_sample_t bits_per_sample; |
| btav_a2dp_codec_channel_mode_t channel_mode; |
| int64_t codec_specific_1; // Codec-specific value 1 |
| int64_t codec_specific_2; // Codec-specific value 2 |
| int64_t codec_specific_3; // Codec-specific value 3 |
| int64_t codec_specific_4; // Codec-specific value 4 |
| |
| std::string ToString() const { |
| std::string codec_name_str; |
| |
| switch (codec_type) { |
| case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC: |
| codec_name_str = "SBC"; |
| break; |
| case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC: |
| codec_name_str = "AAC"; |
| break; |
| case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX: |
| codec_name_str = "aptX"; |
| break; |
| case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD: |
| codec_name_str = "aptX HD"; |
| break; |
| case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC: |
| codec_name_str = "LDAC"; |
| break; |
| case BTAV_A2DP_CODEC_INDEX_SINK_SBC: |
| codec_name_str = "SBC (Sink)"; |
| break; |
| case BTAV_A2DP_CODEC_INDEX_SINK_AAC: |
| codec_name_str = "AAC (Sink)"; |
| break; |
| case BTAV_A2DP_CODEC_INDEX_SINK_LDAC: |
| codec_name_str = "LDAC (Sink)"; |
| break; |
| case BTAV_A2DP_CODEC_INDEX_SOURCE_LC3: |
| codec_name_str = "LC3"; |
| break; |
| case BTAV_A2DP_CODEC_INDEX_SINK_OPUS: |
| codec_name_str = "Opus (Sink)"; |
| break; |
| case BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS: |
| codec_name_str = "Opus"; |
| break; |
| case BTAV_A2DP_CODEC_INDEX_MAX: |
| codec_name_str = "Unknown(CODEC_INDEX_MAX)"; |
| break; |
| } |
| |
| std::string sample_rate_str; |
| AppendCapability(sample_rate_str, |
| (sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE), "NONE"); |
| AppendCapability(sample_rate_str, |
| (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_44100), |
| "44100"); |
| AppendCapability(sample_rate_str, |
| (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_48000), |
| "48000"); |
| AppendCapability(sample_rate_str, |
| (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_88200), |
| "88200"); |
| AppendCapability(sample_rate_str, |
| (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_96000), |
| "96000"); |
| AppendCapability(sample_rate_str, |
| (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_176400), |
| "176400"); |
| AppendCapability(sample_rate_str, |
| (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_192000), |
| "192000"); |
| AppendCapability(sample_rate_str, |
| (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_16000), |
| "16000"); |
| AppendCapability(sample_rate_str, |
| (sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_24000), |
| "24000"); |
| |
| std::string bits_per_sample_str; |
| AppendCapability(bits_per_sample_str, |
| (bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE), |
| "NONE"); |
| AppendCapability(bits_per_sample_str, |
| (bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16), |
| "16"); |
| AppendCapability(bits_per_sample_str, |
| (bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24), |
| "24"); |
| AppendCapability(bits_per_sample_str, |
| (bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32), |
| "32"); |
| |
| std::string channel_mode_str; |
| AppendCapability(channel_mode_str, |
| (channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE), |
| "NONE"); |
| AppendCapability(channel_mode_str, |
| (channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_MONO), |
| "MONO"); |
| AppendCapability(channel_mode_str, |
| (channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO), |
| "STEREO"); |
| |
| return "codec: " + codec_name_str + |
| " priority: " + std::to_string(codec_priority) + |
| " sample_rate: " + sample_rate_str + |
| " bits_per_sample: " + bits_per_sample_str + |
| " channel_mode: " + channel_mode_str + |
| " codec_specific_1: " + std::to_string(codec_specific_1) + |
| " codec_specific_2: " + std::to_string(codec_specific_2) + |
| " codec_specific_3: " + std::to_string(codec_specific_3) + |
| " codec_specific_4: " + std::to_string(codec_specific_4); |
| } |
| |
| private: |
| static std::string AppendCapability(std::string& result, bool append, |
| const std::string& name) { |
| if (!append) return result; |
| if (!result.empty()) result += "|"; |
| result += name; |
| return result; |
| } |
| }; |
| |
| typedef struct { |
| btav_a2dp_scmst_enable_status_t enable_status; |
| uint8_t cp_header; |
| } btav_a2dp_scmst_info_t; |
| |
| typedef struct { |
| bt_status_t status; |
| uint8_t error_code; |
| std::optional<std::string> error_msg; |
| } btav_error_t; |
| |
| /** Callback for connection state change. |
| * state will have one of the values from btav_connection_state_t |
| */ |
| typedef void (*btav_connection_state_callback)(const RawAddress& bd_addr, |
| btav_connection_state_t state, |
| const btav_error_t& error); |
| |
| /** Callback for audiopath state change. |
| * state will have one of the values from btav_audio_state_t |
| */ |
| typedef void (*btav_audio_state_callback)(const RawAddress& bd_addr, |
| btav_audio_state_t state); |
| |
| /** Callback for audio configuration change. |
| * Used only for the A2DP Source interface. |
| */ |
| typedef void (*btav_audio_source_config_callback)( |
| const RawAddress& bd_addr, btav_a2dp_codec_config_t codec_config, |
| std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities, |
| std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities); |
| |
| /** Callback for audio configuration change. |
| * Used only for the A2DP Sink interface. |
| * sample_rate: sample rate in Hz |
| * channel_count: number of channels (1 for mono, 2 for stereo) |
| */ |
| typedef void (*btav_audio_sink_config_callback)(const RawAddress& bd_addr, |
| uint32_t sample_rate, |
| uint8_t channel_count); |
| |
| /** Callback for querying whether the mandatory codec is more preferred. |
| * Used only for the A2DP Source interface. |
| * Return true if optional codecs are not preferred. |
| */ |
| typedef bool (*btav_mandatory_codec_preferred_callback)( |
| const RawAddress& bd_addr); |
| |
| /** BT-AV A2DP Source callback structure. */ |
| typedef struct { |
| /** set to sizeof(btav_source_callbacks_t) */ |
| size_t size; |
| btav_connection_state_callback connection_state_cb; |
| btav_audio_state_callback audio_state_cb; |
| btav_audio_source_config_callback audio_config_cb; |
| btav_mandatory_codec_preferred_callback mandatory_codec_preferred_cb; |
| } btav_source_callbacks_t; |
| |
| /** BT-AV A2DP Sink callback structure. */ |
| typedef struct { |
| /** set to sizeof(btav_sink_callbacks_t) */ |
| size_t size; |
| btav_connection_state_callback connection_state_cb; |
| btav_audio_state_callback audio_state_cb; |
| btav_audio_sink_config_callback audio_config_cb; |
| } btav_sink_callbacks_t; |
| |
| /** |
| * NOTE: |
| * |
| * 1. AVRCP 1.0 shall be supported initially. AVRCP passthrough commands |
| * shall be handled internally via uinput |
| * |
| * 2. A2DP data path shall be handled via a socket pipe between the AudioFlinger |
| * android_audio_hw library and the Bluetooth stack. |
| * |
| */ |
| |
| /** Represents the standard BT-AV A2DP Source interface. |
| */ |
| typedef struct { |
| /** set to sizeof(btav_source_interface_t) */ |
| size_t size; |
| /** |
| * Register the BtAv callbacks. |
| */ |
| bt_status_t (*init)( |
| btav_source_callbacks_t* callbacks, int max_connected_audio_devices, |
| const std::vector<btav_a2dp_codec_config_t>& codec_priorities, |
| const std::vector<btav_a2dp_codec_config_t>& offloading_preference); |
| |
| /** connect to headset */ |
| bt_status_t (*connect)(const RawAddress& bd_addr); |
| |
| /** dis-connect from headset */ |
| bt_status_t (*disconnect)(const RawAddress& bd_addr); |
| |
| /** sets the connected device silence state */ |
| bt_status_t (*set_silence_device)(const RawAddress& bd_addr, bool silence); |
| |
| /** sets the connected device as active */ |
| bt_status_t (*set_active_device)(const RawAddress& bd_addr); |
| |
| /** configure the codecs settings preferences */ |
| bt_status_t (*config_codec)( |
| const RawAddress& bd_addr, |
| std::vector<btav_a2dp_codec_config_t> codec_preferences); |
| |
| /** Closes the interface. */ |
| void (*cleanup)(void); |
| |
| } btav_source_interface_t; |
| |
| /** Represents the standard BT-AV A2DP Sink interface. |
| */ |
| typedef struct { |
| /** set to sizeof(btav_sink_interface_t) */ |
| size_t size; |
| /** |
| * Register the BtAv callbacks |
| */ |
| bt_status_t (*init)(btav_sink_callbacks_t* callbacks, |
| int max_connected_audio_devices); |
| |
| /** connect to headset */ |
| bt_status_t (*connect)(const RawAddress& bd_addr); |
| |
| /** dis-connect from headset */ |
| bt_status_t (*disconnect)(const RawAddress& bd_addr); |
| |
| /** Closes the interface. */ |
| void (*cleanup)(void); |
| |
| /** Sends Audio Focus State. */ |
| void (*set_audio_focus_state)(int focus_state); |
| |
| /** Sets the audio track gain. */ |
| void (*set_audio_track_gain)(float gain); |
| |
| /** sets the connected device as active */ |
| bt_status_t (*set_active_device)(const RawAddress& bd_addr); |
| } btav_sink_interface_t; |
| |
| __END_DECLS |
| |
| #endif /* ANDROID_INCLUDE_BT_AV_H */ |