Android USB 外置声卡插入Audio系统没有正常识别问题梳理以及分析

背景:

现在项目要求实现一个,要使用NDK接口从外接MIC设备(姑且这么称呼吧)上采集声音数据,然后内部进行音频数据格式转换,再进行音频数据输出;

问题:

插入客户指定设备,发现在JAVA AudioManager无法查询到新接入到的物理设备;(当使用NDK进行音频数据采集,需要进行deviceId参数;在JAVA侧可以通过audioManager获取指定类型设备的deviceId)

NDK接口参照:

https://developer.android.google.cn/ndk/reference/group/audio

使用NDK接口音频采集过程,可以参照:

https://developer.android.google.cn/ndk/guides/audio/aaudio/aaudio

现象以及问题分析:

在Java AudioManager层使用sdk api无法查询到指定类型设备ID,这就说明新插入的设备没有被andriod 系统audioManager进行正确识别或添加,于是从下到上进行问题分析;

知识背景:

在Android系统中整个audio一共分析如下几层:

1、物理层(开发板以及外接MIC物理设备)

2、设备驱动层(集成在kernal中)

3、UsbSever服务(由于外接MIC是通过USB接口与开发板进行连接)

4、android AudioManager等Audio服务

问题排查顺序:

1、当物理设备没有被android 的Audio系统识别,首先排查android系统有没有正确识别到USB声卡插入。

android Audio HAL一般都使用alsa。是android内核中的驱动识别到了声卡物理设备接入之后,驱动程序会自动在/pro/asound 目录下创建一个目录,表明有新的物理声卡接入;

ls /proc/asound/
card0 cards devices hwdep modules oss PCH pcm seq timers version

然后可以通过查询devices文件中的内容,来了解物理声卡的能力;

cat /proc/asound/devices
1: : sequencer
2: [ 0] : control
3: [ 0- 0]: digital audio playback
4: [ 0- 0]: digital audio capture
5: [ 0- 2]: digital audio capture
6: [ 0- 3]: digital audio playback
7: [ 0- 7]: digital audio playback
8: [ 0- 8]: digital audio playback
9: [ 0- 9]: digital audio playback
10: [ 0-10]: digital audio playback
11: [ 0- 0]: hardware dependent
12: [ 0- 2]: hardware dependent
33: : timer

以上信息为card0的信息;

2、根据devices中的信息了解物理设备的能力;(是声音采集设备?是声音播放设备?)

126: [ 1] : control
127: [ 1- 0]: digital audio capture

这是我新插入的audio 设备信息(只有控制接口以及声音采集接口),这就证明我这只是一个音频采集设备并不具备音频播放功能;

3、当/proc/asound/devices 目录下有新的文件夹创建之后。

UsbSever服务中的UsbAlsaManager就会自动识别到有新的设备插入,通过文件夹的名称来识别插入的是哪种设备,是一个声卡设备还是PCM设备。

然后通过devices文件中的信息了解设备的能力;然后根据设备能力生成一个usb Audio设备添加内部进行管理;

未识别时的devices信息:

126: [ 1] : control

发生未设备时的LOG如下:

UsbAlsaManager: Adding ALSA device AlsaDevice:

UsbAlsaManager: USB Audio Device Added: UsbAudioDevice: [card: 1, device: 0, name: USB-Audio - TA-2, hasPlayback: false, hasCapture: false, class: 0x80000002]

识别时的devices信息:

126: [ 1] : control
127: [ 1- 0]: digital audio capture

正确识别的LOG信息如下:

UsbAlsaManager: Adding ALSA device AlsaDevice:

UsbAlsaManager: USB Audio Device Added: UsbAudioDevice: [card: 1, device: 0, name: USB-Audio - TA-2, hasPlayback: false, hasCapture: true, class: 0x80000002]

AudioPolicyManagerCustom: setDeviceConnectionStateInt() device: 0x80001000, state 1, address card=1;device=0; name USB-Audio - TA-2

4、当出现AudioPolicyManagerCustom: setDeviceConnectionStateInt()之后,再使用Java AudioManager就可以正确获取指定类型音频输入设备;

流程总结:

正确的USB声卡设备插入流程大致如下:

1、驱动设备到新的声卡设备插入,并在在proc/asound/目录下创建新的文件夹,并将设备能力写入devices文件中

2、UsbServer发现在proc/asound/目录下有新的文件夹创建,则对新的文件夹以及设备信息进行获取解析。

3、通过新获取的信息则,创建usb上层设备抽象。如果是音频设备,并且是(采集或者播放设备),则将新的设备信息通过AudioManager接口添加到android音频系统;

4、当andriod 系统更新内部设备信息之后,根据audio policy信息重新进行route配置。从而触发音频通路的重新选择。

问题总结:

无论设备发现过程以及设备能力怎样。对于Andrioid audio系统添加新设备的主要流程就是调用setDeviceConnectionState();

如果发现新设备没有被系统所识别:

先检查设备驱动识别正确识别到新的设备;

然后调查这种类型设备的发现机制,是通过uevent识别到的,还是像这种文件夹改变而发现的。

再而检查新设备的设备能力是否与我们设想一致。因为audio系统中所管理的设备要具备音频采集或者播放功能;(混音器没遇到过,所以这部分信息不知道)

最后看audio设备添加是否正常被执行;

如果,新假如设备后,音频通路不正常,则就对policy配置进行检查。

本来想顺着代码将usbserver服务进行解析一下,现在发现还有很多内容不是特别理解,这个课题留在后面进行解决。

原文地址:https://www.cnblogs.com/ouyshy/p/13555510.html