Android adb shell dumpsys audio 信息查看分析详解
一、前言
Android 如果要分析当前设备的声音通道相关日志,
仅仅看AudioService的日志是看不到啥日志的,但是看整个audio关键字的日志又太多太乱了,
所以可以看一下系统提供的一个调试指令dumpsys audio 返回的信息进行定位分析,
里面主要包含了AudioService启动时间,当前设备的音频流指向,音频流的声音大小,音频外设的连接情况,音频播放记录,音频外设连接断开记录等等信息。
不同的Android 系统使用 dumpsys audio 命令返回的日志信息可能会有差异,
因为打印返回的信息就是AudioService.java里面打印显示的,
本文的示例讲解是以mtk方案的Android14日志信息进行讲解。
网上基本没有对dumpsys audio 日志信息进行分析的,有兴趣的可以收藏查看。
二、分析
1、简单示例和主要内容
本示例日志是设备连接蓝牙耳机后的dumpsys audio情况日志信息:
# dumpsys audio
[18:57:20]Events log: audio services lifecycle
[18:57:20]11-22 18:54:07:681 AudioService() //(1)AudioService 启动时间,大概可以推测出开机时间
[18:57:20]MediaFocusControl dump time: 6:57:22 PM //(2)执行dumpsys audio的时间
//(3)dumpsys audio最重要的内容,设备支持声音流情况
[18:57:20]Stream volumes (device: index)
[18:57:20]- STREAM_VOICE_CALL (aliased to: STREAM_MUSIC):
。。。
[18:57:20]- STREAM_SYSTEM (aliased to: STREAM_MUSIC):
。。。
[18:57:20]- STREAM_RING (aliased to: STREAM_MUSIC):
。。
//(4)基本是音频播放的情况,上面其他声音通道都是注释了以这个为标准
[18:57:20]- STREAM_MUSIC:
[18:57:20] Muted: false
[18:57:20] Muted Internally: false
[18:57:20] Min: 0 //声音范围
[18:57:20] Max: 15
[18:57:20] streamVolume:7 //当前声音大小
[18:57:20] Current: 2 (speaker): 7, 80 (bt_a2dp): 7, 400 (hdmi): 7, 40000000 (default): 7
[18:57:20] Devices: bt_a2dp(80) //当前声音通道,蓝牙
[18:57:20] Volume Group: music
[18:57:20]
[18:57:20]- STREAM_ALARM (aliased to: STREAM_MUSIC):
[18:57:20] Muted: false
[18:57:20] Muted Internally: false
[18:57:20] Min: 1
[18:57:20] Max: 7
[18:57:20] streamVolume:4
[18:57:20] Current: 2 (speaker): 4, 80 (bt_a2dp): 4, 400 (hdmi): 4, 40000000 (default): 4
[18:57:20] Devices: speaker(2), bt_a2dp(80)
[18:57:20] Volume Group: alarm
//其他声音通道比较少实用,比如铃声,通知等情况
[18:57:20]- STREAM_NOTIFICATION (aliased to: STREAM_MUSIC):
[18:57:20]- STREAM_BLUETOOTH_SCO:
[18:57:20]- STREAM_SYSTEM_ENFORCED (aliased to: STREAM_MUSIC):
[18:57:20]- STREAM_DTMF (aliased to: STREAM_MUSIC):
[18:57:20]- STREAM_TTS (aliased to: STREAM_MUSIC):
[18:57:20]- STREAM_ACCESSIBILITY (aliased to: STREAM_MUSIC):
[18:57:20]- STREAM_ASSISTANT (aliased to: STREAM_MUSIC):
。。。
//Volume Groups 不知道是干啥的,类型也是挺多的。
[18:57:20]Volume Groups (device: index)
[18:57:20]- VOLUME GROUP voice_call:
[18:57:20] Muted: false
[18:57:20] Min: 1
[18:57:20] Max: 7
[18:57:20] Current: 2 (speaker): 4, 80 (bt_a2dp): 7, 40000000 (default): 4
[18:57:20] Devices: bt_a2dp
[18:57:20] Streams: STREAM_VOICE_CALL
[18:57:20]- VOLUME GROUP system:
[18:57:20] Muted: false
[18:57:20] Min: 0
[18:57:20] Max: 100
[18:57:20] Current: 2 (speaker): 47, 80 (bt_a2dp): 7, 40000000 (default): 47
[18:57:20] Devices: bt_a2dp
[18:57:20] Streams: STREAM_SYSTEM
[18:57:20]- VOLUME GROUP ring:
[18:57:20]- VOLUME GROUP music:
[18:57:20]- VOLUME GROUP alarm:
[18:57:20]- VOLUME GROUP alarm:
[18:57:20]- VOLUME GROUP bluetooth_sco:
[18:57:20]- VOLUME GROUP enforced_audible:
[18:57:20]- VOLUME GROUP dtmf:
[18:57:20]- VOLUME GROUP accessibility:
[18:57:20]- VOLUME GROUP assistant:
[18:57:20]- VOLUME GROUP AUDIO_STREAM_REROUTING:
[18:57:20]- VOLUME GROUP AUDIO_STREAM_PATCH:
VOLUME GROUP类型的 Streams属性值都是指向上面的Stream volumes类型的。
[18:57:20]Audio routes:
[18:57:20] mMainType=0x0
//(5)当前连接蓝牙的设备名称,如果未连接蓝牙为null
[18:57:20] mBluetoothName=Xiaodu Portable Speaker
//(6)音频播放情况日志
[19:00:32]Events log: playback activity as reported through PlayerBase
//开机铃声
[19:00:32]11-22 18:54:09:789 new player piid:71 uid/pid:1000/745 type:android.media.SoundPool attr:AudioAttributes: usage=USAGE_ASSISTANCE_SONIFICATION content=CONTENT_TYPE_SONIFICATION flags=0x800 tags= bundle=null session:0
[19:00:33]11-22 18:54:10:837 new player piid:79 uid/pid:1000/1069 type:android.media.SoundPool attr:AudioAttributes: usage=USAGE_MEDIA content=CONTENT_TYPE_UNKNOWN flags=0x800 tags= bundle=null session:0
。。。
//音频文件播放+停止+播放+停止操作的日志
[19:00:33]11-22 18:58:37:956 player piid:103 event:started
[19:00:33]11-22 18:58:38:076 player piid:103 format update:FormatInfo{isSpatialized=false, channelMask=0x3, sampleRate=44100}
[19:00:33]11-22 18:58:38:175 player piid:103 event:device updated deviceId:5
[19:00:33]11-22 18:58:38:190 player piid:103 event:device updated deviceId:5
[19:00:33]11-22 18:58:42:920 player piid:103 event:paused
[19:00:33]11-22 19:00:24:155 player piid:103 event:started
[19:00:33]11-22 19:00:24:169 player piid:103 format update:FormatInfo{isSpatialized=false, channelMask=0x3, sampleRate=44100}
[19:00:33]11-22 19:00:24:204 player piid:103 event:device updated deviceId:5
[19:00:33]11-22 19:00:29:492 player piid:103 event:paused
//(7)当前连接的设备,这里是连接蓝牙耳机
[18:57:21] Connected devices:
[18:57:21] [DeviceInfo: type:0x80 (bt_a2dp) name:Xiaodu Portable Speaker addr:48:F3:F3:ED:78:AD codec: 1f000000 sensorUuid: 00000000-0000-0000-4254-48f3f3ed78ad disabled modes: {}]
[18:57:21]
//(8)如果是连接的usb有线耳机,另外一份日志拼过来的
[15:01:34] Connected devices:
[15:01:34] [DeviceInfo: type:0x4000000 (usb_headset) name:USB-Audio - USB Speaker Phone addr:card=4;device=0 codec: 0 sensorUuid: null disabled modes: {}]
//(9)连接蓝牙耳机、有线耳机等外设音箱的日志
[18:57:21]Events log: wired/A2DP/hearing aid device connection
。。。
[18:57:21]11-22 18:57:04:640 BT profile service: connecting HEARING_AID profile
[18:57:21]11-22 18:57:04:666 BT profile service: connecting A2DP profile
[18:57:21]11-22 18:57:09:875 msg: onBluetoothActiveDeviceChange state=2 addr=48:F3:F3:ED:78:AD prof=2 supprNoisy=true src=AudioService
[18:57:21]11-22 18:57:09:885 BT connected: addr=48:F3:F3:ED:78:AD profile=2 state=2 codec=AUDIO_FORMAT_SBC
[18:57:21]11-22 18:57:10:074 A2DP device addr=48:F3:F3:ED:78:AD now available
//上面可以看到蓝牙连接的时间记录
//(10)声音通道占用的日志
[18:57:21]Events log: force use (logged before setForceUse() is executed)
[18:57:21]11-22 18:54:07:774 setForceUse(FOR_DOCK, FORCE_DIGITAL_DOCK) due to readDockAudioSettings
。。。
[18:57:21]11-22 18:54:08:521 setForceUse(FOR_VIBRATE_RINGING, FORCE_NONE) due to muteRingerModeStreams() from u/pid:1000/745
。。。
//从最后一行日志看,最后是设置为蓝牙通道的
[18:57:21]11-22 18:57:09:897 setForceUse(FOR_MEDIA, FORCE_NONE) due to setBluetoothA2dpOn(true) from u/pid:1000/745 src:onSetBtActiveDevice
//(11)声音变化和通道情况
[18:57:21]Events log: volume changes (logged when command received by AudioService)
[18:57:21]11-22 18:57:09:885 VolumeStreamState.muteInternally(stream:STREAM_MUSIC, muted)
[18:57:21]11-22 18:57:10:053 setDeviceVolumeBehavior: dev:bt_a2dp addr:48:F3:F3:ED:78:AD behavior:DEVICE_VOLUME_BEHAVIOR_VARIABLE pack:com.android.bluetooth
[18:57:21]11-22 18:57:10:156 avrcpSupportsAbsoluteVolume addr=48:F3:F3:ED:78:AD support=false
[18:57:21]11-22 18:57:10:323 VolumeStreamState.muteInternally(stream:STREAM_MUSIC, unmuted)
//从上面日志看是蓝牙声音通道,STREAM_MUSIC 流
//(12)AudioSystemAdapter 不清楚是啥日志
[18:57:21]AudioSystemAdapter:
[18:57:21] last cache clear time: 11-22 18:57:10:110
[18:57:21] mDevicesForAttrCache:
[18:57:21] AudioAttributes: usage=USAGE_ASSISTANCE_SONIFICATION content=CONTENT_TYPE_UNKNOWN flags=0x800 tags= bundle=null forVolume: true stream: STREAM_SYSTEM(1)
[18:57:21] AudioDeviceAttributes: role:output type:bt_a2dp addr:48:F3:F3:ED:78:AD name: profiles:[] descriptors:[]
[18:57:21] AudioAttributes: usage=USAGE_ASSISTANCE_ACCESSIBILITY content=CONTENT_TYPE_UNKNOWN flags=0x800 tags= bundle=null forVolume: true stream: STREAM_ACCESSIBILITY(10)
[18:57:21] AudioDeviceAttributes: role:output type:bt_a2dp addr:48:F3:F3:ED:78:AD name: profiles:[] descriptors:[]
[18:57:21] AudioAttributes: usage=USAGE_UNKNOWN content=CONTENT_TYPE_UNKNOWN flags=0x801 tags= bundle=null forVolume: true stream: STREAM_SYSTEM(1)
[18:57:21] AudioDeviceAttributes: role:output type:speaker addr: name: profiles:[] descriptors:[]
[18:57:21] AudioDeviceAttributes: role:output type:bt_a2dp addr:48:F3:F3:ED:78:AD name: profiles:[] descriptors:[]
。。。
百度查询到:AudioSystemAdapter可能会包含如下功能:
设备检测:检查设备是否支持特定音频特性(如蓝牙、耳机插孔等)。
音频路径管理:动态选择音频流的最佳路径,如扬声器、耳机或蓝牙设备。
音效处理:应用特定的音效效果,如均衡器设置或环绕声模式。
但是从上面日志看不出这些信息,可能信息比较隐蔽。
从上面的示例的主要日志信息,可以看到dumpsys主要包含当前音频流和外设的信息。
2、dumpsys audio日志的主要格式内容
# dumpsys audio //(1)执行命令
[18:57:20]Events log: audio services lifecycle
//(2)AudioService 启动时间,大概可以推测出开机时间
[18:57:20]11-22 18:54:07:681 AudioService()
//(3)dumpsys audio最重要的内容,设备支持声音流情况,正常看STREAM_MUSIC
[18:57:20]Stream volumes (device: index)
[18:57:20]- STREAM_MUSIC:
[18:57:20] Muted: false
[18:57:20] Muted Internally: false
[18:57:20] Min: 0 //声音范围
[18:57:20] Max: 15
[18:57:20] streamVolume:7 //当前声音大小
[18:57:20] Current: 2 (speaker): 7, 80 (bt_a2dp): 7, 400 (hdmi): 7, 40000000 (default): 7
[18:57:20] Devices: bt_a2dp(80) //当前声音通道,蓝牙
[18:57:20] Volume Group: music
[18:57:20]
//(4)音频播放情况日志
[19:00:32]Events log: playback activity as reported through
//(5)音频外设连接情况
[18:57:21] Connected devices:
//(6)声音通道占用的日志
[18:57:21]Events log: force use (logged before setForceUse() is executed)
//(7)音频外设连接断开日志
[18:57:21]Events log: wired/A2DP/hearing aid device connection
//(8)声音变化和通道情况
[18:57:21]Events log: volume changes (logged when command received by AudioService)
//(9)AudioSystemAdapter 音频管理信息
这里只是根据一个实际的示例日志进行的讲解,
上面的讲解不一定完全正确和全面,仅供参考吧。
三、其他
1、dumpsys audio小结
dumpsys audio 主要能看到
当前设备音频流的指向情况,Stream volumes (device: index)
当前系统音频外设连接情况,Connected devices
声音通道占用情况记录,Events log: force use
音频外设连接断开日志,Events log: wired/A2DP/hearing aid device connection
dumpsys audio 最主要就是上面这几个声音相关信息。
更多的要看具体情况的日志了。
2、dumpsys audio 的源码
dumpsys audio 返回的打印信息,其实是Java代码上打印的,具体源码如下:
framework/base/services/core/java/com/android/server/audio/AudioService.java
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
sLifecycleLogger.dump(pw);
if (mAudioHandler != null) {
pw.println("\nMessage handler (watch for unhandled messages):");
mAudioHandler.dump(new PrintWriterPrinter(pw), " ");
} else {
pw.println("\nMessage handler is null");
}
...
pw.println("\nAudio routes:");
pw.print(" mMainType=0x"); pw.println(Integer.toHexString(
mDeviceBroker.getCurAudioRoutes().mainType));
pw.print(" mBluetoothName="); pw.println(mDeviceBroker.getCurAudioRoutes().bluetoothName);
...
pw.println("\n");
pw.println("\nSpatial audio:");
pw.println("mHasSpatializerEffect:" + mHasSpatializerEffect + " (effect present)");
pw.println("isSpatializerEnabled:" + isSpatializerEnabled() + " (routing dependent)");
mSpatializerHelper.dump(pw);
sSpatialLogger.dump(pw);
mAudioSystem.dump(pw);
}
可以看到 dumpsys audio 命令返回的数据,都是在 AudioService.java 里面返回打印的;
Audio相关数据很多,有兴趣的可以自己分析研究看看;
如果想要自定义添加一下额外的打印,可以在源码里面添加。
3、使用谷歌文件管理器 GoogleFile 播放音频文件日志:
logct | grep -E "AudioService|AudioTrack"
//打开文件管理器后首次播放:
11-23 10:22:26.542 798 1614 I MediaSessionStack: addSession to bottom of stack | record: com.google.android.apps.nbu.files/AudioService (userId=0)
11-23 10:22:26.938 798 1614 I AudioService.FadeOutManager: unfadeOutUid() uid:10074
11-23 10:22:27.148 798 937 I MediaSessionStack: onPlaybackStateChanged - Pushing session to top | record: com.google.android.apps.nbu.files/AudioService (userId=0)
11-23 10:22:27.635 798 1457 I ActivityManager: Background started FGS: Allowed [callingPackage: com.google.android.apps.nbu.files; callingUid: 10074; uidState: TOP ; uidBFSL: [BFSL]; intent: Intent { cmp=com.google.android.apps.nbu.files/.mediaconsumption.audio.service.AudioService (has extras) }; code:PROC_STATE_TOP; tempAllowListReason:<null>; targetSdkVersion:34; callerTargetSdkVersion:34; startForegroundCount:0; bindFromPackage:null: isBindService:true]
11-23 10:22:27.666 798 798 D MediaSessionService: Media button session is changed to com.google.android.apps.nbu.files/AudioService (userId=0)
//停止后,再次点击播放
11-23 10:22:58.294 7108 7259 D AudioTrack: getTimestamp_l(16): device stall time corrected using current time 2328289907108
11-23 10:22:58.339 798 1460 I MediaSessionStack: onPlaybackStateChanged - Pushing session to top | record: com.google.android.apps.nbu.files/AudioService (userId=0)
11-23 10:22:58.344 7108 7259 D AudioTrack: getTimestamp_l(16): stale timestamp time corrected, currentTimeNanos: 2318205649000 < limitNs: 2328189081941 < mStartNs: 2328287081941
11-23 10:22:58.344 7108 7259 W AudioTrack: getTimestamp_l(16): retrograde timestamp time corrected, 2328189081941 < 2328329633858
能看到一点日志,比如AudioTrack播放时间,但是没有太多日志,比如用什么设备播放、播放音量等等信息。
所以dumpsys audio 还是可以看到当时比较有用的一些日志的。
4、Android 的声音通道类型
其中streamType定义如下:
STREAM_ALARM:闹钟
STREAM_DTMF:双音多频,拨号键的声音
STREAM_MUSIC:音乐
STREAM_NOTIFICATION:通知
STREAM_RING:铃声
STREAM_SYSTEM:系统
STREAM_VOICE_CALL:通话
Android大概支持上面的声音通道类型,主要使用的是外放的 STREAM_MUSIC。
5、Android–耳机插拔检测(framework篇)
上层到底层的一顿讲解