Android 耳机插入过程分析 (AudioManager部分)
接上一篇,记录audioManager对耳机插入的操作
https://www.cnblogs.com/helloworldtoyou/p/9868890.html
主要是发送广播,另外更新音频通路
初始化:
10-29 12:50:39.542 1400 1400 I SystemServer: StartAudioService
10-29 12:50:39.542 1400 1400 I SystemServiceManager: Starting com.android.server.audio.AudioService$Lifecycle
10-29 12:50:39.587 1400 1400 D AudioService: Master mono false
10-29 12:50:39.589 1400 1400 D AudioService: Master mute false, user=0
10-29 12:50:39.592 1400 1400 D AudioService: Mic mute false, user=0
10-29 12:50:39.684 1400 1400 D SystemServerTiming: StartAudioService took to complete: 142ms
10-29 12:50:40.614 1400 1706 D AudioService: Touch exploration enabled=false stream override delay is now 0 ms
10-29 12:50:40.614 1400 1706 D AudioService: Accessibility volume enabled = false
10-29 12:50:41.702 1400 1946 D AudioService: Volume policy changed: VolumePolicy[volumeDownToEnterSilent=true,volumeUpToExitSilent=true,doNotDisturbWhenSilent=true,vibrateToSilentDebounce=400]
10-29 12:50:41.802 1400 1621 D AudioService: Volume controller: VolumeController(android.os.BinderProxy@9c596d8,mVisible=false)
10-29 12:50:42.217 1400 1400 D AudioService: Master mono false
10-29 12:50:42.225 1400 1400 D AudioService: Master mute false, user=0
10-29 12:50:42.228 1400 1400 D AudioService: Mic mute false, user=0
插入:
11-07 11:39:55.551 2349 2349 I AudioService: setWiredDeviceConnectionState(1 nm: addr:)
11-07 11:39:55.552 2349 2349 I AudioService: setWiredDeviceConnectionState(1 nm: addr:)
11-07 11:39:55.552 2349 3588 I AudioService: onSetWiredDeviceConnectionState(dev:4 state:1 address: deviceName: caller: android);
11-07 11:39:55.552 2349 3588 I AudioService: handleDeviceConnection(true dev:4 address: name:)
11-07 11:39:55.552 2349 3588 I AudioService: deviceKey:0x4:
11-07 11:39:55.552 2349 3588 I AudioService: deviceSpec:null is(already)Connected:false
11-07 11:39:55.593 2349 3588 I AudioService: sendDeviceConnectionIntent(dev:0x4 state:0x1 address: name:);
11-07 11:39:55.594 2349 3588 I AudioService: updateAudioRoutes MAIN_HEADSET
11-07 11:39:55.594 2349 3588 I AudioService: updateAudioRoutes connType != 0, state: 1
11-07 11:39:55.594 2349 3588 I AudioService: updateAudioRoutes connType MSG_REPORT_NEW_ROUTES
11-07 11:39:55.594 2349 3588 I AudioService: onSetWiredDeviceConnectionState(dev:80000010 state:1 address: deviceName: caller: android);
11-07 11:39:55.594 2349 3588 I AudioService: handleDeviceConnection(true dev:80000010 address: name:)
11-07 11:39:55.594 2349 3588 I AudioService: deviceKey:0x80000010:
11-07 11:39:55.594 2349 3588 I AudioService: deviceSpec:null is(already)Connected:false
11-07 11:39:55.610 2349 3588 I AudioService: sendDeviceConnectionIntent(dev:0x80000010 state:0x1 address: name:);
11-07 11:39:55.610 2349 3588 I AudioService: updateAudioRoutes Liutao
11-07 11:39:55.611 2349 3588 I AudioService: onAccessoryPlugMediaUnmute newDevice=4 [headset]
11-07 11:39:55.611 2349 3588 I AudioService: mAudioHandler 5060, N: 3
11-07 11:39:55.618 2349 3588 I AudioService: onAccessoryPlugMediaUnmute newDevice=-2147483632 [-2147483632]
拔出;
11-07 11:41:08.165 2349 2349 I AudioService: setWiredDeviceConnectionState(0 nm: addr:)
11-07 11:41:08.168 2349 2349 I AudioService: setWiredDeviceConnectionState(0 nm: addr:)
11-07 11:41:08.870 2349 3588 I AudioService: onSetWiredDeviceConnectionState(dev:4 state:0 address: deviceName: caller: android);
11-07 11:41:08.876 2349 3588 I AudioService: handleDeviceConnection(false dev:4 address: name:)
11-07 11:41:08.876 2349 3588 I AudioService: deviceKey:0x4:
11-07 11:41:08.877 2349 3588 I AudioService: deviceSpec:[type:0x4 name: address:] is(already)Connected:true
11-07 11:41:08.885 2349 3588 I AudioService: sendDeviceConnectionIntent(dev:0x4 state:0x0 address: name:);
11-07 11:41:08.887 2349 3588 I AudioService: updateAudioRoutes MAIN_HEADSET
11-07 11:41:08.887 2349 3588 I AudioService: updateAudioRoutes connType != 0, state: 0
11-07 11:41:08.887 2349 3588 I AudioService: updateAudioRoutes connType MSG_REPORT_NEW_ROUTES
11-07 11:41:08.887 2349 3588 I AudioService: mAudioHandler 5060, N: 3
11-07 11:41:08.914 2349 3588 I AudioService: onSetWiredDeviceConnectionState(dev:80000010 state:0 address: deviceName: caller: android);
11-07 11:41:08.914 2349 3588 I AudioService: handleDeviceConnection(false dev:80000010 address: name:)
11-07 11:41:08.914 2349 3588 I AudioService: deviceKey:0x80000010:
11-07 11:41:08.914 2349 3588 I AudioService: deviceSpec:[type:0x80000010 name: address:] is(already)Connected:true
11-07 11:41:08.918 2349 3588 I AudioService: sendDeviceConnectionIntent(dev:0x80000010 state:0x0 address: name:);
frameworks\base\media\java\android\media\AudioManager.java
public void setWiredDeviceConnectionState(int type, int state, String address, String name) {
final IAudioService service = getService();
try {
service.setWiredDeviceConnectionState(type, state, address, name,
mApplicationContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
frameworks\base\services\core\java\com\android\server\audio\AudioService.java
public void setWiredDeviceConnectionState(int type, int state, String address, String name,
String caller) {
synchronized (mConnectedDevices) {
if (DEBUG_DEVICES) {
Slog.i(TAG, "setWiredDeviceConnectionState(" + state + " nm: " + name + " addr:"
+ address + ")");
}
int delay = checkSendBecomingNoisyIntent(type, state, AudioSystem.DEVICE_NONE);
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
0 /* arg1 unused */,
0 /* arg2 unused */,
new WiredDeviceConnectionState(type, state, address, name, caller),
delay);
}
}
frameworks\base\services\core\java\com\android\server\audio\AudioService.java
private void queueMsgUnderWakeLock(Handler handler, int msg,
int arg1, int arg2, Object obj, int delay) {
final long ident = Binder.clearCallingIdentity();
// Always acquire the wake lock as AudioService because it is released by the
// message handler.
mAudioEventWakeLock.acquire();
Binder.restoreCallingIdentity(ident);
sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
}
private static void sendMsg(Handler handler, int msg,
int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {
if (existingMsgPolicy == SENDMSG_REPLACE) {
handler.removeMessages(msg);
} else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
return;
}
synchronized (mLastDeviceConnectMsgTime) {
long time = SystemClock.uptimeMillis() + delay;
handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
if (msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE ||
msg == MSG_SET_A2DP_SRC_CONNECTION_STATE ||
msg == MSG_SET_A2DP_SINK_CONNECTION_STATE) {
mLastDeviceConnectMsgTime = time;
}
}
}
private class AudioHandler extends Handler {
case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
{ WiredDeviceConnectionState connectState =
(WiredDeviceConnectionState)msg.obj;
mWiredDevLogger.log(new WiredDevConnectEvent(connectState));
onSetWiredDeviceConnectionState(connectState.mType, connectState.mState,
connectState.mAddress, connectState.mName, connectState.mCaller);
mAudioEventWakeLock.release();
}
break;
private void onSetWiredDeviceConnectionState(int device, int state, String address,
String deviceName, String caller) {
if (DEBUG_DEVICES) {
//打印结果AudioService: onSetWiredDeviceConnectionState(dev:8 state:1 address: deviceName: caller: android);
Slog.i(TAG, "onSetWiredDeviceConnectionState(dev:" + Integer.toHexString(device)
+ " state:" + Integer.toHexString(state)
+ " address:" + address
+ " deviceName:" + deviceName
+ " caller: " + caller + ");");
}
synchronized (mConnectedDevices) {
if ((state == 0) && ((device & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0)) {
setBluetoothA2dpOnInt(true, "onSetWiredDeviceConnectionState state 0");
}
// 打印AudioService: handleDeviceConnection(true dev:8 address: name:)
if (!handleDeviceConnection(state == 1, device, address, deviceName)) {
// change of connection state failed, bailout
return;
}
if (state != 0) {
if ((device & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0) {
setBluetoothA2dpOnInt(false, "onSetWiredDeviceConnectionState state not 0");
}
if ((device & mSafeMediaVolumeDevices) != 0) {
sendMsg(mAudioHandler,
MSG_CHECK_MUSIC_ACTIVE,
SENDMSG_REPLACE,
0,
0,
caller,
MUSIC_ACTIVE_POLL_PERIOD_MS);
}
// Television devices without CEC service apply software volume on HDMI output
if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
checkAllFixedVolumeDevices();
if (mHdmiManager != null) {
synchronized (mHdmiManager) {
if (mHdmiPlaybackClient != null) {
mHdmiCecSink = false;
mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
}
}
}
}
} else {
if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
if (mHdmiManager != null) {
synchronized (mHdmiManager) {
mHdmiCecSink = false;
}
}
}
}
// 发送耳机插入的广播
sendDeviceConnectionIntent(device, state, address, deviceName);
// 更新音频通路
updateAudioRoutes(device, state);
}
}
private void sendDeviceConnectionIntent(int device, int state, String address,
String deviceName) {
if (DEBUG_DEVICES) {
Slog.i(TAG, "sendDeviceConnectionIntent(dev:0x" + Integer.toHexString(device) +
" state:0x" + Integer.toHexString(state) + " address:" + address +
" name:" + deviceName + ");");
}
Intent intent = new Intent();
if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) {
intent.setAction(Intent.ACTION_HEADSET_PLUG);
intent.putExtra("microphone", 1);
} else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE ||
device == AudioSystem.DEVICE_OUT_LINE) {
intent.setAction(Intent.ACTION_HEADSET_PLUG);
intent.putExtra("microphone", 0);
} else if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
intent.setAction(Intent.ACTION_HEADSET_PLUG);
intent.putExtra("microphone",
AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_IN_USB_HEADSET, "")
== AudioSystem.DEVICE_STATE_AVAILABLE ? 1 : 0);
} else if (device == AudioSystem.DEVICE_IN_USB_HEADSET) {
if (AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_USB_HEADSET, "")
== AudioSystem.DEVICE_STATE_AVAILABLE) {
intent.setAction(Intent.ACTION_HEADSET_PLUG);
intent.putExtra("microphone", 1);
} else {
// do not send ACTION_HEADSET_PLUG when only the input side is seen as changing
return;
}
} else if (device == AudioSystem.DEVICE_OUT_HDMI ||
device == AudioSystem.DEVICE_OUT_HDMI_ARC) {
configureHdmiPlugIntent(intent, state);
}
if (intent.getAction() == null) {
return;
}
intent.putExtra(CONNECT_INTENT_KEY_STATE, state);
intent.putExtra(CONNECT_INTENT_KEY_ADDRESS, address);
intent.putExtra(CONNECT_INTENT_KEY_PORT_NAME, deviceName);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
final long ident = Binder.clearCallingIdentity();
// 发送广播,上层可以通过接受广播来判断耳机的状态。
try {
ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
private void updateAudioRoutes(int device, int state)
{
int connType = 0;
if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) {
//Slog.i(TAG, "updateAudioRoutes MAIN_HEADSET");进入这里
connType = AudioRoutesInfo.MAIN_HEADSET;
} else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE ||
device == AudioSystem.DEVICE_OUT_LINE) {
connType = AudioRoutesInfo.MAIN_HEADPHONES;
} else if (device == AudioSystem.DEVICE_OUT_HDMI ||
device == AudioSystem.DEVICE_OUT_HDMI_ARC) {
connType = AudioRoutesInfo.MAIN_HDMI;
} else if (device == AudioSystem.DEVICE_OUT_USB_DEVICE||
device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
connType = AudioRoutesInfo.MAIN_USB;
}
synchronized (mCurAudioRoutes) {
if (connType != 0) {
int newConn = mCurAudioRoutes.mainType;
if (state != 0) {
newConn |= connType;
} else {
newConn &= ~connType;
}
if (newConn != mCurAudioRoutes.mainType) {
mCurAudioRoutes.mainType = newConn;
// 发送消息给Handler
sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
SENDMSG_NOOP, 0, 0, null, 0);
}
}
}
}
private class AudioHandler extends Handler {
public void handleMessage(Message msg) {
case MSG_REPORT_NEW_ROUTES: {
int N = mRoutesObservers.beginBroadcast();
if (N > 0) {
AudioRoutesInfo routes;
synchronized (mCurAudioRoutes) {
routes = new AudioRoutesInfo(mCurAudioRoutes);
}
while (N > 0) {
N--;
IAudioRoutesObserver obs = mRoutesObservers.getBroadcastItem(N);
try {
obs.dispatchAudioRoutesChanged(routes);
} catch (RemoteException e) {
}
}
}
mRoutesObservers.finishBroadcast();
observeDevicesForStreams(-1);
break;
}
frameworks\base\media\java\android\media\MediaRouter.java
final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() {
@Override
public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
mHandler.post(new Runnable() {
@Override public void run() {
updateAudioRoutes(newRoutes);
}
});
}
};
Android 耳机插入过程分析 (AudioManager部分)的更多相关文章
- Android 耳机插入过程分析
Android 耳机插入过程分析 参考链接: https://www.jianshu.com/p/d82a8dabb3e7 初始化: 10-26 07:40:43.932 1414 1414 I Sy ...
- 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
腾讯优测是专业的移动自动化测试平台,提供多维度的自动化测试服务,让测试更简单! 近期有报道称,澳大利亚悉尼市新某大学的一名男生在课堂上看电影,不料耳机没有插好,变成了现场直播... 如果你认为耳机没插 ...
- Android -- 检测耳机插入状态
原理 其实android系统在耳机 ...
- 联想Y50耳机插入耳机孔后没有声音解决办法
症状:博主本子Y50,前阵子关机时,提示win10要下载更新并安装,开机后发现将耳机插入耳机孔后死活听不到声音(笔记本自带的音响有声音).期间怀疑过耳机坏了的问题,检查过耳机在手机上能正常播放声音.最 ...
- Android 批量插入数据到SQLite数据库
Android中在sqlite插入数据的时候默认一条语句就是一个事务,因此如果存在上万条数据插入的话,那就需要执行上万次插入操作,操作速度可想而知.因此在Android中插入数据时,使用批量插入的方式 ...
- android 语言切换过程分析
android 语言切换过程分析 2014-02-27 18:13 1207人阅读 评论(0) 收藏 举报 语言切换android语言切换android改变语言 最近在看一个bug,系统切换语言后,本 ...
- Android批量插入数据到SQLite数据库
Android中在sqlite插入数据的时候默认一条语句就是一个事务,因此如果存在上万条数据插入的话,那就需要执行上万次插入操作,操作速度可想而知.因此在Android中插入数据时,使用批量插入的方式 ...
- iOS 检测耳机插入/拔出
http://www.verydemo.com/demo_c134_i28481.html 开发过程中录音和播放这块碰到了一些问题,麻烦的主要有三个: 检测是否有声音输入设备 当有多个声音输出设备时, ...
- MTK Android 耳机线控的实现方法
android 耳机线控的实现方法 keycodeonkeydownkeyevent 耳机线控的功能 耳机线控是一种很好用,并且能提升用户体验的功能.可以用来实现一些常用和基本的功能.比如:实现音乐播 ...
随机推荐
- android笔记---百度地图api应用 (一)
package com.example.bdtest; import com.baidu.mapapi.MKEvent; import com.baidu.mapapi.MKPlanNode; imp ...
- kali64位 安装 adb
1,adb只有32位的 ,下载地址http://dl.dbank.com/c0umekbpxi# 2,下载解压,但是执行adb命令时,报./adb: error while loading shar ...
- 关于一点pthread_cond_t条件锁的思考以及实验
转:http://blog.csdn.net/aniao/article/details/5802015 APUE上,关于条件锁.其中有这么几条总结: 1.使用条件锁前必须先锁住对应的互斥锁. 2.条 ...
- MyBatisBatchItemWriter Cannot change the ExecutorType when there is an existing transaction
但凡使用mybatis,同时与spring集成使用时,接下来要说的这个问题是躲不了的.众所周知,mybatis的SqlSessionFactory在获取一个SqlSession时使用默认Executo ...
- ARKit从入门到精通(11)-ARKit开发常见问题及解决方案
转载请注明出处:ARKit从入门到精通(11)-ARKit开发常见问题及解决方案 本文主要介绍ARKit开发过程中一些常见问题 1.ARKit框架无法导入问题 2.ARKit运行黑屏或者白屏问题:Un ...
- in linux system of ftp command
一口流利的english title 常用命令: ftp baidu.com ftp>ls ftp>cd directory ftp>get filename 下载 ftp>p ...
- 【转】Java计算文件的hash值
原文地址:http://blog.csdn.net/qq_25646191/article/details/78863110 如何知道一个文件是否改变了呢?当然是用比较文件hash值的方法,文件has ...
- Java之线程状态
Java线程有6种状态: 1.New(新生),使用new Thread(r)创建一个新线程时,该线程处于新生状态,新生状态会为线程的执行做一些准备. 2.Runnable(可执行),调用线程的star ...
- [培训]keysight培训
DDR DDR->DDR2->DDR3->DDR4->DDR5->HBM, LPDDR(low power DDR)
- LeetCode之Decode Ways
A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' - ...