Android BluetoothA2dp

一、BluetoothA2dp介绍

高级音频分发规范 (A2DP) 定义了实现以单声道(mono)、立体声(stereo)或多声道(multi-channel)模式分发高质量音频内容的协议和程序。因此,术语“高级音频(advanced audio)”应与“蓝牙音频(Bluetooth audio)”区分开来,后者表示在蓝牙核心规范第 2 卷 B 部分第 9 节中定义的 SCO 通道上的窄带语音分布。

一个典型的用例是将音乐内容从立体声音乐播放器流式传输到耳机或扬声器。音频数据以适当的格式压缩,以有效利用有限的带宽。

A2DP 专注于音频流,而视频分发配置文件 (VDP) 指定视频流。对这两种配置文件的支持可以分发带有高质量音频的视频内容。 VDP中描述了视频和音频流的使用案例。

另请注意,A2DP 不包括远程控制功能。设备可以通过实现 A2DP 和所描述的控制配置文件来支持远程控制功能,例如,在音频/视频远程控制配置文件 (AVRCP) 的使用场景中。

A2DP 取决于通用访问配置文件 (GAP) 以及通用音频/视频分发配置文件 (GAVDP),后者定义了设置音频/视频流所需的程序。 A2DP 定义了特定于音频流的参数和过程。

BluetoothA2dp构造图

如下为BluetoothA2dp构造图:

BluetoothA2dp协议栈

如下为BluetoothA2dp协议栈:

AVDTP协议建立在connection-oriented L2CAP channel上,只能支持point-to-point signaling

BluetoothA2dp角色

Source源 (SRC) – 发送音频的称为 Source。

Sink接收器 (SNK) – 接收音频的称为Sink。

例如:车机连接蓝牙耳机播放音乐, 那么车机就是做 source 设备,蓝牙耳机就是sink 设备。

车机连接手机播放手机中的音乐,那么手机就是做 source 设备,车机就是sink 设备。

BluetoothA2dp ABR

A2DP ABR是指A2DP自适应比特率(Adaptive Bit Rate)功能。它允许音频流根据当前的无线连接质量自动调整比特率,以提供更好的音频体验。在A2DP ABR中,音频流的比特率可以根据无线信号的强度和稳定性进行动态调整,以确保音频的连续播放和较高的音质。

A2DP ABR的实现依赖于A2DP协议和相关的硬件支持。在Android系统中,A2DP ABR功能可以通过硬件卸载来实现,即将音频流的处理交给音频处理器和蓝牙控制器,以减轻主处理器的负担。这样可以提高音频传输的效率和稳定性。

要启用A2DP ABR功能,需要确保设备的蓝牙芯片支持A2DP硬件卸载功能,并且在系统设置中将A2DP硬件卸载功能设置为启用状态。默认情况下,A2DP硬件卸载功能是关闭的,但可以通过设置来启用。

总结起来,A2DP ABR是一种通过动态调整比特率来提供更好音频体验的功能,它依赖于A2DP协议和相关的硬件支持。在Android系统中,可以通过启用A2DP硬件卸载功能来实现A2DP ABR功能。

BluetoothA2dp相关术语

Stream:represents the logical end-to-end connection of streaming media data (audio or video) between two A/V devices(音视频流数据).

Media Packets, Recovery Packets, and Reporting Packets:根据三种不同的数据类型,有这三种数据包。其中,Basic Service会用到Basic service,Report service会用到Reporting Packets,Recovery service会用到Recovery Packets,此外Multiplexing service会用到Media Packets和其余一种或两种Packet。

Stream End Point (SEP):应用程序通过这个接口提供Transport Services and AV capabilities来建立Stream。

Stream Context (SC):两端设备都有的关于Stream的信息。

Stream Handle (SH):主要是暴露给用于程序使用的。

Stream End Point Identifier (SEID):标识Stream End Point的。

Transport Session:一条stream可以分解为多个transport sessions,每个transport session对应一个AVDTP的packet category ,which means Media, Recovery, or Reporting packets。

Transport Session Identifier (TSID):标识Transport Session。

Transport Channel:通常和一个L2CAP Channel对应。不用AVDTP Multiplexing Mode时,一条Transport Channel只传输一个transport session;用transport session的情况下,一条Transport Channel可以传输多个transport session(media,report或者recovery)。

Transport Channel Identifier (TCID):标识Transport Channel,唯一关联一条L2CAP channel。

GAVDP定义了两种角色:

Initiator (INT) – This is the device that initiates a signaling procedure.【发起signaling的】

Acceptor (ACP) – This is the device that shall respond to an incoming request from the INT.【响应signaling的】

A2DP在此基础上具体实现了连个角色:

Source (SRC) – A device is the SRC when it acts as a source of a digital audio stream that is delivered to the SNK of the piconet.【输出音频stream的】

Sink (SNK) – A device is the SNK when it acts as a sink of a digital audio stream delivered from the SRC on the same piconet.【接受音频stream的】

这里需要注意的是:一般在A2DP中Source和Sink的角色是固定的,而GAVDP的这两个角色是可以互换的,只要是发起signaling的一方就为initiator。

二、BluetoothA2dp相关接口

IBluetoothA2dp

APIs for Bluetooth A2DP service

蓝牙 A2DP 服务的 API

IBluetoothA2dp代码位于:

packages/modules/Bluetooth/system/binder/android/bluetooth/IBluetoothA2dp.aidl

IBluetoothA2dp的定义:

oneway interface IBluetoothA2dp {}

IBluetoothA2dp API:

void connect(in BluetoothDevice device, in SynchronousResultReceiver receiver);
void connectWithAttribution(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
void disconnect(in BluetoothDevice device, in SynchronousResultReceiver receiver);
void disconnectWithAttribution(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
void getConnectedDevices(in SynchronousResultReceiver receiver);
void getConnectedDevicesWithAttribution(in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
void getDevicesMatchingConnectionStates(in int[] states, in SynchronousResultReceiver receiver);
void getDevicesMatchingConnectionStatesWithAttribution(in int[] states, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
void getConnectionState(in BluetoothDevice device, in SynchronousResultReceiver receiver);    
void getConnectionStateWithAttribution(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
void setActiveDevice(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
void getActiveDevice(in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
void setConnectionPolicy(in BluetoothDevice device, int connectionPolicy, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
void getConnectionPolicy(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver)
void isAvrcpAbsoluteVolumeSupported(in SynchronousResultReceiver receiver);
oneway void setAvrcpAbsoluteVolume(int volume, in AttributionSource attributionSource);
void isA2dpPlaying(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
void getCodecStatus(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
oneway void setCodecConfigPreference(in BluetoothDevice device, in BluetoothCodecConfig codecConfig, in AttributionSource attributionSource);
oneway void enableOptionalCodecs(in BluetoothDevice device, in AttributionSource attributionSource)
oneway void disableOptionalCodecs(in BluetoothDevice device, in AttributionSource attributionSource);
void isOptionalCodecsSupported(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
void isOptionalCodecsEnabled(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
oneway void setOptionalCodecsEnabled(in BluetoothDevice device, int value, in AttributionSource attributionSource);
void getDynamicBufferSupport(in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
void getBufferConstraints(in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
void setBufferLengthMillis(int codec, int size, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);

IBluetoothA2dpSink

APIs for Bluetooth A2DP sink service

蓝牙 A2DP 接收器服务的 API

IBluetoothA2dpSink代码位于:

packages/modules/Bluetooth/system/binder/android/bluetooth/IBluetoothA2dp.aidl

IBluetoothA2dpSink的定义:

oneway interface IBluetoothA2dpSink {}

IBluetoothA2dpSink API:

      void connect(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
        void disconnect(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
        void getConnectedDevices(in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
        void getDevicesMatchingConnectionStates(in int[] states, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
        void getConnectionState(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
        void getAudioConfig(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
        void setConnectionPolicy(in BluetoothDevice device, int connectionPolicy, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
        void getConnectionPolicy(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
        void isA2dpPlaying(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);

三、BluetoothA2dp相关类

BluetoothA2dp

BluetoothA2dp是Android中的一个类,它代表了蓝牙高级音频分发配置文件(A2DP)。它允许设备通过蓝牙连接到音频设备,例如耳机或扬声器,并传输高质量的音频流。BluetoothA2dp类实现了Android.Bluetooth.IBluetoothProfile接口,该接口定义了蓝牙配置文件的通用行为。@Android.Runtime.Register注释用于注册Java类,以便在运行时使用。DoNotGenerateAcw参数告诉Mono for Android不要为该类生成额外的包装器类。

BluetoothA2dp代码位于:

packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothA2dp.java

BluetoothA2dp的定义:

public final class BluetoothA2dp implements BluetoothProfile {}

BluetoothA2dp API:

public boolean connect(BluetoothDevice device):连接
public boolean disconnect(BluetoothDevice device):断开连接
public List<BluetoothDevice> getConnectedDevices():获取此特定配置文件的连接设备。
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states):获取匹配任何给定连接状态的设备列表。
public int getConnectionState(BluetoothDevice device):获取配置文件的当前连接状态
public boolean setActiveDevice(@Nullable BluetoothDevice device):设置活动设备
public BluetoothDevice getActiveDevice():获取活动设备
public boolean setPriority(BluetoothDevice device, int priority):设置权限。入参为需要设置的远端设备实例以及权限能力。
public boolean setConnectionPolicy(@NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) :设置协议连接策略。入参为需设置的设备及连接策略。
public int getPriority(BluetoothDevice device) :获取权限
public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) :获取连接策略
public boolean isAvrcpAbsoluteVolumeSupported():检查Avrcp设备是否支持绝对音量功能。
public void setAvrcpAbsoluteVolume(int volume) :设置Avrcp绝对音量
public boolean isA2dpPlaying(BluetoothDevice device):检查 A2DP 配置文件是否正在播放音乐。
public BluetoothCodecStatus getCodecStatus(@NonNull BluetoothDevice device) :获取解码器状态
public void setCodecConfigPreference(@NonNull BluetoothDevice device, @NonNull BluetoothCodecConfig codecConfig):设置编解码器配置首选项。
public void enableOptionalCodecs(@NonNull BluetoothDevice device) :启用可选的 Codex 备用设备故障连接。
public void disableOptionalCodecs(@NonNull BluetoothDevice device) :禁用可选的 Codex 常见设备故障连接。
public void setOptionalCodecsEnabled(@NonNull BluetoothDevice device, @OptionalCodecsPreferenceStatus int value):设置可选 Codex Normal 设备的默认状态。
public @Type int getDynamicBufferSupport() :Get the supported type of the Dynamic Audio Buffer.
public @Nullable BufferConstraints getBufferConstraints() :返回 Record-of-BufferConstraints 对象起始器默认值/最大值/最小音频缓冲区。可以使用并通知Whatte控制器具有sapport forte音频缓冲区。
public boolean setBufferLengthMillis(@BluetoothCodecConfig.SourceCodecType int codec, int value) :设置动态音频缓冲区大小。

BluetoothA2dpSink

BluetoothA2dpSink是Android中的一个类,它代表了一个A2DP Sink(即蓝牙音频接收器)的Bluetooth Profile。通过BluetoothAdapter的getProfileProxy方法获取BluetoothA2dpSink的实例,可以对A2DP协议连接状态进行操作,包括获取当前连接状态和连接/断开A2DP协议连接等操作。

BluetoothA2dpSink代码位于:

packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothA2dpSink.java

BluetoothA2dpSink的定义:

public final class BluetoothA2dpSink implements BluetoothProfile {}

BluetoothA2dpSinkAPI:

public boolean connect(BluetoothDevice device):连接
public boolean disconnect(BluetoothDevice device):断开连接
public List<BluetoothDevice> getConnectedDevices()获取连接设备
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states):获取匹配任何给定连接状态的设备列表。
public int getConnectionState(BluetoothDevice device) 获取配置文件的当前连接状态
public BluetoothAudioConfig getAudioConfig(BluetoothDevice device):获取 A2DP 源设备的当前音频配置,如果设备没有音频配置,则为 null
public boolean setPriority(BluetoothDevice device, int priority) :设置权限。入参为需要设置的远端设备实例以及权限能力。
public boolean setConnectionPolicy(@NonNull BluetoothDevice device, @ConnectionPolicy int connectionPolicy) :设置协议连接策略。入参为需设置的设备及连接策略。
public int getPriority(BluetoothDevice device):获取权限
public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) :获取连接策略
public boolean isAudioPlaying(@NonNull BluetoothDevice device):检查蓝牙设备上是否正在播放音频(A2DP 配置文件正在播放音乐)。

BluetoothCodecStatus

Represents the codec status (configuration and capability) for a Bluetooth A2DP source device.

表示蓝牙 A2DP 源设备的编解码器状态(配置和功能)。

BluetoothCodecStatus代码位于:

packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothCodecStatus.java

BluetoothCodecStatus的定义:

public final class BluetoothCodecStatus implements Parcelable {}

A2dpService

A2dpService是Android系统中的一个服务,它提供了A2DP的支持,允许设备通过蓝牙连接到音频设备并进行音频传输。A2dpService通过实现IProfileService接口来提供服务,并通过BluetoothA2dpBinder类来绑定服务。在A2dpService中,initBinder()方法用于初始化Binder对象,start()方法用于启动服务并设置状态机。A2dpService还提供了一些其他的方法,例如连接到远程设备、断开连接、获取连接状态等。

A2dpService代码位于:

packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dp/A2dpService.java

A2dpService的定义:

public class A2dpService extends ProfileService {
    private class BondStateChangedReceiver extends BroadcastReceiver {}
    static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub implements IProfileServiceBinder {}
}

A2dpSinkService

A2dpSinkService是Android系统中的一个服务,用于支持A2DP Sink Profile。A2DP Sink Profile是种蓝牙音频协议,允许设备接收来自其他设备的音频流。A2dpSinkService可以让Android设备作为A2DP Sink设备,接收其他设备(如手机、电脑等)发送的音频流,并将其播放出来。

A2dpSinkService代码位于:

packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dp/A2dpSinkService.java

A2dpSinkService的定义:

public class A2dpSinkService extends ProfileService {
    private static class A2dpSinkServiceBinder extends IBluetoothA2dpSink.Stub implements IProfileServiceBinder {}
}

A2dpStateMachine

A2dpStateMachine是Bluetooth.apk中的一个类,用于管理A2DP(Advanced Audio Distribution Profile)状态机。它在自己的构造函数中对编码的支持进行了初始化,并且包含了编码的支持。A2dpStateMachine还负责处理A2DP连接和断开连接的事件,并在连接建立后启动音频流传输。除此之外,A2dpStateMachine还负责处理来自底层蓝牙协议栈的事件,例如SCO(Synchronous Connection-Oriented)连接的建立和断开等。

A2dpStateMachine代码位于:

packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java

A2dpStateMachine的定义:

final class A2dpStateMachine extends StateMachine {
    class Disconnected extends State {}
    class Connecting extends State {}
    class Disconnecting extends State {}
    class Connected extends State {}
}

A2dpSinkStateMachine

A2dpSinkStateMachine是Android系统中的一个状态机,用于管理A2DP Sink Profile的连接和断开连接。它是Bluetooth A2DP Sink Profile的一部分,用于接收来自A2DP Source的音频流并将其传输到本地设备的音频输出设备上。A2dpSinkStateMachine的主要作用是管理A2DP Sink Profile的连接和断开连接,以及处理来自A2DP Source的音频流。它还负责处理来自系统的其他事件,例如蓝牙连接状态的更改和音频输出设备的更改。

A2dpSinkStateMachine代码位于:

packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java

A2dpSinkStateMachine的定义:

public class A2dpSinkStateMachine extends StateMachine {
    class Disconnected extends State {}
    class Connecting extends State {}
    class Connected extends State {}
    protected class Disconnecting extends State {}
}

A2dpNativeInterface

A2DP Native Interface to/from JNI.

与JNI之间的A2DP接收器本机接口。

A2dpNativeInterface代码位于:

packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java

A2dpNativeInterface的定义:

public class A2dpNativeInterface {}

A2dpNativeInterface方法:

public static A2dpNativeInterface getInstance():Get singleton instance.
public void init(int maxConnectedAudioDevices, BluetoothCodecConfig[] codecConfigPriorities, BluetoothCodecConfig[] codecConfigOffloading) :Initializes the native interface.
public void cleanup():Cleanup the native interface.
public boolean connectA2dp(BluetoothDevice device):Initiates A2DP connection to a remote device.
public boolean disconnectA2dp(BluetoothDevice device) :Disconnects A2DP from a remote device.
public boolean setSilenceDevice(BluetoothDevice device, boolean silence):Sets a connected A2DP remote device to silence mode.
public boolean setActiveDevice(BluetoothDevice device):Sets a connected A2DP remote device as active.
public boolean setCodecConfigPreference(BluetoothDevice device, BluetoothCodecConfig[] codecConfigArray):Sets the codec configuration preferences.
private void onConnectionStateChanged(byte[] address, int state)
private void onAudioStateChanged(byte[] address, int state) 
private void onCodecConfigChanged(byte[] address, BluetoothCodecConfig newCodecConfig, BluetoothCodecConfig[] codecsLocalCapabilities, BluetoothCodecConfig[] codecsSelectableCapabilities)
private boolean isMandatoryCodecPreferred(byte[] address) 

A2dpSinkNativeInterface

A2DP Sink Native Interface to/from JNI.

与JNI之间的A2DP接收器本机接口。

A2dpSinkNativeInterface代码位于:

packages/modules/Bluetooth/abdriid/app/src/com/android/bluetooth/a2dpsink/A2dpSinkNativeInterface.java

A2dpSinkNativeInterface的定义:

public class A2dpSinkNativeInterface {}

A2dpSinkNativeInterface方法:

public static A2dpSinkNativeInterface getInstance() :Get singleton instance.
public void init(int maxConnectedAudioDevices):Initializes the native interface and sets the max number of connected devices
public void cleanup() :Cleanup the native interface.
public boolean connectA2dpSink(BluetoothDevice device):Initiates an A2DP connection to a remote device.
public boolean disconnectA2dpSink(BluetoothDevice device) :Disconnects A2DP from a remote device.
public boolean setActiveDevice(BluetoothDevice device) :Set a BluetoothDevice as the active device
public void informAudioFocusState(int focusGranted):Inform A2DP decoder of the current audio focus
public void informAudioTrackGain(float gain):Inform A2DP decoder the desired audio gain
public void onConnectionStateChanged(byte[] address, int state) :For the JNI to send messages about connection state changes
public void onAudioStateChanged(byte[] address, int state) :For the JNI to send messages about audio stream state changes
public void onAudioConfigChanged(byte[] address, int sampleRate, int channelCount):For the JNI to send messages about audio configuration changes

四、BluetoothA2dp流程分析

BluetoothA2dp connect流程分析

Android13 BluetoothA2dp connect流程分析-CSDN博客

BluetoothA2dp disconnect流程分析

Android13 BluetoothA2dp disconnect流程分析-CSDN博客

BluetoothA2dpSink connect流程分析

Android13 BluetoothA2dpSink connect流程分析-CSDN博客

BluetoothA2dpSink disconnect流程分析

Android13 BluetoothA2dpSink disconnect流程分析-CSDN博客

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值