Android 耳机插入过程分析

参考链接:

https://www.jianshu.com/p/d82a8dabb3e7

初始化:

10-26 07:40:43.932 1414 1414 I SystemServer: StartWiredAccessoryManager

10-26 07:40:43.936 1414 1414 W WiredAccessoryManager: This kernel does not have usb audio support

10-26 07:40:43.937 1414 1414 W WiredAccessoryManager: This kernel does not have HDMI audio support

10-26 07:40:43.937 1414 1414 W WiredAccessoryManager: This kernel does not have DP audio support

10-26 07:40:43.937 1414 1414 D SystemServerTiming: StartWiredAccessoryManager took to complete: 6ms

10-26 07:40:46.375 1414 1414 V WiredAccessoryManager: notifyWiredAccessoryChanged: when=0 bits= mask=54

10-26 07:40:46.375 1414 1414 V WiredAccessoryManager: newName=h2w newState=0 headsetState=0 prev headsetState=0

10-26 07:40:46.375 1414 1414 E WiredAccessoryManager: No state change.

10-26 07:40:46.375 1414 1414 V WiredAccessoryManager: init()

耳机插入

10-26 11:26:48.552 1414 1684 V WiredAccessoryManager: notifyWiredAccessoryChanged: when=13604972191000 bits=SW_HEADPHONE_INSERT SW_MICROPHONE_INSERT mask=94

10-26 11:26:48.552 1414 1684 V WiredAccessoryManager: newName=h2w newState=1 headsetState=1 prev headsetState=0

10-26 11:26:48.554 1414 1684 I WiredAccessoryManager: MSG_NEW_DEVICE_STATE

10-26 11:26:48.555 1414 1414 V WiredAccessoryManager: headsetName: connected

耳机拔出

10-26 11:26:53.134 1414 1684 V WiredAccessoryManager: notifyWiredAccessoryChanged: when=13609554723000 bits= mask=94

10-26 11:26:53.134 1414 1684 V WiredAccessoryManager: newName=h2w newState=0 headsetState=0 prev headsetState=1

10-26 11:26:53.136 1414 1684 I WiredAccessoryManager: MSG_NEW_DEVICE_STATE

10-26 11:26:53.137 1414 1414 V WiredAccessoryManager: headsetName: disconnected

高通读取外设插入方式有两种:

1. UEvent:

读取/sys/class/switch/h2w/state文件等状态

2. InputEvent:

读取/dev/input/event

通过属性值,判断采用何种方式。

frameworks\base\core\res\res\values\config.xml

true

getevent

add device 1: /dev/input/event7

name: "msm8953-snd-card-mtp Button Jack"

add device 2: /dev/input/event6

name: "msm8953-snd-card-mtp Headset Jack"

add device 3: /dev/input/event2

name: "goodix-ts"

add device 4: /dev/input/event3

name: "hbtp_vm"

could not get driver version for /dev/input/mouse0, Not a typewriter

add device 5: /dev/input/event0

name: "qpnp_pon"

could not get driver version for /dev/input/mice, Not a typewriter

add device 6: /dev/input/event1

name: "tsu6721"

add device 7: /dev/input/event4

name: "keyremap_virtual"

add device 8: /dev/input/event5

name: "gpio-keys"

插入:

/dev/input/event6: 0005 0002 00000001

/dev/input/event6: 0005 0004 00000001

/dev/input/event6: 0005 0007 00000001

/dev/input/event6: 0000 0000 00000000

拔出:

/dev/input/event6: 0005 0002 00000000

/dev/input/event6: 0005 0004 00000000

/dev/input/event6: 0005 0007 00000000

/dev/input/event6: 0000 0000 00000000

getevent -l

/dev/input/event6: EV_SW SW_HEADPHONE_INSERT 00000001

/dev/input/event6: EV_SW SW_MICROPHONE_INSERT 00000001

/dev/input/event6: EV_SW SW_JACK_PHYSICAL_INS 00000001

/dev/input/event6: EV_SYN SYN_REPORT 00000000

/dev/input/event6: EV_SW SW_HEADPHONE_INSERT 00000000

/dev/input/event6: EV_SW SW_MICROPHONE_INSERT 00000000

/dev/input/event6: EV_SW SW_JACK_PHYSICAL_INS 00000000

/dev/input/event6: EV_SYN SYN_REPORT 00000000

代码跟踪

frameworks\base\services\core\java\com\android\server\input\InputManagerService.java

mUseDevInputEventForAudioJack =

context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);

if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {

mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,

switchMask);

}

frameworks\base\services\core\java\com\android\server\WiredAccessoryManager.java

public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask) {

if (LOG) Slog.v(TAG, "notifyWiredAccessoryChanged: when=" + whenNanos

+ " bits=" + switchCodeToString(switchValues, switchMask)

+ " mask=" + Integer.toHexString(switchMask));

synchronized (mLock) {

int headset;

mSwitchValues = (mSwitchValues & ~switchMask) | switchValues;

switch (mSwitchValues &

(SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_LINEOUT_INSERT_BIT)) {

case 0:

headset = 0;

break;

case SW_HEADPHONE_INSERT_BIT:

headset = BIT_HEADSET_NO_MIC;

break;

case SW_LINEOUT_INSERT_BIT:

headset = BIT_LINEOUT;

break;

case SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT:

headset = BIT_HEADSET;

break;

case SW_MICROPHONE_INSERT_BIT:

headset = BIT_HEADSET;

break;

default:

headset = 0;

break;

}

updateLocked(NAME_H2W,

(mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) | headset);

}

}

private void updateLocked(String newName, int newState) {

// Retain only relevant bits

int headsetState = newState & SUPPORTED_HEADSETS;

int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG;

int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL;

int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT);

boolean h2wStateChange = true;

boolean usbStateChange = true;

if (LOG) Slog.v(TAG, "newName=" + newName

+ " newState=" + newState

+ " headsetState=" + headsetState

+ " prev headsetState=" + mHeadsetState);

if (mHeadsetState == headsetState) {

Log.e(TAG, "No state change.");

return;

}

// reject all suspect transitions: only accept state changes from:

// - a: 0 headset to 1 headset

// - b: 1 headset to 0 headset

if (h2w_headset == (BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) {

Log.e(TAG, "Invalid combination, unsetting h2w flag");

h2wStateChange = false;

}

// - c: 0 usb headset to 1 usb headset

// - d: 1 usb headset to 0 usb headset

if (usb_headset_anlg == BIT_USB_HEADSET_ANLG && usb_headset_dgtl == BIT_USB_HEADSET_DGTL) {

Log.e(TAG, "Invalid combination, unsetting usb flag");

usbStateChange = false;

}

if (!h2wStateChange && !usbStateChange) {

Log.e(TAG, "invalid transition, returning ...");

return;

}

mWakeLock.acquire();

// 发送数据给

Log.i(TAG, "MSG_NEW_DEVICE_STATE");

Message msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState,

mHeadsetState, "");

mHandler.sendMessage(msg);

mHeadsetState = headsetState;

}

private final Handler mHandler = new Handler(Looper.myLooper(), null, true) {

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

case MSG_NEW_DEVICE_STATE:

setDevicesState(msg.arg1, msg.arg2, (String)msg.obj);

mWakeLock.release();

break;

case MSG_SYSTEM_READY:

onSystemReady();

mWakeLock.release();

break;

}

}

};

private void setDevicesState(

int headsetState, int prevHeadsetState, String headsetName) {

synchronized (mLock) {

int allHeadsets = SUPPORTED_HEADSETS;

for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {

if ((curHeadset & allHeadsets) != 0) {

setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName);

allHeadsets &= ~curHeadset;

}

}

}

}

private void setDeviceStateLocked(int headset,

int headsetState, int prevHeadsetState, String headsetName) {

if ((headsetState & headset) != (prevHeadsetState & headset)) {

int outDevice = 0;

int inDevice = 0;

int state;

if ((headsetState & headset) != 0) {

state = 1;

} else {

state = 0;

}

if (headset == BIT_HEADSET) {

outDevice = AudioManager.DEVICE_OUT_WIRED_HEADSET;

inDevice = AudioManager.DEVICE_IN_WIRED_HEADSET;

} else if (headset == BIT_HEADSET_NO_MIC){

outDevice = AudioManager.DEVICE_OUT_WIRED_HEADPHONE;

} else if (headset == BIT_LINEOUT){

outDevice = AudioManager.DEVICE_OUT_LINE;

} else if (headset == BIT_USB_HEADSET_ANLG) {

outDevice = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET;

} else if (headset == BIT_USB_HEADSET_DGTL) {

outDevice = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;

} else if (headset == BIT_HDMI_AUDIO) {

outDevice = AudioManager.DEVICE_OUT_HDMI;

} else {

Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);

return;

}

if (LOG) {

Slog.v(TAG, "headsetName: " + headsetName +

(state == 1 ? " connected" : " disconnected"));

}

// 发送给audio manager.

if (outDevice != 0) {

mAudioManager.setWiredDeviceConnectionState(outDevice, state, "", headsetName);

}

if (inDevice != 0) {

mAudioManager.setWiredDeviceConnectionState(inDevice, state, "", headsetName);

}

}

}

android耳机上报流程,Android 耳机插入过程分析相关推荐

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

    [问题现象] 根据测试组同事反馈:在我们的设备上使用 JBL 品牌某款带有 3 个按键的有线耳机时,按下"音量+"键时设备会减小音量而不是增加音量,按下"音量-" ...

  2. android p 权限流程,Android native 权限控制流程

    关联文章: 前言: 在 Android Runtime Permission 详解 中详细的说明了permission 在Android 6.0 前后的区别,对于M 以后应用可以通过checkPerm ...

  3. android屏幕适配流程,Android屏幕适配姿势

    GitHub地址 为什么要屏幕适配? device_framentation.png 统计 碎片化 品牌机型碎片化 屏幕尺寸碎片化 操作系统碎片化 为了保证用户获得一致的用户体验效果,使得某一元素在A ...

  4. android wifi wps 流程,android中WiFi wps连接方式

    Android 个人热点 wps方式连接流程 android手机开启个人热点时,可以选择WPS连接方式 个人热点端 连接端 当个人热点端选择按钮时,连接端只需要点击WPS按钮即可连接:当个人热点端选择 ...

  5. android zygote启动流程,Android zygote启动流程详解

    对zygote的理解 在Android系统中,zygote是一个native进程,是所有应用进程的父进程.而zygote则是Linux系统用户空间的第一个进程--init进程,通过fork的方式创建并 ...

  6. android otg 挂载流程,android USB OTG功能如何打开及实现

    1.检查HW原理图,确认是否支持OTG功能(vbus是否供上电,IDDIG pin链接是否正确) 2.若HW确认支持OTG功能,则按照如下方法分别打开USB OTG功能及实现挂载: 如何打开USB O ...

  7. android serviceconnection unbind流程,Android - Service Bind/Unbind 使用

    Service Bind/Unbind 使用方式 本文介绍了本地服务,也就是同一个进程内的服务,如何使用 Bind/Unbind 方式被 Activity 使用. 本文不涉及 AIDL 使用 Serv ...

  8. android avrcp处理流程,Android Bluetooth AVRCP

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? AVRCP(Audio/Video Remote Control Profile),即音频/视频远程控制规范. AVRC ...

  9. android serviceconnection unbind流程,Android unbindService 流程分析

    基于Android 6.0的源码剖析, 分析bind service的启动流程. /frameworks/base/core/java/android/app/ContextImpl.java /fr ...

最新文章

  1. CLR自定义菜单项(ToolStripItem)
  2. php的优化模块,php memcache模块优化配置详解
  3. html body background color,HTML Style backgroundColor用法及代码示例
  4. 什么是Google Play保护以及如何确保Android安全?
  5. 玩转oracle 11g(35):rman备份-参数文件spfile损坏恢复
  6. 物理史2000年来最豪华阵容也是最为精彩的对决!
  7. MyBatis:模糊查询的4种实现方式
  8. rtmp服务器 协议之同步
  9. ajax php 错误提示,php – jQuery AJAX错误处理
  10. Android开发之旅-Fragment和Activity之间onCreateOptionsMenu的联系
  11. 《算法设计与分析基础 第二版》pdf
  12. H5页面在自己APP中图标显示正常,接入钉钉请求.woff图标字体报错
  13. 写论文:证明非线性系统的稳定性
  14. 构建一个代号为1的聊天应用程序4
  15. Shell小技巧(一百零五)脚本中的空格小结
  16. 储能电源/移动电源专用升降压DC-DC方案PL9405
  17. OpenStack 启动虚拟机 Booting from Hard Disk
  18. mac 安装mysql 数据库
  19. 5 - 多元函数微分学
  20. 原创文章:使用Vuejs实现个人所得税功能,以及5000起点和3500起点之间的缴费变化兼容移动端

热门文章

  1. 工作的硬实力/软技巧
  2. java的基本概念:进制、单位、编码、数据类型、变量声明、ASCII码
  3. 机械键盘入门:教你如何正确选择机械键盘!学习游戏两不误
  4. 好看的个人网站源码_新手想建个人网站,都要注意哪些关于自助建站源码的坑?...
  5. 对话框不响应WM_KEYDOWN消息,可以通过重载BOOL PreTranslateMessage(MSG * pMsg)来实现
  6. java程序笑脸怎么打_我编写的JAVA程序为什么在编译执行后会先打出一个笑脸呢?...
  7. Linux下文件的压缩、解压缩、打包以及提取
  8. 网络不断电系统服务器ip,IP网络控制主机 T-7700N
  9. 大学生企业计算机应用能力需求调研,五个专业计算机能力需求调研分析论文
  10. 督查督办管理系统适合什么企业