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
<bool name="config_useDevInputEventForAudioJack">true</bool> 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 耳机插入过程分析的更多相关文章

  1. Android 耳机插入过程分析 (AudioManager部分)

    接上一篇,记录audioManager对耳机插入的操作 https://www.cnblogs.com/helloworldtoyou/p/9868890.html 主要是发送广播,另外更新音频通路 ...

  2. 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?

    腾讯优测是专业的移动自动化测试平台,提供多维度的自动化测试服务,让测试更简单! 近期有报道称,澳大利亚悉尼市新某大学的一名男生在课堂上看电影,不料耳机没有插好,变成了现场直播... 如果你认为耳机没插 ...

  3. Android -- 检测耳机插入状态

    原理                                                                                    其实android系统在耳机 ...

  4. 联想Y50耳机插入耳机孔后没有声音解决办法

    症状:博主本子Y50,前阵子关机时,提示win10要下载更新并安装,开机后发现将耳机插入耳机孔后死活听不到声音(笔记本自带的音响有声音).期间怀疑过耳机坏了的问题,检查过耳机在手机上能正常播放声音.最 ...

  5. Android 批量插入数据到SQLite数据库

    Android中在sqlite插入数据的时候默认一条语句就是一个事务,因此如果存在上万条数据插入的话,那就需要执行上万次插入操作,操作速度可想而知.因此在Android中插入数据时,使用批量插入的方式 ...

  6. android 语言切换过程分析

    android 语言切换过程分析 2014-02-27 18:13 1207人阅读 评论(0) 收藏 举报 语言切换android语言切换android改变语言 最近在看一个bug,系统切换语言后,本 ...

  7. Android批量插入数据到SQLite数据库

    Android中在sqlite插入数据的时候默认一条语句就是一个事务,因此如果存在上万条数据插入的话,那就需要执行上万次插入操作,操作速度可想而知.因此在Android中插入数据时,使用批量插入的方式 ...

  8. iOS 检测耳机插入/拔出

    http://www.verydemo.com/demo_c134_i28481.html 开发过程中录音和播放这块碰到了一些问题,麻烦的主要有三个: 检测是否有声音输入设备 当有多个声音输出设备时, ...

  9. MTK Android 耳机线控的实现方法

    android 耳机线控的实现方法 keycodeonkeydownkeyevent 耳机线控的功能 耳机线控是一种很好用,并且能提升用户体验的功能.可以用来实现一些常用和基本的功能.比如:实现音乐播 ...

随机推荐

  1. 分布式缓存Memcache和Redis

    引言 针对于如今计算机的CPU和网络设施,相应用程序来说,运行效率的瓶颈.已经不是代码的长度(实现同一个功能)和带宽了,而是,代码訪问资源的过程.即:让我们的程序慢下来的罪魁祸首就是IO操作. 程序从 ...

  2. android 去掉标题栏、状态栏、横屏

    // 去掉标题栏 supportRequestWindowFeature(Window.FEATURE_NO_TITLE); // 全屏.隐藏状态栏 getWindow().setFlags(Wind ...

  3. Redis source code analysis

    http://zhangtielei.com/posts/blog-redis-dict.html http://zhangtielei.com/assets/photos_redis/redis_d ...

  4. android alipay

    "java.security.spec.InvalidKeySpecException" KeyFactory keyFactory =KeyFactory.getInstance ...

  5. mybatis使用注解往postgresql数据库表insert数据[主键自增]的写法

    建表SQL: DROP TABLE IF EXISTS person; CREATE TABLE person( person_id serial PRIMARY KEY NOT NULL, pers ...

  6. uboot之第一阶段

    U-boot的启动一般分为两个阶段,现在我们先将第一阶段. 在此之前,我们先了解一下uboot的目录结构,各个文件夹是什么作用. 如果连各个文件夹是干什么的都不清楚就开始移植剪裁,势必会和我刚拿到开发 ...

  7. 代码重定位和位置无关码——运行于nor flash

    通过前面的学习,我们知道,把可执行程序从一个位置复制到另一个位置的过程叫做重定位. 现在有两种方式,第一种是只重定位data段到内存(sdram),为什么需要重定位?因为有些flash的写操作,不是简 ...

  8. tomcat8.5性能优化

    主要是按照两篇文章,部分参数因适配Tomcat8.5进行了调整 一.有关 JAVA_OPTS http://www.open-open.com/lib/view/open1401931407228.h ...

  9. 如何在线程中获取spring 管理的bean

    转载自:https://my.oschina.net/skyline520/blog/181158?fromerr=GjtR6Wec spring xml中定义 <!--spring 工具类-- ...

  10. How Not to Crash #2: Mutation Exceptions 可变异常(不要枚举可变的集合)

    How Not to Crash #2: Mutation Exceptions 可变异常html, body {overflow-x: initial !important;}html { font ...