如何修改 Android 的蓝牙堆栈以启用 A2dp 接收器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21104611/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:59:52  来源:igfitidea点击:

How To Modify Android's Bluetooth Stack to Enable A2dp Sink

androidbluetoothaudio-recordingmicrophonea2dp

提问by Eu-Lee

I'm working on an audio recorder app that uses a bluetooth mic to record audio on to an Android device (Nexus 7 - rooted Android 4.4.2). It's currently implemented on HFP and everything is working fine. The bluetooth mic is implemented with Bluegiga's WT32 bluetooth module + a mic input, audio quality via HFP isn't great but it's sufficient for now.

我正在开发一个录音机应用程序,该应用程序使用蓝牙麦克风将音频录制到 Android 设备(Nexus 7 - 根植于 Android 4.4.2)。它目前在 HFP 上实施,一切正常。蓝牙麦克风是通过 Bluegiga 的 WT32 蓝牙模块 + 麦克风输入实现的,通过 HFP 的音频质量不是很好,但现在已经足够了。

However, I'm now trying to change the bluetooth profile to A2dp, since there are two mic inputs (L/R) and WT32 supports A2dp (source). After much research I found that stock Android doesn't support A2dp (sink), and it's possible to modify Android's bluetooth stack to enable A2dp (sink).

但是,我现在正在尝试将蓝牙配置文件更改为 A2dp,因为有两个麦克风输入(L/R)并且 WT32 支持 A2dp(来源)。经过大量研究,我发现库存 Android 不支持 A2dp(接收器),并且可以修改 Android 的蓝牙堆栈以启用 A2dp(接收器)。

What I don't understand is how does one access and modify the bluetooth stack.It would be nice if someone with an answer is able to break-down the steps to achieve this.

我不明白的是如何访问和修改蓝牙堆栈。如果有答案的人能够分解实现这一目标的步骤,那就太好了。

I've tried following the answer to this question: Receive audio via Bluetooth in Android, yet I can't seem to find the appropriate file to modify. Actually, I don't even know if I'm looking into the right folder. I've looked through the devices file via Android-studio's DDMS-File Explorer.

我试过按照这个问题的答案: 在 Android 中通过蓝牙接收音频,但我似乎找不到合适的文件来修改。实际上,我什至不知道我是否正在查看正确的文件夹。我已经通过 Android-studio 的 DDMS-File Explorer 查看了设备文件。

ps, I'm still fairly new with Android app development, so I may have misused some of the terminologies and I apologies in-advance for that.

ps,我对 Android 应用程序开发还很陌生,所以我可能误用了一些术语,我提前道歉。

采纳答案by Avi Shukron

This is actually what I'm trying to do for a long time... The reason you can't find the configuration file is because Google replaced the Bluetooth stack from BlueZ with a new stack built by Google and Broadcom. The new stack uses a different configuration file, which I don't know how to tinker with.

这其实是我很久以来一直在努力做的…… 之所以找不到配置文件,是因为谷歌用谷歌和博通构建的新堆栈替换了BlueZ的蓝牙堆栈。新堆栈使用不同的配置文件,我不知道如何修改。

If you are serious about it, the closest thing I found to start with is the official introduction for the bluetooth framework on Android: https://source.android.com/devices/bluetooth.html

如果你是认真的,我发现最接近的是Android上蓝牙框架的官方介绍:https: //source.android.com/devices/bluetooth.html

回答by Zach

So the above answer isn't totally correct.

所以上面的答案并不完全正确。

The following is how it breaks down:

以下是它的分解方式:

HAL, is the hardware abstraction layer that implements the actual Bluetooth state machines in c/cpp code, as such it controls the various state machines for A2dp, HFP, GATT, SPP, AVRCP, etc. services. Each of these services also reference SMP and ATT files for controlling the actual Bluetooth server or client databases, and there security.

HAL 是硬件抽象层,它在 c/cpp 代码中实现实际的蓝牙状态机,因此它控制 A2dp、HFP、GATT、SPP、AVRCP 等服务的各种状态机。这些服务中的每一个还引用 SMP 和 ATT 文件来控制实际的蓝牙服务器或客户端数据库,以及安全性。

HCI, is where the actual work gets done. the HAL doesn't really doanything, it assembles the complex data messages that get sent along a tty serial (either spi, or UART) to an inter-network connected chip on the PCBA via the methods used in the HCI layer, which can be found in the "BTE" layer in /external/bluetooth/bluedroid/ directory of an android compiling trunk from AOSP 4.2.2 to current. - currently there are several manufacturers of these chips but they are mostly all Broadcom based ic's packaged in a dual, or triple radio package that contains a wifi, Bluetooth 4.0 Smart, and Bluetooth 4.0 radio.

HCI,是完成实际工作的地方。HAL 并没有真正任何事情,它通过 HCI 层中使用的方法组装沿着 tty 串行(spi 或 UART)发送到 PCBA 上的网络间连接芯片的复杂数据消息,这可以可以在从 AOSP 4.2.2 到当前的 android 编译主干的 /external/bluetooth/bluedroid/ 目录中的“BTE”层中找到。- 目前有几家制造商生产这些芯片,但它们大多都是基于 Broadcom 的 ic 封装在双或三无线电包中,其中包含 wifi、蓝牙 4.0 智能和蓝牙 4.0 无线电。

It is possible to do what you are trying to do, but you would need to include hardware.so, and bluetooth_jni.so into an NDK/JNI package/project that goes with your apps, and registers via the calls from the .cpp files for each of the Bluetooth services found in "Packages/apps/Bluetooth/jni", you would then handle the registration in your NDK library of 'com_android_bluetooth_a2dp.cpp', and 'com_android_bluetooth_avrcp.cpp', as their appropriately typed objects.

可以做您想做的事情,但您需要将 hardware.so 和 bluetooth_jni.so 包含到与您的应用程序一起使用的 NDK/JNI 包/项目中,并通过来自 .cpp 文件的调用进行注册对于在“Packages/apps/Bluetooth/jni”中找到的每个蓝牙服务,您将在 NDK 库中处理“com_android_bluetooth_a2dp.cpp”和“com_android_bluetooth_avrcp.cpp”中的注册,作为它们的适当类型对象。

The other issue is, you will need to implement your own custom A2DP stack, as the Android Bluedroid stack only has bit's and piece's of the Sinkrole implemented in the frameworks while the A2DP role has a full implementation of Sourcerole. Additionally, depending what you actually intend to do with your Bluetooth A2DP sink implementation you will need to implement AVRCP as well - as per the Bluetooth SIG (special interest group), there are inter-connectivity requirements between Bluetooth devices that will lead to major issues if you implement sink role, without AVRCP "remote control target device" and "remote control control device", as the sink role ATT commands from Bluetooth over A2DP (or any Bluetooth service/profile) execute certain handshakes during the service discovery process, when the associated gateway ( the connecting device ), executes a capabilities request the A2DP service is expected to implement i/o capabilities for Start Stop commands, and possibly skip/track advance commands.

另一个问题是,您需要实现自己的自定义 A2DP 堆栈,因为 Android Bluedroid 堆栈只有在框架中实现的Sink角色的零碎部分,而 A2DP 角色具有Source的完整实现角色。此外,根据您实际打算对蓝牙 A2DP 接收器实现做什么,您还需要实现 AVRCP - 根据蓝牙 SIG(特殊兴趣小组),蓝牙设备之间存在互连要求,这将导致重大问题如果您实现接收器角色,没有 AVRCP“远程控制目标设备”和“远程控制设备”,作为接收器角色 ATT 命令从蓝牙通过 A2DP(或任何蓝牙服务/配置文件)在服务发现过程中执行某些握手,当关联的网关(连接设备),执行能力请求,A2DP 服务预期实现启动停止命令的 I/O 能力,并可能跳过/跟踪提前命令。

Additional to all of this, when implementing A2DP you will need to choose whether you will be handling PCM streams or AAC streams. If you are handling AAC streams (or DRM protected PCM streams for that matter, which anything like Pandora, spotify, etc. uses), you need to implement the SBC Encoder or Decoder appropriate to you implementation, else all you will have is a bunch of encrypted data. Also, be sure to implement the bitrate at the appropriate speed for your devices AudioManager implementation, some phones use 48,000hZ and some us 44,100hZ, this is important if you want high quality audio as generally most PCM A2DP implementations that are utilizing Surround Sound 7.1+ will require 48,000hZ as well as AAC encoding/decoding.

除此之外,在实现 A2DP 时,您需要选择是处理 PCM 流还是 AAC 流。如果您正在处理 AAC 流(或 DRM 保护的 PCM 流,例如 Pandora、spotify 等使用的),您需要实现适合您实现的 SBC 编码器或解码器,否则您将拥有的只是一堆的加密数据。此外,请确保为您的设备 AudioManager 实现以适当的速度实现比特率,有些手机使用 48,000hZ,有些手机使用 44,100hZ,如果您想要高质量的音频,这很重要,因为通常大多数使用环绕声 7.1 的 PCM A2DP 实现+ 将需要 48,000hZ 以及 AAC 编码/解码。

I hope this provides you with some insight.

我希望这可以为您提供一些见解。

回答by Wenjie Gong

https://android-review.googlesource.com/#/c/98161/implements A2DP Sink. It works on Nexus 5. You can try it.

https://android-review.googlesource.com/#/c/98161/实现 A2DP Sink。它适用于 Nexus 5。你可以试试。

回答by Abhishek Dwivedi

There are lots of changes happened in Android OS over the time.

随着时间的推移,Android 操作系统发生了很多变化。

As of Android O (Android 8.*), sink profiles are partially supported by Google. Such as Audio sink will easily work if enabled in profile. It looks like the higher layer of BT is kind of implementation complete at the framework, which is in the form of App i.e. packages/app/Bluetooth(with some bugs but still works). But all profiles are not completed at framework lower layer via HAL interfaces which is btif framework (such as btif_rc.cpp, etc which you can look at Android source) and which is the replacement to older Bluez stack by Google.

从 Android O (Android 8.*) 开始,Google 部分支持接收器配置文件。如果在配置文件中启用,例如音频接收器将很容易工作。看起来BT的更高层是在框架中完成的一种实现,它是App ie的形式packages/app/Bluetooth(有一些错误但仍然有效)。但是所有配置文件都不是通过 HAL 接口在框架下层完成的,HAL 接口是 btif 框架(例如btif_rc.cpp等,您可以查看 Android 源代码)并且它是 Google 对旧 Bluez 堆栈的替代。

As I said BT sink is partially implemented and is in work in progress state. BT sink such as Audio will easily work if enabled as sink profile but not all such as AVRCP will not work. At present, I saw the issue with AOSP code that incoming traffic from the remote device to Android works but outgoing traffic from Android to the remote device doesn't work (upon which AVRCP profile works) as remote device object is not maintained in the stack and so JNI calls from app/Bluetooth fails with null device at btif_*.cppfiles. For example, send pass-through commands doesn't work.

正如我所说的,BT 接收器已部分实施并且处于工作状态。如果作为接收器配置文件启用,BT 接收器(例如音频)将很容易工作,但并非所有(例如 AVRCP)都将不起作用。目前,我看到了 AOSP 代码的问题,即从远程设备到 Android 的传入流量有效,但从 Android 到远程设备的传出流量不起作用(AVRCP 配置文件在此基础上有效),因为堆栈中未维护远程设备对象因此来自应用程序/蓝牙的 JNI 调用失败,btif_*.cpp文件中的设备为空。例如,发送传递命令不起作用。

So, we may see Bluetooth sink profiles working in future.

因此,我们可能会看到蓝牙接收器配置文件在未来工作。

If you want to explore more check AOSP,

如果您想探索更多,请查看 AOSP,

  1. Services at packages/app/Bluetooth/
  2. HAL's at system/bt/btif/
  1. 服务在 packages/app/Bluetooth/
  2. HAL 在 system/bt/btif/