![](https://img-blog.csdnimg.cn/20210612162024414.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTI5MDYxMjI=,size_16,color_FFFFFF,t_70)
切入点:
AF和APS系统第一次起来后,到底干了什么。
检测到耳机插入事件后,AF和APS的处理。
1 AudioFlinger-instantiate
AF和APS的诞生
int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
//先创建AF
AudioFlinger::instantiate();
//再创建APS
AudioPolicyService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
2 AudioHardwareInterface-create
AudioFlinger::AudioFlinger()
: BnAudioFlinger(),//基类构造函数
mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextThreadId(0)
{
mHardwareStatus = AUDIO_HW_IDLE;
//创建audio的HAL代表
mAudioHardware = AudioHardwareInterface::create();
mHardwareStatus = AUDIO_HW_INIT;
if (mAudioHardware->initCheck() == NO_ERROR) {
setMode(AudioSystem::MODE_NORMAL);
setMasterVolume(1.0f);
setMasterMute(false);
}
}
AF创建了一个AudioHardware的HAL对象。注意整个系统就这一个AudioHardware了。也就是说,不管是线控耳机,蓝牙耳机,麦克,外放等等,最后都会由这一个HAL统一管理。
3 AudioPolicyService-instantiate
AudioPolicyService::AudioPolicyService()
: BnAudioPolicyService() , mpPolicyManager(NULL)
{
// mpPolicyManager 策略管理器
char value[PROPERTY_VALUE_MAX];
mTonePlaybackThread = new AudioCommandThread(String8(""));
mAudioCommandThread = new AudioCommandThread(String8("ApmCommandThread"));
#if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)
// 注意AudioPolicyManagerBase的构造函数,把this传进去了。
mpPolicyManager = new AudioPolicyManagerBase(this);
#else
...
#endif
// 根据系统属性来判断摄像机是否强制使用声音。这个...为什么会放在这里?
// 手机带摄像机好像刚出来的时候,为了防止偷拍,强制按快门的时候必须发出声音
property_get("ro.camera.sound.forced", value, "0");
mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
}
AudioPolicyManagerBase的构造函数可是把APS传进去了,看来又会有一些回调靠APS了。
4 new AudioPolicyManagerBase
这是重点!
AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
: mPhoneState(AudioSystem::MODE_NORMAL), ---->这里有电话的状态?
mRingerMode(0),
mMusicStopTime(0),
mLimitRingtoneVolume(false)
{
mpClientInterface = clientInterface; //BT,保存APS对象。
for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {
mForceUse[i] = AudioSystem::FORCE_NONE;
}
...
// 下面这个意思就是把几种for_use的情况使用的设备全部置为NONE。
// 比如设置FOR_MEDIA的场景,使用的设备就是FORCE_NONE
for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {
mForceUse[i] = AudioSystem::FORCE_NONE;
}
// 目前可以的输出设备:耳机和外放
mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE | AudioSystem::DEVICE_OUT_SPEAKER;
// 目前可用的输入设备,内置MIC
mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;
// 注意这里是OR操作符,最终mAvailableOutputDevices = 0X3
mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE | AudioSystem::DEVICE_OUT_SPEAKER;
// 目前可用的输入设备,内置MIC,mAvailableInputDevices为0x4000,不过我们不关注input
mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;
...
// 创建一个AudioOutputDescriptor,并设置它的device为外设0x2
AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
// 调用APS的openOutput,得到一个mHardwareOutput。这是个int型
// 而且,下面的参数都是指针类型(flags除外),难道?有人会改value吗?
mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
&outputDesc->mSamplingRate,
&outputDesc->mFormat,
&outputDesc->mChannels,
&outputDesc->mLatency,
outputDesc->mFlags);
// 把int和指针加入到一个map了,方便管理。
addOutput(mHardwareOutput, outputDesc);
setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, true);
updateDeviceForStrategy();
}
下面是audio_mode的定义。
enum audio_mode {
MODE_INVALID = -2, //无效mode
MODE_CURRENT = -1,//当前mode,和音频设备的切换(路由)有关
MODE_NORMAL = 0,//正常mode,没有电话和铃声
MODE_RINGTONE,//收到来电信号了,此时会有铃声
MODE_IN_CALL,//电话mode,这里表示已经建立通话了
NUM_MODES // Android大量采用这种技巧来表示枚举结束了。
};
forced_config,强制_配置,看名字好像是强制使用设备吧,比如外放,耳机,蓝牙等。
enum forced_config {
FORCE_NONE,
FORCE_SPEAKER,
FORCE_HEADPHONES,
FORCE_BT_SCO,
FORCE_BT_A2DP,
FORCE_WIRED_ACCESSORY,
FORCE_BT_CAR_DOCK,
FORCE_BT_DESK_DOCK,
NUM_FORCE_CONFIG,
FORCE_DEFAULT = FORCE_NONE
};
enum force_use {
FOR_COMMUNICATION, //这里是for_xxx,不是force_xxx。
FOR_MEDIA,
FOR_RECORD,
FOR_DOCK,
NUM_FORCE_USE
};
来看看AudioSystem是怎么定义输入输出设备:
enum audio_devices {
// output devices
DEVICE_OUT_EARPIECE = 0x1,
DEVICE_OUT_SPEAKER = 0x2,
DEVICE_OUT_WIRED_HEADSET = 0x4,
DEVICE_OUT_WIRED_HEADPHONE = 0x8,
DEVICE_OUT_BLUETOOTH_SCO = 0x10,
DEVICE_OUT_BLUETOOTH_SCO_HEADSET = 0x20,
DEVICE_OUT_BLUETOOTH_SCO_CARKIT = 0x40,
DEVICE_OUT_BLUETOOTH_A2DP = 0x80,
DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER = 0x200,
DEVICE_OUT_AUX_DIGITAL = 0x400,
DEVICE_OUT_DEFAULT = 0x8000,
DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADSET | DEVICE_OUT_WIRED_HEADPHONE | DEVICE_OUT_BLUETOOTH_SCO | DEVICE_OUT_BLUETOOTH_SCO_HEADSET | DEVICE_OUT_BLUETOOTH_SCO_CARKIT |
DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER | DEVICE_OUT_AUX_DIGITAL | DEVICE_OUT_DEFAULT),
DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP |
DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER),
// input devices
DEVICE_IN_COMMUNICATION = 0x10000,
DEVICE_IN_AMBIENT = 0x20000,
DEVICE_IN_BUILTIN_MIC = 0x40000,
DEVICE_IN_BLUETOOTH_SCO_HEADSET = 0x80000,
DEVICE_IN_WIRED_HEADSET = 0x100000,
DEVICE_IN_AUX_DIGITAL = 0x200000,
DEVICE_IN_VOICE_CALL = 0x400000,
DEVICE_IN_BACK_MIC = 0x800000,
DEVICE_IN_DEFAULT = 0x80000000,
DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION | DEVICE_IN_AMBIENT |
DEVICE_IN_BUILTIN_MIC |DEVICE_IN_BLUETOOTH_SCO_HEADSET | DEVICE_IN_WIRED_HEADSET |
DEVICE_IN_AUX_DIGITAL | DEVICE_IN_VOICE_CALL | DEVICE_IN_BACK_MIC |
DEVICE_IN_DEFAULT)
};
5 mForceUse[i] = AudioSystem-FORCE_NONE
6 new AudioOutputDescriptor
AudioOutputDescriptor:
描述audio输出的,可以用来保存一些配置信息。跟踪音频stream类型使用这个output的一些情况。
AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor()
: mId(0), mSamplingRate(0), mFormat(0), mChannels(0), mLatency(0),
mFlags((AudioSystem::output_flags)0), mDevice(0), mOutput1(0), mOutput2(0)
{}
7 mpClientInterface-openOutput
audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices,
uint32_t *pSamplingRate,
uint32_t *pFormat,
uint32_t *pChannels,
uint32_t *pLatencyMs,
AudioSystem::output_flags flags)
{
sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
return af->openOutput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, pLatencyMs, flags);
}
8 AudioSystem-get_audio_flinger
9 af-openOutput
int AudioFlinger::openOutput(uint32_t *pDevices,
uint32_t *pSamplingRate,
uint32_t *pFormat,
uint32_t *pChannels,
uint32_t *pLatencyMs,
uint32_t flags)
{
// 我们思考下传进来的值吧,*pDevices=0x2,代表外放,其他都是0。
status_t status;
PlaybackThread *thread = NULL;
mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
uint32_t format = pFormat ? *pFormat : 0;
uint32_t channels = pChannels ? *pChannels : 0;
uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
Mutex::Autolock _l(mLock);
// HAL对象得到一个AudioStreamOut,传进去的值会改吗?
AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,
(int *)&format,
&channels,
&samplingRate,
&status);
mHardwareStatus = AUDIO_HW_IDLE;
if (output != 0) {
// 那几个值变成:format为PCM_16_BIT,channels为2,samplingRate为44100
// 这样的话,那只能走else分支了。
if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
(format != AudioSystem::PCM_16_BIT) ||
(channels != AudioSystem::CHANNEL_OUT_STEREO)) {
thread = new DirectOutputThread(this, output, ++mNextThreadId);
} else {
// 原来open一个Output,就会在AF中创建一个混音线程。设计得真好。
// 所有设置为外放的程序,它的输出都是这个外放stream混音线程来工作。
// 所有设置为耳机的程序,它的输出都是这个耳机stream混音线程来完成。
// 为什么对stream特加强调呢,没看见我们调用的是mAudioHardware->openOutputStream(0x2,,,)嘛。返回的是一个AudioStreamOut,可不是设备喔。
// Android把这些个东西都交给HAL层去实现了。不用自己来管理系统上有什么耳机,外设,蓝牙真实设备之类的东东,它反正用AudioStreamOut来表示它想要的就可以了。
thread = new MixerThread(this, output, ++mNextThreadId);
}
// 好了,又多得了一个线程,
mPlaybackThreads.add(mNextThreadId, thread);
if (pSamplingRate) *pSamplingRate = samplingRate;
if (pFormat) *pFormat = format;
if (pChannels) *pChannels = channels;
if (pLatencyMs) *pLatencyMs = thread->latency();
// 从这里返回的是混音线程的索引。
return mNextThreadId;
}
// 如果没创建成功线程,则返回零。
return 0;
}
10 mAudioHardware-openOutputStream
11 new MixerThread
12 setOutputDevice
void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t device, bool force, int delayMs)
{
// 注意我们的参数:
// output = 1,
// device为AudioSystem::DEVICE_OUT_SPEAKER
// force为true,delayMs用默认值0
AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
if (outputDesc->isDuplicated()) {
setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs);
setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs);
return;
}
// prevDevice:0X3,外放|耳机
uint32_t prevDevice = (uint32_t)outputDesc->device();
// 现在设置的是外设
if ((device == 0 || device == prevDevice) && !force) {
return;
}
// 设置这个outputDesc为外放
outputDesc->mDevice = device;
// popCount为2,因为device=0x2=0010
// 另外,我对下面这个output== mHardwareOutput尤其感兴趣。
// mHardwareOutput实际上是AF返回的一个线程索引,那AMB怎么根据这样一个东西来管理所有的线程呢?果然,这里就比较了output是不是等于最初创建的线程索引。
// 这就表明,虽然只有这么一个mHardwareOutput,但实际上还是能够操作其他output的!
if (output == mHardwareOutput && AudioSystem::popCount(device) == 2) {
setStrategyMute(STRATEGY_MEDIA, true, output);
usleep(outputDesc->mLatency*2*1000);
}
// 说我们要设置路由,新的输出设备为外放
// 等我们以后讲由外放切换到耳机,再来看这个问题。
AudioParameter param = AudioParameter();
param.addInt(String8(AudioParameter::keyRouting), (int)device);
mpClientInterface->setParameters(mHardwareOutput, param.toString(), delayMs);
// update stream volumes according to new device
applyStreamVolumes(output, device, delayMs);
// if changing from a combined headset + speaker route, unmute media streams
if (output == mHardwareOutput && AudioSystem::popCount(prevDevice) == 2) {
// 这里把media的音量置为0。以后再说。
setStrategyMute(STRATEGY_MEDIA, false, output, delayMs);
}
}
这个调用,更新了mHardwareOutput对应的输出路由设备,而且还发了一个命令给APS,要更新对应混音线程的输出路由设备。
13 mpClientInterface-setParameters
14 setStrategyMute
15 updateDeviceForStrategy
void AudioPolicyManagerBase::updateDeviceForStrategy()
{
for (int i = 0; i < NUM_STRATEGIES; i++) {
mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false);
}
}
表明各种策略下使用的对应设备也准备好了。
NUM_STRATEGIES在hardware/libhardware_legacy/include/hardware_legacy/AudioPolicyManagerBase.h中定义。
enum routing_strategy {
STRATEGY_MEDIA,
STRATEGY_PHONE, //通话音
STRATEGY_SONIFICATION,//除了其他三个外的,可以是铃声,提醒声等。
STRATEGY_DTMF, //拨号音
NUM_STRATEGIES
};
16 getDeviceForStrategy
为各种策略找到它对应的设备。
uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache)
{
// fromCache为false
uint32_t device = 0;
switch (strategy) {
case STRATEGY_DTMF:
if (mPhoneState != AudioSystem::MODE_IN_CALL) {
// 如果在打电话过程中,你再按按键,则和MEDIA走一个设备
device = getDeviceForStrategy(STRATEGY_MEDIA, false);
break;
}
// 注意这里没有break,所以在其他mode下,DTMF和PHONE用一个策略
case STRATEGY_PHONE:
// 还得判断用户是不是强制使用了输出设备。
switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) {
case AudioSystem::FORCE_BT_SCO:
if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
if (device) break;
}
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO;
if (device) break;
// if SCO device is requested but no SCO device is available, fall back to default case
// FALL THROUGH
// 我们还记得强制设置那里吗?对了,此时都是FORCE_NONE。而且,mAvailableOutputDevices是0X3 (外放|耳机)
default: // FORCE_NONE
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
if (device) break;
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
if (device) break;
// 看,下面这句会成立。啥意思?如果有耳机的话,那么输出设备就是耳机
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE;
break;
// 再验证下我们刚才说的,如果强制使用外放的话,
case AudioSystem::FORCE_SPEAKER:
if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
if (device) break;
}
// 果然,会强制使用外放。
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
break;
}
break;
case STRATEGY_SONIFICATION: // 分析方法同上
if (mPhoneState == AudioSystem::MODE_IN_CALL) {
device = getDeviceForStrategy(STRATEGY_PHONE, false);
break;
}
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
// 同样没有break,说明SONIFICATION受MEDIA策略影响。
case STRATEGY_MEDIA: {
uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
}
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
}
// 可惜,上面那些高级设备我们都没有
if (device2 == 0) {
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
}
// 假设我们没有从SONIFICATION下来,那么device最终会 = DEVICE_OUT_SPEAKER。
// 假设我们从SONIFICATION下来,那么device还是等于DEVICE_OUT_SPEAKER
device |= device2;
}
break;
default:
break;
}
return device;
}
AudioPolicy总结:
1 AF创建了一个代表HAL对象的东西
2 APS创建了两个AudioCommandThread,一个用来处理命令,一个用来播放tone。我们还没看。
3 APS同时会创建AudioManagerBase,做为系统默认的音频管理
4 AMB集中管理了策略上面的事情,同时会在AF的openOutput中创建一个混音线程。同时,AMB会更新一些策略上的安排。
另外,我们分析的AMB是Generic的,但不同厂商可以实现自己的策略。