android耳机上报流程,Android系统中耳机按键键值上报不正确 解决过程

【问题现象】

根据测试组同事反馈:在我们的设备上使用 JBL 品牌某款带有 3 个按键的有线耳机时,按下“音量+”键时设备会减小音量而不是增加音量,按下“音量-”键时设备无响应;在设备上使用 Samsung 品牌某款带有 3 个按键的有线耳机时,按下“音量-”键时设备会启动语音助手而不是减小音量。但按下 2 款耳机的中间键(播放/暂停键)均可以得到正确的响应。

【分析问题】

首先查看这 2 款耳机的音频接口,均为 3.5mm 耳机插头,其中三星耳机是白色环的 CTIA 标准插头,JBL耳机是黑色环的 OMTP 标准插头。这 2 种标准插头的区别在于第 3、4个金属环的接法是相反的。CTIA标准的第 3 个金属环为 GND,第 4 个金属环为 MIC;OMTP标准的第 3 个金属环则为 MIC,而第 4 个金属环为 GND。更具体的信息可以参考我之前写的《3.5mm 音频接口类型说明》这篇文章。

然后 adb 登录到设备上,使用 getevent 命令查看耳机按键按下时,设备的实时上报键值和响应。类似下图中这样,参数 /dev/input/event9 :

98035d53c17761e6ef34ac97546d4c72.png

经过实时查看发现:JBL耳机的“音量+”键按下时,实际上报的键值为 KEY_VOLUMEDOWN,所以设备上相应地做出了减小音量的响应,而“音量-”键按下时,没有键值被上报。这很异常。三星耳机的“音量-”键按下时,实际上报的键值为 KEY_VOICECOMMAND,所以设备上相应地启动了语音助手程序。至此可以看到,不是系统上层做出了错误的响应,而是系统底层上报按键事件时就发生了错误,所以应该在底层驱动来解决这个问题。

可是为什么按下 JBL 耳机的“音量-”时没有键值被上报呢?让我们从按键事件的本质来分析:按键本身是个硬件,当它被按下时实际上是接通了耳机检测芯片到地线(GND)的一条通路。这条通路可以是直接连接到 GND,也可以是通过电阻连接到 GND。建立这样的连接通路会在耳机检测芯片上造成电平变化(上升沿或下降沿),而这实际上就是一个中断信号。耳机检测芯片接收到这个中断后,会对连接到按键的芯片引脚上的电平进行 ADC 采样,再将得到的数值与芯片内存储的各按键值(KEY_VOLUMEUP、KEY_VOLUMEDOWN、KEY_MEDIA、KEY_VOICECOMMAND)进行对比,如果有符合的键值,则向 SoC 芯片发送一个中断,同时发送该键值,如果没有找到匹配的键值,自然也就不会上报了。

我们可以通过 /proc/interrupts 节点来查看 SoC 芯片是否收到了中断。比如可以像下方这样查看 ts3a227e 发送的中断数,如果按下“音量-”按键后中断计数没有增加,那么就说明耳机检测芯片确实没有向 SoC 芯片发出中断:

9d98e0c0b363538200dc2f12c487c490.png

耳机按键分压电路模型类似于下图:

android耳机上报流程,Android系统中耳机按键键值上报不正确 解决过程_第1张图片

之所以 2 款耳机的中间键被按下时都可以得到正确的响应,是因为大部分耳机的中间键都是直接接地的,按键被按下时对应的电平都是 0V。具体电路类似下图:

android耳机上报流程,Android系统中耳机按键键值上报不正确 解决过程_第2张图片

综上所述,各键值与各电压值是对应的,这个问题的本质实际上是底层驱动检测到了错误的电压继而上报

你可能感兴趣的:(android耳机上报流程)