Android音频log分析及其常用关键字

目录

1. 日志类型

2. 日志级别 priority:

3. 查看日志常用函数:

3.1 播放相关

3.2 设备选择相关 

3.3 音量相关

3.4 常用的日志 关键字

4. CallAudioState \ CallAudioManager 

5.  音频流类型获取音频的路由策略

6. 通过streamType得到audio_io_handle

6.1 APM(AudioPolicyManager)

6.2 Engine: getOutputDevicesForStream 

6.2.1 getAttributesForStreamType 

 6.2.2 getOutputDevicesForAttributes

6.2.3 getOutputsForDevices(devices, mOutputs); 

6.2.4 selectOutput


1. 日志类型

Logger日志驱动程序内部使用一个环形缓冲区保存日志,缓冲区满了之后新日志会覆盖旧日志。因此要按照日志类型和输出量对日志进行分类,避免不重要日志覆盖重要日志,数据量大的日志覆盖数据量小的日志。

日志类型作用Java接口备注
main应用程序级别android.util.Log
system系统级别 android.util.Slog重要
event诊断系统问题android.util.Eventlog

应用程序开发者不应该

使用此类型的日志

radio无线设备相关数据量大

如果使用android.util.Log和android.util.Slog接口写入的日志标签值是以“RIL”开头或者等于“HTC_RIL”、“AT”、“GSM”、“STK”、“CDMA”、“PHONE”和“SMS”时,他们就会被转换为radio类型的日志写入到Logger日志驱动程序中。

2. 日志级别 priority:

  1. V 最小级别日志,Verbose级
  2. D 调试信息,Debug级
  3. I 打印重要数据,Info级
  4. W 打印警告信息,Warn级
  5. E 打印错误信息,Error级
  6. F 非常严重的错误信息,Fatal级

     一般查看日志都是查看Error级

3. 查看日志常用函数:

3.1 播放相关

1、startOutput() output %d, stream %d, session %d, portId %d, phoneState %d, communiCf %d, mediaCf %d

该函数表示一段音频的开始

stream为音频的类型,常见类型有0(通话);1(系统音);2(铃声);3(媒体音);4(闹钟);5(通知音);6(通话音蓝牙SCO);7(强制音);8(DTMF拨号音);9(TTS智慧语音);10(辅助功能提示音);

session:标识一个实例,可以通过这个找到播放的应用

phoneState:显示的是通话状态

后面两个表示是否强制用于通话或者媒体

 2、stopOutput() output %d, stream %d, session %d, portId %d

该函数表示一段音频的结束。

参数与相对应的startOutput相对应

 3、asd_out : L = [0], R = [0], continus 20 times

hal层输出,如果存在就说明hal层有声音,但不一定准确

4、asd_out_fwk: L = [0], R = [0], continus 20 times, Device = 0x80
asd_out_fwk: L = -33.742146db, R = -33.591274db, Device = 0x80, TimeStampKernel = 908640, TimeStampServer = 923520

fwk最终的声音

3.2 设备选择相关 

一般在播放一段音频之后紧跟的就是输出设备的选择,很多时候无声问题往往就是因为播放设备选错引起的
1、setDeviceConnectionStateInt() device: 0x%X, state %d, name %s format 0x%X

该函数用来确定设备的连接与断开,但是由于fwk属于中间层,所以即使我们打印了这句话,

        也不能确保设备确实连接上或者断开了,尤其是对于蓝牙,可能出现打印了已断开但断开失败的问题。

        device为设备的类型。

        state为状态,1表示连接,0表示断开

        name为设备名称。

        format为蓝牙音频解码器(具体哪些不太清楚)。

/* Formats for A2DP codecs, must match system/audio-base.h audio_format_t */

 public static final int AUDIO_FORMAT_INVALID          = 0xFFFFFFFF;

 public static final int AUDIO_FORMAT_DEFAULT        = 0;

 public static final int AUDIO_FORMAT_AAC                = 0x04000000;

 public static final int AUDIO_FORMAT_SBC                = 0x1F000000;

 public static final int AUDIO_FORMAT_APTX              = 0x20000000;

 public static final int AUDIO_FORMAT_APTX_HD       = 0x21000000;

 public static final int AUDIO_FORMAT_LDAC              = 0x23000000;

2、changing device to %s

打印出这句话表示设备已经切换,如果没有这句而有setOutputDevice则未发生切换,虽然是切换函数但是切换是有条件的。

device,也就是%s位置的值为设备类型与上面的device相对应。

3、setForceUse() usage %d, config %d, mPhoneState %d mA2dpSuspended 0

该函数用来选择设备的切换

(是setOutputDevices之所以选择某个设备的原因,也就是先执行了setForceUse,然后才是setOutputDevices),往往在设备切换出错时使用。

usage是场景,也就是用来播什么,比如是响铃,通话,或是媒体,具体类型如下。

   //usage for setForceUse, must match audio_policy_force_use_t

   public static final int FOR_COMMUNICATION = 0;

   public static final int FOR_MEDIA = 1;

   public static final int FOR_RECORD = 2;

   public static final int FOR_DOCK = 3;

   public static final int FOR_SYSTEM = 4;

   public static final int FOR_HDMI_SYSTEM_AUDIO = 5;

   public static final int FOR_ENCODED_SURROUND = 6;

   public static final int FOR_VIBRATE_RINGING = 7;

   public static final int FOR_DESKTOP_MODE = 8;

   public static final int FOR_EXTEND_MEDIA = 9;

   private static final int NUM_FORCE_USE = 10;

config是设备,如下

  //device categories config for setForceUse, must match audio_policy_forced_cfg_t

  public static final int FORCE_NONE = 0;

  public static final int FORCE_SPEAKER = 1;

  public static final int FORCE_HEADPHONES = 2;

  public static final int FORCE_BT_SCO = 3;

  public static final int FORCE_BT_A2DP = 4;

  public static final int FORCE_WIRED_ACCESSORY = 5;

  public static final int FORCE_BT_CAR_DOCK = 6;

  public static final int FORCE_BT_DESK_DOCK = 7;

  public static final int FORCE_ANALOG_DOCK = 8;

  public static final int FORCE_DIGITAL_DOCK = 9;

  public static final int FORCE_NO_BT_A2DP = 10;

  public static final int FORCE_SYSTEM_ENFORCED = 11;

  public static final int FORCE_HDMI_SYSTEM_AUDIO_ENFORCED = 12;

  public static final int FORCE_ENCODED_SURROUND_NEVER = 13;

  public static final int FORCE_ENCODED_SURROUND_ALWAYS = 14;

  public static final int FORCE_ENCODED_SURROUND_MANUAL = 15;

  public static final int FORCE_DESKTOP_HDMI = 16;

  public static final int FORCE_DESKTOP_NO_HDMI = 17;

  public static final int FORCE_EXTEND_EARPIECE = 18;

  public static final int FORCE_EXTEND_SPEAKER = 19;

  public static final int FORCE_EXTEND_A2DP = 20;

  public static final int FORCE_EXTEND_SCO = 21;

  public static final int FORCE_EXTEND_HEADSET = 22;

  public static final int FORCE_EXTEND_TYPEC = 23;

  public static final int FORCE_EXTEND_USB = 24;

  public static final int FORCE_EXTEND_OTHER = 25;

  public static final int FORCE_EXTEND_MSDP = 26;

  public static final int NUM_FORCE_CONFIG = 27;

  public static final int FORCE_DEFAULT = FORCE_NONE;

mPhoneState是手机状态,常用的也就 0(一般),1(响铃),2(通话*真),3(通话*虚拟,比如微信语音通话)

mA2dpSuspended表示蓝牙A2DP是否被抑制,如果为1则需要查看下蓝牙SCO是否打开,这两不能同时启用

4、getOutputsForDevices

getOutputsForDevices, openOutputs size is 2, outputs size is 2

openOutputs size表示当前获取到的设备总数

outputs size表示正在使用的设备总数

3.3 音量相关

1、InputEvent: %d-%d

第一个参数是按键码,一般我们常看的是24(音量增加),25(音量减少)。

第二个参数是按下或松开,0是按下,1是松开。

2、adjustStreamVolume() stream=3, dir=1, flags=4113, caller=android

stream:流类型

dir:direction音量调节,-1为减,1为加,0为不变

caller:那个应用修改的,一般都是android

3、setStreamVolume stream=3; value=0.000000; output=13

该函数为设置音量的函数,如果有此打印表示音量已被改变

 stream:流类型

 value:音量值

 output:设备描述符,13为主输出设备

4、 checkAndSetVolume volumeSource 6, index 6, device 00000080, volumeDb -34.000000, output 389

该函数只是检测音量大小的函数

volumeSource:类型同stream,但不对齐,比如volumeSource 6 = stream 3,如下

index:音量级

普通音量分为16级 0-15,0最小,15最大,蓝牙耳机不一定满足此音量级分布。

查看eventlogcat,搜索volume_changed可见到如下

volume_changed: [6,11,7,15,com.tencent.mm]

6:stream类型;11:音量设置前的音量级;7为音量设置后的音量级;15为最大音量级;最后一个为调用的包名

 

device:设备标识

volumeDb:经过computeVolume函数计算过的,数据类型为double,数越小音量越小,-758.000000为无声,0为最大。

output:同上

注意:checkAndSetVolume的index和volumeDb冲突时以index为准

checkAndSetVolume :

1 AUDIO_STREAM_ACCESSIBILITY
2 AUDIO_STREAM_ALARM
3 AUDIO_STREAM_BLUETOOTH_SCO
4 AUDIO_STREAM_DTMF
5 AUDIO_STREAM_ENFORCED_AUDIBLE
6 AUDIO_STREAM_MUSIC
7 AUDIO_STREAM_NOTIFICATION
8 AUDIO_STREAM_PATCH
9 AUDIO_STREAM_REROUTING
10 AUDIO_STREAM_RING
11 AUDIO_STREAM_SYSTEM
12 AUDIO_STREAM_TTS
13 AUDIO_STREAM_VOICE_CALL

 5、setStreamVolumeIndexAS: stream=3 dev=80 idx=15

该函数用于调节音量级

stream:流类型

dev:设备类型

idx:音量级同index

 6、setStreamVolumeIndex() stream 3, device 0x0080, index 15

执行调节音量级,有此打印表示音量级已被修改

3.4 常用的日志 关键字

  1. startOutput: 开始播放
  2. stopOutput: 停止播放
  3. setDeviceConnectionStateInt: 选择播放设备连接状态(state=1连接,state=0断开)
  4. setOutputDevices: 设置播放设备
  5. setStreamVolume: 设置音量
  6. final_volume: 实际的音量 0最小 1最大
  7. setRingerMode: 0静音 1震动 2正常
  8. setVolume: 软件设置音量
  9. setModeInt: 改变手机状态,也会影响到设备的选择    0一般 1响铃 2通话 3voip网络电话
  10. setPhoneState: 手机通话状态改变 一般是通话状态改变0->2
  11. setSpeakerphoneOn: 打开或关闭扬声器(免提状态),一般通话时候用
  12. asd_out: 外放或有线耳机调用的函数
  13. AudioFlinger: 播放信息
  14. startBluetoothSco:打开蓝牙SCO
  15. stopBluetoothSco:关闭蓝牙SCO
  16. setBluetoothSco: SCO状态,为start/stop的回调
  17. abandonAudioFocus:遗弃焦点
  18. requestAudioFocus:获得焦点
  19. audio focus pkg:焦点所在位置的包名
  20. dispatchVolumeKeyEvent:接收到按键事件
  21. adjustSuggestedStreamVolume:正在执行调音量的步骤
  22. getInputForAttr: 录音入口 一个代表一次启动
  23. startInput | stopInput | closeInput: 录音 参数对应PCM
  24. setClientActive: 录音(状态)
  25. computevolume
  26. Start_output_stream: 定义在hal层的audio_hw.h中:0是普通,1是低时延,2是高清,3是offload,4是aaudio,8是通话状态

设备,流等信息查询
/frameworks/base/media/java/android/media/AudioSystem.java

Stream 流的信息:

AUDIO_STREAM_VOICE_CALL = 0, 通话音

AUDIO_STREAM_SYSTEM = 1, 系统音

AUDIO_STREAM_RING = 2,   铃声

AUDIO_STREAM_MUSIC = 3, 媒体音

AUDIO_STREAM_ALARM = 4, 闹钟

AUDIO_STREAM_NOTIFICATION = 5,  通知音

AUDIO_STREAM_BLUETOOTH_SCO = 6, 蓝牙SCO通道 (电话)

AUDIO_STREAM_ENFORCED_AUDIBLE = 7, 强制音频

AUDIO_STREAM_DTMF = 8,   按键音一类的

AUDIO_STREAM_TTS = 9,   智慧语音的语音播报 (属于9,其他只能设备也有可能)

AUDIO_STREAM_ACCESSIBILITY = 10,辅助提示音

volumeSource,与stream对应但不对齐:

AUDIO_STREAM_ACCESSIBILITY = 1 = stream 10
AUDIO_STREAM_ALARM = 2 = stream 4
AUDIO_STREAM_BLUETOOTH_SCO = 3 = stream 6
AUDIO_STREAM_DTMF= 4 = stream 8
AUDIO_STREAM_ENFORCED_AUDIBLE = 5 = stream 7
AUDIO_STREAM_MUSIC = 6 = stream 3
AUDIO_STREAM_NOTIFICATION = 7 = stream 5
AUDIO_STREAM_PATCH = 8
AUDIO_STREAM_REROUTING = 9
AUDIO_STREAM_RING = 10 = stream 2
AUDIO_STREAM_SYSTEM = 11 = stream 1

AUDIO_STREAM_TTS = 12 = stream 9
AUDIO_STREAM_VOICE_CALL = 13 = stream 0

手机状态mode:

MODE_INVALID                         = -2;
MODE_CURRENT                     = -1;
MODE_NORMAL                       = 0;               //普通状态,一般情况下使用
MODE_RINGTONE                    = 1;               //响铃状态,来电响铃状态下使用
MODE_IN_CALL                         = 2;               //通话状态,打电话呼叫建立时使用
MODE_IN_COMMUNICATION   = 3;               //communication状态,建立一个音/视频呼叫或VoIP呼叫

NUM_MODES                             = 4;

设备信息:

AUDIO_DEVICE_OUT_EARPIECE                           //0x1 听筒
AUDIO_DEVICE_OUT_SPEAKER                            //0x2 扬声器       
AUDIO_DEVICE_OUT_WIRED_HEADSET                      //0x4 有线耳机HEADSET
AUDIO_DEVICE_OUT_WIRED_HEADPHONE                    //0x8 有线耳机HEADPHONE
AUDIO_DEVICE_OUT_BLUETOOTH_SCO                      //0x10 蓝牙 SCO
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET              //0x20 蓝牙 SCO 
AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT               //0x40 蓝牙 SCO 车机
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP                     //0x80 蓝牙 A2DP
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES          //0x100 蓝牙 A2DP 耳机
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER             //0x200 蓝牙 A2PD 扬声器

蓝牙电话会选择0x10 SCO

蓝牙听歌会选择0x80 A2DP

0x3 就是 0x1 + 0x2 (听筒加扬声器)

语音播报通道选择

1,当前有A2DP连接----使用music通道。

2,当前有SCO连接----使用Call通道。

3,除1,2外的其他场景----使用TTS通道。

// 常见设备定义(全)

enum {
    AUDIO_DEVICE_NONE                          = 0x0u,
    AUDIO_DEVICE_BIT_IN                        = 0x80000000u,
    AUDIO_DEVICE_BIT_DEFAULT                   = 0x40000000u,
 
    AUDIO_DEVICE_OUT_EARPIECE                  = 0x1u,
    AUDIO_DEVICE_OUT_SPEAKER                   = 0x2u,
    AUDIO_DEVICE_OUT_WIRED_HEADSET             = 0x4u,
    AUDIO_DEVICE_OUT_WIRED_HEADPHONE           = 0x8u,
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO             = 0x10u,
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET     = 0x20u,
    AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT      = 0x40u,
    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP            = 0x80u,
    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100u,
    AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER    = 0x200u,
    AUDIO_DEVICE_OUT_AUX_DIGITAL               = 0x400u,
    AUDIO_DEVICE_OUT_HDMI                      = 0x400u,      // OUT_AUX_DIGITAL
    AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET         = 0x800u,
    AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET         = 0x1000u,
    AUDIO_DEVICE_OUT_USB_ACCESSORY             = 0x2000u,
    AUDIO_DEVICE_OUT_USB_DEVICE                = 0x4000u,
    AUDIO_DEVICE_OUT_REMOTE_SUBMIX             = 0x8000u,
    AUDIO_DEVICE_OUT_TELEPHONY_TX              = 0x10000u,
    AUDIO_DEVICE_OUT_LINE                      = 0x20000u,
    AUDIO_DEVICE_OUT_HDMI_ARC                  = 0x40000u,
    AUDIO_DEVICE_OUT_SPDIF                     = 0x80000u,
    AUDIO_DEVICE_OUT_FM                        = 0x100000u,
    AUDIO_DEVICE_OUT_AUX_LINE                  = 0x200000u,
    AUDIO_DEVICE_OUT_SPEAKER_SAFE              = 0x400000u,
    AUDIO_DEVICE_OUT_IP                        = 0x800000u,
    AUDIO_DEVICE_OUT_BUS                       = 0x1000000u,
    AUDIO_DEVICE_OUT_PROXY                     = 0x2000000u,
    AUDIO_DEVICE_OUT_USB_HEADSET               = 0x4000000u,
    AUDIO_DEVICE_OUT_HEARING_AID               = 0x8000000u,
    AUDIO_DEVICE_OUT_ECHO_CANCELLER            = 0x10000000u,
    AUDIO_DEVICE_OUT_DEFAULT                   = 0x40000000u, // BIT_DEFAULT
 
    AUDIO_DEVICE_IN_COMMUNICATION              = 0x80000001u, // BIT_IN | 0x1
    AUDIO_DEVICE_IN_AMBIENT                    = 0x80000002u, // BIT_IN | 0x2
    AUDIO_DEVICE_IN_BUILTIN_MIC                = 0x80000004u, // BIT_IN | 0x4
    AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET      = 0x80000008u, // BIT_IN | 0x8
    AUDIO_DEVICE_IN_WIRED_HEADSET              = 0x80000010u, // BIT_IN | 0x10
    AUDIO_DEVICE_IN_AUX_DIGITAL                = 0x80000020u, // BIT_IN | 0x20
    AUDIO_DEVICE_IN_HDMI                       = 0x80000020u, // IN_AUX_DIGITAL
    AUDIO_DEVICE_IN_VOICE_CALL                 = 0x80000040u, // BIT_IN | 0x40
    AUDIO_DEVICE_IN_TELEPHONY_RX               = 0x80000040u, // IN_VOICE_CALL
    AUDIO_DEVICE_IN_BACK_MIC                   = 0x80000080u, // BIT_IN | 0x80
    AUDIO_DEVICE_IN_REMOTE_SUBMIX              = 0x80000100u, // BIT_IN | 0x100
    AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET          = 0x80000200u, // BIT_IN | 0x200
    AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET          = 0x80000400u, // BIT_IN | 0x400
    AUDIO_DEVICE_IN_USB_ACCESSORY              = 0x80000800u, // BIT_IN | 0x800
    AUDIO_DEVICE_IN_USB_DEVICE                 = 0x80001000u, // BIT_IN | 0x1000
    AUDIO_DEVICE_IN_FM_TUNER                   = 0x80002000u, // BIT_IN | 0x2000
    AUDIO_DEVICE_IN_TV_TUNER                   = 0x80004000u, // BIT_IN | 0x4000
    AUDIO_DEVICE_IN_LINE                       = 0x80008000u, // BIT_IN | 0x8000
    AUDIO_DEVICE_IN_SPDIF                      = 0x80010000u, // BIT_IN | 0x10000
    AUDIO_DEVICE_IN_BLUETOOTH_A2DP             = 0x80020000u, // BIT_IN | 0x20000
    AUDIO_DEVICE_IN_LOOPBACK                   = 0x80040000u, // BIT_IN | 0x40000
    AUDIO_DEVICE_IN_IP                         = 0x80080000u, // BIT_IN | 0x80000
    AUDIO_DEVICE_IN_BUS                        = 0x80100000u, // BIT_IN | 0x100000
    AUDIO_DEVICE_IN_PROXY                      = 0x81000000u, // BIT_IN | 0x1000000
    AUDIO_DEVICE_IN_USB_HEADSET                = 0x82000000u, // BIT_IN | 0x2000000
    AUDIO_DEVICE_IN_BLUETOOTH_BLE              = 0x84000000u, // BIT_IN | 0x4000000
    AUDIO_DEVICE_IN_DEFAULT                    = 0xC0000000u, // BIT_IN | BIT_DEFAULT
};

AudioManager(音频管理器)

1. adjustVolume(int direction, int flags) 

作用:控制手机音量,调大或者调小一个单位,根据第一个参数进行判断 。

2.adjustStreamVolume(int streamType, int direction, int flags): 

作用:同上,不过可以选择调节的声音类型 

3.setStreamVolume(int streamType, int index, intflags)

作用:直接设置音量大小。

4.getMode( )

作用:返回当前的音频模式。

5. 方法:setMode( )

作用:设置声音模式。

返回值:有下述几种模式: 

MODE_NORMAL(普通), MODE_RINGTONE(铃声)

MODE_IN_CALL(打电话),MODE_IN_COMMUNICATION(通话)

6. getRingerMode( )

作用:返回当前的铃声模式。

7.方法:setRingerMode(int streamType)

作用:设置铃声模式 。

返回值:有下述几种模式: 

如RINGER_MODE_NORMAL(普通)

RINGER_MODE_SILENT(静音)

RINGER_MODE_VIBRATE(震动)

8.getStreamVolume(int streamType)

作用:获得手机的当前音量,最大值为7,最小值为0,当设置为0的时候,会自动调整为震动模式。

9. getStreamMaxVolume(int streamType)

作用:获得手机某个声音类型的最大音量值。

10.setStreamMute(int streamType,boolean state)

作用:将手机某个声音类型设置为静音。

11. setSpeakerphoneOn(boolean on)

作用:设置是否打开扩音器。


12. setMicrophoneMute(boolean on)

作用:设置是否让麦克风静音。


13. isMicrophoneMute()

作用:判断麦克风是否静音或是否打开。


14. isMusicActive()

作用:判断是否有音乐处于活跃状态。


15. isWiredHeadsetOn()

作用:判断是否插入了耳机。


16. abandonAudioFocus(AudioManager.OnAudioFocusChangeListenerl)

作用:放弃音频的焦点。


17. adjustSuggestedStreamVolume(int,int suggestedStreamType intflags)

作用:调整最相关的流的音量,或者给定的回退流。


18. getParameters(String keys)

作用:给音频硬件设置一个varaible数量的参数值。


19. getVibrateSetting(int vibrateType)

作用:返回是否该用户的振动设置为振动类型。


20. isBluetoothA2dpOn()

作用:检查是否A2DP蓝牙耳机音频路由是打开或关闭。


21. isBluetoothScoAvailableOffCall()

作用:显示当前平台是否支持使用SCO的关闭调用用例。


22. isBluetoothScoOn()

作用:检查通信是否使用蓝牙SCO。


23. loadSoundEffects()

作用:加载声音效果。


24. playSoundEffect((int effectType, float volume)

作用:播放声音效果。


25. egisterMediaButtonEventReceiver(ComponentName eventReceiver)

作用:注册一个组件MEDIA_BUTTON意图的唯一接收机。


26. requestAudioFocus(AudioManager.OnAudioFocusChangeListener l,int streamType,int durationHint)

作用:请求音频的焦点。

27. setBluetoothScoOn(boolean on)

作用:要求使用蓝牙SCO耳机进行通讯。


28. startBluetoothSco/stopBluetoothSco()

作用:启动/停止蓝牙SCO音频连接。


29. unloadSoundEffects()

作用:卸载音效。

4. CallAudioState \ CallAudioManager 

CallAudioState

用来封装通话过程中的音频播放状态

属性

CallAudioState.java
public static final int ROUTE_EARPIECE      = 0x00000001;//听筒
public static final int ROUTE_BLUETOOTH     = 0x00000002;//蓝牙
public static final int ROUTE_WIRED_HEADSET = 0x00000004;//有线耳机
public static final int ROUTE_SPEAKER       = 0x00000008;//扬声器
public static final int ROUTE_WIRED_OR_EARPIECE = ROUTE_EARPIECE | ROUTE_WIRED_HEADSET;//听筒或者耳机
public static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
        ROUTE_SPEAKER;//全部状态

重要方法:

CallAudioState.java
//是否静音
public boolean isMuted() {
    return isMuted;
}
 
//返回音频状态
public int getRoute() {
    return route;
}

CallAudioManager

CallAudioManager可以类比于AudioManager,负责通话过程中音频播放状态的逻辑;

CallAudioManager是在CallsManager被初始化的;


CallsManager.java
CallsManager(......){
    mCallAudioManager = new CallAudioManager(callAudioRouteStateMachine,
                this,new CallAudioModeStateMachine((AudioManager)
                        mContext.getSystemService(Context.AUDIO_SERVICE)),
                playerFactory, mRinger, new RingbackPlayer(playerFactory), mDtmfLocalTonePlayer);
}

CallAudioRouteStateMachine

 它是处理通话过程中的音频模式的,如语音模式,通话模式等

CallAudioModeStateMachine.java
//音频状态
private final BaseState mUnfocusedState = new UnfocusedState();//待机
private final BaseState mRingingFocusState = new RingingFocusState();//响铃
private final BaseState mSimCallFocusState = new SimCallFocusState();//Call
private final BaseState mVoipCallFocusState = new VoipCallFocusState();//COMMUNICATION
private final BaseState mOtherFocusState = new OtherFocusState();
 
private final AudioManager mAudioManager;
private CallAudioManager mCallAudioManager;
 
private int mMostRecentMode;
private boolean mIsInitialized = false;
 
public CallAudioModeStateMachine(AudioManager audioManager) {
    super(CallAudioModeStateMachine.class.getSimpleName());
    mAudioManager = audioManager;
    mMostRecentMode = AudioManager.MODE_NORMAL;
 
    //将这些状态添加到mStateInfo中
    addState(mUnfocusedState);
    addState(mRingingFocusState);
    addState(mSimCallFocusState);
    addState(mVoipCallFocusState);
    addState(mOtherFocusState);
    
    //待机状态是默认状态
    setInitialState(mUnfocusedState);
    
    //完成CallAudioModeStateMachine的构造
    start();
    sendMessage(INITIALIZE, new MessageArgs());
}

5.  音频流类型获取音频的路由策略

routing_strategy Engine::getStrategyForStream(audio_stream_type_t stream)
{
    // stream to strategy mapping
    switch (stream) {
    case AUDIO_STREAM_VOICE_CALL:
    case AUDIO_STREAM_BLUETOOTH_SCO:
        return STRATEGY_PHONE;
    case AUDIO_STREAM_RING:
    case AUDIO_STREAM_ALARM:
        return STRATEGY_SONIFICATION;
    case AUDIO_STREAM_NOTIFICATION:
        return STRATEGY_SONIFICATION_RESPECTFUL;
    case AUDIO_STREAM_DTMF:
        return STRATEGY_DTMF;
    default:
        ALOGE("unknown stream type %d", stream);
    case AUDIO_STREAM_SYSTEM:
        // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
        // while key clicks are played produces a poor result
    case AUDIO_STREAM_MUSIC:
        return STRATEGY_MEDIA;
    case AUDIO_STREAM_ENFORCED_AUDIBLE:
        return STRATEGY_ENFORCED_AUDIBLE;
    case AUDIO_STREAM_TTS:
        return STRATEGY_TRANSMITTED_THROUGH_SPEAKER;
    case AUDIO_STREAM_ACCESSIBILITY:
        return STRATEGY_ACCESSIBILITY;
    case AUDIO_STREAM_REROUTING:
        return STRATEGY_REROUTING;
    }
}
//音频策略枚举
enum routing_strategy {
    STRATEGY_MEDIA, // 媒体策略
    STRATEGY_PHONE, // 电话策略
    STRATEGY_SONIFICATION, // 通知策略
    STRATEGY_SONIFICATION_RESPECTFUL,
    STRATEGY_DTMF, // DTMF 策略
    STRATEGY_ENFORCED_AUDIBLE, // 强制输出策略
    STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
    STRATEGY_ACCESSIBILITY,
    STRATEGY_REROUTING,
    NUM_STRATEGIES
};

6. 通过streamType得到audio_io_handle

 根据streamType找到合适的设备对应的 audio_io_handle的过程, audioPolicyService -> APM->Engine(具体的策略[配置文件]) 找到合适的设备

大概过程是:

  1. streamType -(getAttributesForStreamType) -> attributes  (streamType对应的多个attributes)
  2. getOutputDevicesForAttributes-> DeviceVector (attributes 找到对应的devices)
  3. getOutputsForDevices -> SortedVector<audio_io_handle_t> (多个devicess对应多个handles)
  4. selectOutput(audio_io_handles, output_flag, audio_format, channel_flag, samplintRate) -> audio_io_handle (从多handle中根据out flag, format, channel, SR,得到最合适的audio_io_handle)
audio_io_handle_t AudioSystem::getOutput(audio_stream_type_t stream)
{
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == 0) return 0;
    return aps->getOutput(stream);
}

6.1 APM(AudioPolicyManager)

frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream)
{
    DeviceVector devices = mEngine->getOutputDevicesForStream(stream, false /*fromCache*/);

    // Note that related method getOutputForAttr() uses getOutputForDevice() not selectOutput().
    // We use selectOutput() here since we don't have the desired AudioTrack sample rate,
    // format, flags, etc. This may result in some discrepancy for functions that utilize
    // getOutput() solely on audio_stream_type such as AudioSystem::getOutputFrameCount()
    // and AudioSystem::getOutputSamplingRate().

    SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs);

    audio_io_handle_t output;
    if (stream == AUDIO_STREAM_MUSIC  &&
            property_get_bool("audio.deep_buffer.media", false /* default_value */)) {
        // use DEEP_BUFFER as default output for music stream type
         output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_DEEP_BUFFER, AUDIO_FORMAT_INVALID);
    }
    else{
          output = selectOutput(outputs);
    }

    ALOGV("getOutput() stream %d selected devices %s, output %d", stream,
          devices.toString().c_str(), output);
    return output;
}

6.2 Engine: getOutputDevicesForStream 

frameworks/av/services/audiopolicy/enginedefault/src/Engine.cpp
//通过stream_type得到attribute, 由attribute得到Device
DeviceVector Engine::getOutputDevicesForStream(audio_stream_type_t stream, bool fromCache) const
{
    auto attributes = getAttributesForStreamType(stream);
    return getOutputDevicesForAttributes(attributes, nullptr, fromCache);
}

6.2.1 getAttributesForStreamType 

frameworks/av/services/audiopolicy/engine/common/src/ProductStrategy.cpp
audio_attributes_t ProductStrategy::getAttributesForStreamType(audio_stream_type_t streamType) const /*one stream type 得到多个属性*/
{
    const auto iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
                                   [&streamType](const auto &supportedAttr) {
        return supportedAttr.mStream == streamType; });
    return iter != end(mAttributesVector) ? iter->mAttributes : AUDIO_ATTRIBUTES_INITIALIZER;
}
// mAttributesVector 怎么生成的?
frameworks/av/services/audiopolicy/engine/common/src/EngineBase.cpp
engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig()
{
    auto addSupportedAttributesToGroup = [](auto &group, auto &volumeGroup, auto &strategy) {
        for (const auto &attr : group.attributesVect) {
            strategy->addAttributes({group.stream, volumeGroup->getId(), attr});
            volumeGroup->addSupportedAttributes(attr);
        }
    };
}
audio_policy_engine_product_strategies.xml
    <ProductStrategy name="STRATEGY_MEDIA">
        <AttributesGroup streamType="AUDIO_STREAM_ASSISTANT" volumeGroup="assistant">
            <Attributes>
                <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
                <Usage value="AUDIO_USAGE_ASSISTANT"/>
            </Attributes>
        </AttributesGroup>
         <AttributesGroup streamType="AUDIO_STREAM_MUSIC" volumeGroup="music">                              // 解析这个配置文件里,一个streamType得到过得attributes                                                                  
            <Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes>
            <Attributes> <Usage value="AUDIO_USAGE_GAME"/> </Attributes>
            <Attributes> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes>
            <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/> </Attributes>
            <Attributes></Attributes>
        </AttributesGroup>
        <AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system">
            <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/> </Attributes>
        </AttributesGroup>
    </ProductStrategy>

 6.2.2 getOutputDevicesForAttributes

DeviceVector Engine::getOutputDevicesForAttributes(const audio_attributes_t &attributes,
                                                   const sp<DeviceDescriptor> &preferredDevice,
                                                   bool fromCache) const
{
    // First check for explict routing device
    if (preferredDevice != nullptr) {
        ALOGV("%s explicit Routing on device %s", __func__, preferredDevice->toString().c_str());
        return DeviceVector(preferredDevice);
    } // 由 attribute -> product_strategy
    product_strategy_t strategy = getProductStrategyForAttributes(attributes);
    const DeviceVector availableOutputDevices = getApmObserver()->getAvailableOutputDevices();
    const SwAudioOutputCollection &outputs = getApmObserver()->getOutputs();
    //
    // @TODO: what is the priority of explicit routing? Shall it be considered first as it used to
    // be by APM?
    //
    // Honor explicit routing requests only if all active clients have a preferred route in which
    // case the last active client route is used
    sp<DeviceDescriptor> device = findPreferredDevice(outputs, strategy, availableOutputDevices); // 输出设备,可用的输出设备和策略通过这些参数得到Preferred
    if (device != nullptr) {
        return DeviceVector(device);
    }

    return fromCache? mDevicesForStrategies.at(strategy) : getDevicesForProductStrategy(strategy);
}

6.2.3 getOutputsForDevices(devices, mOutputs); 

SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevices(
            const DeviceVector &devices,
            const SwAudioOutputCollection& openOutputs)
{
    SortedVector<audio_io_handle_t> outputs;

    ALOGVV("%s() devices %s", __func__, devices.toString().c_str());
    for (size_t i = 0; i < openOutputs.size(); i++) {
        ALOGVV("output %zu isDuplicated=%d device=%s",
                i, openOutputs.valueAt(i)->isDuplicated(),
                openOutputs.valueAt(i)->supportedDevices().toString().c_str());
        if (openOutputs.valueAt(i)->supportsAllDevices(devices)
                && openOutputs.valueAt(i)->devicesSupportEncodedFormats(devices.types())) {
            ALOGVV("%s() found output %d", __func__, openOutputs.keyAt(i));
            outputs.add(openOutputs.keyAt(i));
        }
    }
    return outputs;
}

6.2.4 selectOutput

audio_io_handle_t selectOutput(const SortedVector<audio_io_handle_t>& outputs,
                                       audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
                                       audio_format_t format = AUDIO_FORMAT_INVALID,
                                       audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE,
                                       uint32_t samplingRate = 0);

audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_handle_t>& outputs,
                                                       audio_output_flags_t flags,
                                                       audio_format_t format,
                                                       audio_channel_mask_t channelMask,
                                                       uint32_t samplingRate)
{
    audio_io_handle_t primary_output = 0;
    bool isCts = getAppMaskByName(callingAppName) & APP_TYPE_CTS_AUDIOPRO ? true : false;

    LOG_ALWAYS_FATAL_IF(!(format == AUDIO_FORMAT_INVALID || audio_is_linear_pcm(format)),
        "%s called with format %#x", __func__, format);

    // Flags disqualifying an output: the match must happen before calling selectOutput()
    static const audio_output_flags_t kExcludedFlags = (audio_output_flags_t)
        (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT);

    // Flags expressing a functional request: must be honored in priority over
    // other criteria
    static const audio_output_flags_t kFunctionalFlags = (audio_output_flags_t)
        (AUDIO_OUTPUT_FLAG_VOIP_RX | AUDIO_OUTPUT_FLAG_INCALL_MUSIC |
            AUDIO_OUTPUT_FLAG_TTS | AUDIO_OUTPUT_FLAG_DIRECT_PCM | AUDIO_OUTPUT_FLAG_VIRTUAL_DEEP_BUFFER);
    // Flags expressing a performance request: have lower priority than serving
    // requested sampling rate or channel mask
    static const audio_output_flags_t kPerformanceFlags = (audio_output_flags_t)
        (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_DEEP_BUFFER |
            AUDIO_OUTPUT_FLAG_RAW | AUDIO_OUTPUT_FLAG_SYNC);

    const audio_output_flags_t functionalFlags =
        (audio_output_flags_t)(flags & kFunctionalFlags);
    const audio_output_flags_t performanceFlags =
        (audio_output_flags_t)(flags & kPerformanceFlags);

    audio_io_handle_t bestOutput = (outputs.size() == 0) ? AUDIO_IO_HANDLE_NONE : outputs[0];

    // select one output among several that provide a path to a particular device or set of
    // devices (the list was previously build by getOutputsForDevices()).
    // The priority is as follows:
    // 1: the output supporting haptic playback when requesting haptic playback
    // 2: the output with the highest number of requested functional flags
    // 3: the output supporting the exact channel mask
    // 4: the output with a higher channel count than requested
    // 5: the output with a higher sampling rate than requested
    // 6: the output with the highest number of requested performance flags
    // 7: the output with the bit depth the closest to the requested one
    // 8: the primary output
    // 9: the first output in the list

    // matching criteria values in priority order for best matching output so far
    std::vector<uint32_t> bestMatchCriteria(8, 0);

    const uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
    const uint32_t hapticChannelCount = audio_channel_count_from_out_mask(
        channelMask & AUDIO_CHANNEL_HAPTIC_ALL);

    for (audio_io_handle_t output : outputs) {
        sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
        // matching criteria values in priority order for current output
        std::vector<uint32_t> currentMatchCriteria(8, 0);

        if (outputDesc->isDuplicated()) {
            continue;
        }
        if ((kExcludedFlags & outputDesc->mFlags) != 0) {
            continue;
        }

        // If haptic channel is specified, use the haptic output if present.
        // When using haptic output, same audio format and sample rate are required.
        const uint32_t outputHapticChannelCount = audio_channel_count_from_out_mask(
            outputDesc->getChannelMask() & AUDIO_CHANNEL_HAPTIC_ALL);
        if ((hapticChannelCount == 0) != (outputHapticChannelCount == 0)) {
            continue;
        }
        if (outputHapticChannelCount >= hapticChannelCount
            && format == outputDesc->getFormat()
            && samplingRate == outputDesc->getSamplingRate()) {
                currentMatchCriteria[0] = outputHapticChannelCount;
        }

        // functional flags match
        currentMatchCriteria[1] = popcount(outputDesc->mFlags & functionalFlags);

        // channel mask and channel count match
        uint32_t outputChannelCount = audio_channel_count_from_out_mask(
                outputDesc->getChannelMask());
        if (channelMask != AUDIO_CHANNEL_NONE && channelCount > 2 &&
            channelCount <= outputChannelCount) {
            if ((audio_channel_mask_get_representation(channelMask) ==
                    audio_channel_mask_get_representation(outputDesc->getChannelMask())) &&
                    ((channelMask & outputDesc->getChannelMask()) == channelMask)) {
                currentMatchCriteria[2] = outputChannelCount;
            }
            currentMatchCriteria[3] = outputChannelCount;
        }

        // sampling rate match
        if (samplingRate > SAMPLE_RATE_HZ_DEFAULT &&
                samplingRate <= outputDesc->getSamplingRate()) {
            currentMatchCriteria[4] = outputDesc->getSamplingRate();
        }

        // performance flags match
        currentMatchCriteria[5] = popcount(outputDesc->mFlags & performanceFlags);

        // format match
        if (format != AUDIO_FORMAT_INVALID) {
            currentMatchCriteria[6] =
                PolicyAudioPort::kFormatDistanceMax -
                PolicyAudioPort::formatDistance(format, outputDesc->getFormat());
        }

        // primary output match
        currentMatchCriteria[7] = outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY;
        if (currentMatchCriteria[7])
            primary_output = output;

        // compare match criteria by priority then value
        if (std::lexicographical_compare(bestMatchCriteria.begin(), bestMatchCriteria.end(),
                currentMatchCriteria.begin(), currentMatchCriteria.end())) {
            bestMatchCriteria = currentMatchCriteria;
            bestOutput = output;

            std::stringstream result;
            std::copy(bestMatchCriteria.begin(), bestMatchCriteria.end(),
                std::ostream_iterator<int>(result, " "));
            ALOGV("%s new bestOutput %d criteria %s",
                __func__, bestOutput, result.str().c_str());
        }
    }

    {
        //only cts use ull, the others use primary output
        //if do not have ull profile(audio_policy_configuration.xml), cannot create ull desc.
        //so it must create ull output first
        sp<SwAudioOutputDescriptor> outputDescPrimary = mOutputs.valueFor(bestOutput);
        if (outputDescPrimary != nullptr && (outputDescPrimary->mFlags == (AUDIO_OUTPUT_FLAG_FAST|AUDIO_OUTPUT_FLAG_RAW))
                     && !isCts && primary_output != 0) {
            bestOutput = primary_output;
        }
    }

    return bestOutput;
}

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值