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 耳机线控的功能 耳机线控是一种很好用,并且能提升用户体验的功能.可以用来实现一些常用和基本的功能.比如:实现音乐播 ...
随机推荐
- 分析 ThreadLocal 内存泄漏问题
ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用 ThreadLocal,就可能会导 ...
- Mac OS安装git
mac系统在AppStore里下载最新的Xcode,目前最新版本是Version 8.3.1 (8E1000a), 由于最新版的Xcode里已集成了git,所以下载后可直接在终端使用git了.
- burpsuite扩展集成sqlmap插件
通常我们在使用sqlmap测试SQL注入问题的时候会先使用burpsuite来抓包,然后交给sqlmap进行扫描,此操作略显繁琐. 为了避免这种繁琐的重复操作可以将sqlmap以插件的方式集成到bur ...
- Mac OS X 下安装使用 Docker
它依赖于 LXC(Linux Container),能从网络上获得配置好的 Linux 镜像,非常容易在隔离的系统中运行自己的应用.也因为它的底层核心是个 LXC,所以在 Mac OS X 下需要在 ...
- delphi 学习笔记的例子
由于360改变了共享策略,导致之前的共享连接不能使用 重新共享了下. http://yunpan.cn/cgS2DBRT572jy (提取码:1eda)
- Vue2键盘事件:keydown/keyup...
Vue2键盘事件:keydown/keyup... 1.使用 <!DOCTYPE html> <html> <head> <title></tit ...
- pip升级Python程序包
列出当前安装的包: pip list 列出可升级的包: pip list --outdate 升级一个包: pip install --upgrade requests // mac,linux,un ...
- c#中日期格式化
c#的日期格式化比较简单,在ToString中设置日期格式即可 DateTime.Now.ToLocalTime().ToString("yyyy_MM_dd_hh_mm_ss") ...
- RelativeLayout.LayoutParams
通过id设置相对兄弟元素对齐. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android&qu ...
- JAVA-数据库之添加记录
相关资料:<21天学通Java Web开发> 添加记录1.使用语句对象Statement的executeUpdate()方法可以很方便地实现添加记录.2.只需要在executUpdae() ...