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 耳机线控的功能 耳机线控是一种很好用,并且能提升用户体验的功能.可以用来实现一些常用和基本的功能.比如:实现音乐播 ...
随机推荐
- Cowboy实例
这个例子主要是用cocos2d-x引擎自带的资源 cocos2d-x-2.2.2\samples\Cpp\TestCpp\Resources\armature 新建工程之后 #include &quo ...
- Linux系统/boot目录破损无法启动怎么办
linux系统中的/boot目录存放着系统开机所需要的各种文件,其中包含内核.开机菜单及所需配置文件等等.但是当不小心删除了/boot目录里的某些文件或者干脆整个/boot目录都不见了的情况下,该如何 ...
- iOS开发transform的使用
// // ViewController.m // 18-transform的使用 #import "ViewController.h" @interface ViewCont ...
- 【转】(五)unity4.6Ugui中文教程文档-------概要-UGUI Interaction Components
原创至上,移步请戳:(五)unity4.6Ugui中文教程文档-------概要-UGUI Interaction Components 4.Interaction Components 本节涵盖了处 ...
- windows开通https服务
一.申请ssl证书 建议1个免费的ssl证书申请网站,已测试,可用 1.注册https://login.wosign.com/reg.html?rf=buy 2.邮箱验证登录后访问https://bu ...
- 使用 IDEA 开发工具(版本为 IntelliJ IDEA 14.1.4)打可执行jar包的操作步骤
声明:教程演示使用的开发工具的版本是 IntelliJ IDEA 14.1.4. 1.选择IDEA开发工具菜单栏 File --> Project Structure,弹出如下窗口,在左侧的列表 ...
- hive的row_number()函数
hive的row_number()函数 功能 用于分组,比方说依照uuid分组 组内可以依照某个属性排序,比方说依照uuid分组,组内按照imei排序 语法为row_number() over (pa ...
- ftell函数使用注意事项
ftell函数的原型如下: long ftell(FILE *stream); 主要功能是获取FILE指针在当前文件中的位置. 但在使用文本模式打开文件时,ftell函数返回值不一定跟FILE文件指针 ...
- Django-管理站点重写admin模板
参考链接:https://blog.csdn.net/u013378306/article/details/79023242 使用Django的admin管理工具,可以快速的构建自己的管理平台,使用D ...
- 【Java】自动类型转换规则
自动类型转换遵循下面的规则: 若参与运算的数据类型不同,则先转换成同一类型,然后进行运算. 转换按数据长度增加的方向进行,以保证精度不降低.例如int型和long型运算时,先把int量转成long型后 ...