dumpsys media.metrics
-
-
Records Discarded: 3209 (by Count: 3209 by Expiration: 0)
0: {audio.thread.53, (11-21 07:08:42.464), (audioserver, 0, 1041), (throttleMs=3.000000e+00)}
1: {audio.thread.53, (11-21 07:08:42.485), (audioserver, 0, 1041), (throttleMs=2.000000e+00)}
2: {audio.thread.53, (11-21 07:08:42.506), (audioserver, 0, 1041), (throttleMs=1.000000e+00)}
3: {audio.thread.53, (11-21 07:08:42.574), (audioserver, 0, 1041), (throttleMs=2.000000e+00)}
4: {audio.thread.53, (11-21 07:08:42.624), (audioserver, 0, 1041), (throttleMs=3.000000e+00)}
5: {audio.thread.53, (11-21 07:08:42.688), (audioserver, 0, 1041), (throttleMs=1.000000e+00)}
6: {audio.thread.53, (11-21 07:08:42.827), (audioserver, 0, 1041), (throttleMs=2.000000e+00)}
7: {audio.track.61, (11-21 07:08:44.550), (android.uid.system, 0, 1000), (event#=setVolume, volume.left=1.000000e+00, volume.right=1.000000e+00)}
8: {audio.thread.53, (11-21 07:08:44.599), (audioserver, 0, 1041), (event#=createAudioPatch, inputDevices=, outputDevices=(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, 6C:D3:EE:8A:43:20))}
9: {audio.track.61, (11-21 07:08:44.619), (android.uid.system, 0, 1000), (callerName=soundpool, event#=start, executionTimeNs=69001500, state=STATE_ACTIVE, status#=0)}
10: {audio.track.61, (11-21 07:08:44.716), (android.uid.system, 0, 1000), (bufferSizeFrames=4512, event#=stop, executionTimeNs=427583, state=STATE_STOPPED, underrun=0)}
11: {audio.track.61, (11-21 07:08:44.738), (audioserver, 0, 1041), (latencyMs=1.006627e+02, startupMs=1.141446e+02)}
12: {audio.track.63, (11-21 07:08:44.749), (media, 0, 1013), (event#=pause, executionTimeNs=3365333, state=STATE_PAUSED)}
13: {audio.track.61, (11-21 07:08:44.755), (android.uid.system, 0, 1000), (event#=setVolume, volume.left=1.000000e+00, volume.right=1.000000e+00)}
14: {audio.track.61, (11-21 07:08:44.756), (android.uid.system, 0, 1000), (callerName=soundpool, event#=start, executionTimeNs=199958, state=STATE_ACTIVE, status#=0)}
15: {audio.track.61, (11-21 07:08:44.855), (android.uid.system, 0, 1000), (bufferSizeFrames=4512, event#=stop, executionTimeNs=810542, state=STATE_STOPPED, underrun=0)}
16: {audio.track.61, (11-21 07:08:44.877), (audioserver, 0, 1041), (latencyMs=9.432017e+01, startupMs=2.717963e+01)}
17: {audio.device.setBluetoothA2dpOn, (11-21 07:08:45.247), (android.uid.system, 708, 1000), (state=on)}
18: {audio.forceUse.FOR_MEDIA, (11-21 07:08:45.247), (android.uid.system, 0, 1000), (event#=onSetForceUse, forceUseDueTo=setBluetoothA2dpOn(true) from u/pid:1000/708 src:AudioService.setBtA2dpOn, forceUseMode=FORCE_NONE E)}
19: {audio.device.onReportNewRoutes, (11-21 07:08:45.248), (android.uid.system, 0, 1000), (observers=5)}
20: {audio.volume.STREAM_VOICE_CALL.hdmi, (11-21 07:08:45.267), (android.uid.system, 0, 1000), (event#=put, index=1000, maxIndex=1000, minIndex=0)}
21: {audio.volume.STREAM_SYSTEM.hdmi, (11-21 07:08:45.292), (android.uid.system, 0, 1000), (event#=put, index=1000, maxIndex=1000, minIndex=0)}
22: {audio.volume.STREAM_RING.hdmi, (11-21 07:08:45.316), (android.uid.system, 0, 1000), (event#=put, index=1000, maxIndex=1000, minIndex=0)}
23: {audio.volume.STREAM_MUSIC.hdmi, (11-21 07:08:45.331), (android.uid.system, 0, 1000), (event#=put, index=250, maxIndex=250, minIndex=0)}
24: {audio.volume.STREAM_ALARM.hdmi, (11-21 07:08:45.347), (android.uid.system, 0, 1000), (event#=put, index=1000, maxIndex=1000, minIndex=10)}
-
在敲下命令
dumpsys media.metrics时,实际调用的是MediaMetricsService中的dump函数来打印缓存日志信息。 -
MediaMetricsService是 Android 系统中的一个后台服务,它的核心任务是持续收集和存储来自媒体组件(如音频、视频、编解码器等)的日志信息等。 -
通过该命令可以查看Audio framework中java和c++ framework中各个关键操作的日志,从该日志可以辅助开发者定位问题。
1、Java中的Metrics
1.1、代码示例
代码中如果有new MediaMetrics.Item,那么调用的时候就会记录一条metric。
例如在AudioService.java中记录每次调节音量的信息:
frameworks\base\services\core\java\com\android\server\audio\AudioService.java中
java
private final SparseIntArray mIndexMap = new SparseIntArray(8) {
@Override
public void put(int key, int value) {
super.put(key, value);
record("put", key, value);
if (cacheGetStreamVolume()) {
if (DEBUG_VOL) {
Log.d(TAG, "Clear volume cache after update index map");
}
AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
}
}
@Override
public void setValueAt(int index, int value) {
super.setValueAt(index, value);
record("setValueAt", keyAt(index), value);
if (cacheGetStreamVolume()) {
if (DEBUG_VOL) {
Log.d(TAG, "Clear volume cache after update index map");
}
AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
}
}
// Record all changes in the VolumeStreamState
private void record(String event, int key, int value) {
final String device = key == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
: AudioSystem.getOutputDeviceName(key);
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_VOLUME + MediaMetrics.SEPARATOR
+ AudioSystem.streamToString(mStreamType)
+ "." + device)
.set(MediaMetrics.Property.EVENT, event)
.set(MediaMetrics.Property.INDEX, value)
.set(MediaMetrics.Property.MIN_INDEX, mIndexMin)
.set(MediaMetrics.Property.MAX_INDEX, mIndexMax)
.record();
}
};
每次调节音量就有一条记录:
{audio.volume.STREAM_ALARM.hdmi, (10-15 12:12:31.888), (android.uid.system, 0, 1000), (event#=put, index=800, maxIndex=1000, minIndex=0)}
1.2、tag定义
java的MediaMetrics.Name的定义在:
frameworks/base/media/java/android/media/MediaMetrics.java
...
public static final String AUDIO_MODE = AUDIO + SEPARATOR + "mode";
public static final String AUDIO_SERVICE = AUDIO + SEPARATOR + "service";
public static final String AUDIO_VOLUME = AUDIO + SEPARATOR + "volume";
public static final String AUDIO_VOLUME_EVENT = AUDIO_VOLUME + SEPARATOR + "event";
public static final String METRICS_MANAGER = "metrics" + SEPARATOR + "manager";
...
2、C++中的Metrics
2.1、代码示例
代码中如果有mediametrics::LogItem调用就会记录一条metric。
例如在AudioTrack.cpp中启动一次track播放
frameworks/av/media/libaudioclient/AudioTrack.cpp
c++
status_t AudioTrack::start()
{
AutoMutex lock(mLock);
if (mState == STATE_ACTIVE) {
return INVALID_OPERATION;
}
ALOGV("%s(%d): prior state:%s", __func__, mPortId, stateToString(mState));
// Defer logging here due to OpenSL ES repeated start calls.
// TODO(b/154868033) after fix, restore this logging back to the beginning of start().
const int64_t beginNs = systemTime();
status_t status = NO_ERROR; // logged: make sure to set this before returning.
mediametrics::Defer defer([&] {
mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_CALLERNAME,
mCallerName.empty()
? AMEDIAMETRICS_PROP_CALLERNAME_VALUE_UNKNOWN
: mCallerName.c_str())
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
.set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
.set(AMEDIAMETRICS_PROP_STATE, stateToString(mState))
.set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
.record(); });
每次AudioTrack start打印有:
{audio.track.16, (10-15 12:12:32.024), (root, 0, 0), (callerName=unknown, event#=start, executionTimeNs=5194083, state=STATE_ACTIVE, status#=0)}
2.2、tag定义
c++的MediaMetrics.Name的定义在:
frameworks\av\media\libmediametrics\include\MediaMetricsConstants.h
#define AMEDIAMETRICS_KEY_PREFIX_AUDIO "audio."
// Device related key prefix.
#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_DEVICE AMEDIAMETRICS_KEY_PREFIX_AUDIO "device."
// The AudioMmap key appends the "trackId" to the prefix.
// This is the AudioFlinger equivalent of the AAudio Stream.
// TODO: unify with AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM
#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP AMEDIAMETRICS_KEY_PREFIX_AUDIO "mmap."
// The AudioRecord key appends the "trackId" to the prefix.
#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD AMEDIAMETRICS_KEY_PREFIX_AUDIO "record."
// The Audio Sensor key appends the sensor handle integer.
#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_SENSOR AMEDIAMETRICS_KEY_PREFIX_AUDIO "sensor."
// The Audio Spatializer key appends the spatializerId (currently 0)
#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_SPATIALIZER AMEDIAMETRICS_KEY_PREFIX_AUDIO "spatializer."
// The Audio Spatializer device key appends the device type.
#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_SPATIALIZER_DEVICE \
AMEDIAMETRICS_KEY_PREFIX_AUDIO_SPATIALIZER "device."
// The AudioStream key appends the "streamId" to the prefix.
#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_STREAM AMEDIAMETRICS_KEY_PREFIX_AUDIO "stream."
// The AudioThread key appends the "threadId" to the prefix.
#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD AMEDIAMETRICS_KEY_PREFIX_AUDIO "thread."
// The AudioTrack key appends the "trackId" to the prefix.
#define AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK AMEDIAMETRICS_KEY_PREFIX_AUDIO "track."
// Keys are strings used for MediaMetrics Item Keys
#define AMEDIAMETRICS_KEY_AUDIO_FLINGER AMEDIAMETRICS_KEY_PREFIX_AUDIO "flinger"
#define AMEDIAMETRICS_KEY_AUDIO_MIDI AMEDIAMETRICS_KEY_PREFIX_AUDIO "midi"
#define AMEDIAMETRICS_KEY_AUDIO_POLICY AMEDIAMETRICS_KEY_PREFIX_AUDIO "policy"