【Android Audio】dumpsys media.metrics分析

dumpsys media.metrics

  • 1、Java中的Metrics

  • 2、C++中的Metrics

    • 2.1、代码示例

    • 2.2、tag定义

      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"
相关推荐
nono牛1 小时前
Android Binder 详解与实践指南
android·binder
小镇学者1 小时前
【PHP】PHP WebShell(网页木马)分析
android·开发语言·php
2501_916007472 小时前
iOS 压力测试的工程化体系,构建高强度、多维度、跨工具协同的真实负载测试流程
android·ios·小程序·uni-app·cocoa·压力测试·iphone
毕设源码-钟学长4 小时前
【开题答辩全过程】以 浮生馆汉服租赁管理系统为例,包含答辩的问题和答案
android·java·tomcat
louisgeek4 小时前
Android NDK 开发中的崩溃排查
android
2501_915921436 小时前
iOS 开发者工具推荐,构建从调试到性能优化的多维度生产力工具链(2025 深度工程向)
android·ios·性能优化·小程序·uni-app·iphone·webview
Chrison_mu7 小时前
Android项目背景动效-Kotlin
android·开发语言·kotlin
曾经的三心草8 小时前
JavaEE初阶-多线程2
android·java·java-ee
v***5658 小时前
Spring Cloud Gateway
android·前端·后端