[RK3399][Android7.1] 音频中audio_policy.conf的作用

RK3399 同时被 2 个专栏收录
180 篇文章 34 订阅
72 篇文章 15 订阅

Platform: RK3399
OS: Android 7.1
Kernel: v4.4.83

文件内容:

按模块划分,比如primary,a2dp, usb…
模块里包含硬件设备支持的参数,比如采样率、通道数、数据位深。

audio_hw_modules {
  primary {
    outputs {
      primary {
        sampling_rates  44100|48000
        channel_masks AUDIO_CHANNEL_OUT_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_SPDIF
        flags AUDIO_OUTPUT_FLAG_PRIMARY
      }
      hdmi {
        sampling_rates 44100|48000|192000
        channel_masks AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_7POINT1
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_AUX_DIGITAL
        flags AUDIO_OUTPUT_FLAG_DIRECT
      }
    }
  }

  a2dp {
    outputs {
      a2dp {
        sampling_rates 44100
        channel_masks AUDIO_CHANNEL_OUT_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_ALL_A2DP
      }
    }
  }
 }

生成目录:

一般有两个地方:

#define AUDIO_POLICY_CONFIG_FILE "/system/etc/audio_policy.conf"
#define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf"

一般它都是存在/system/etc/下。


代码加载位置:

AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface) {
......
	//先看/vendor/etc/有没有
    if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {
		//再看/system/etc/有没有
        if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {
            ALOGE("could not load audio policy configuration file, setting defaults");
            //没有就不用config文件,直接加载默认的配置了。
            defaultAudioPolicyConfig();
        }
    }
......
}

默认配置:

void AudioPolicyManagerBase::defaultAudioPolicyConfig(void)
{
    HwModule *module;
    IOProfile *profile;

    mDefaultOutputDevice = AUDIO_DEVICE_OUT_SPEAKER;
    mAttachedOutputDevices = AUDIO_DEVICE_OUT_SPEAKER;
    mAvailableInputDevices = AUDIO_DEVICE_IN_BUILTIN_MIC & ~AUDIO_DEVICE_BIT_IN;
	//默认使用primary模块
    module = new HwModule("primary");

	//不管是输入还是输出都是以profile的形式保存
    profile = new IOProfile(module);
    profile->mSamplingRates.add(44100);
    profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT);
    profile->mChannelMasks.add(AUDIO_CHANNEL_OUT_STEREO);
    profile->mSupportedDevices = AUDIO_DEVICE_OUT_SPEAKER;
    profile->mFlags = AUDIO_OUTPUT_FLAG_PRIMARY;
    module->mOutputProfiles.add(profile);
	
    profile = new IOProfile(module);
    profile->mSamplingRates.add(8000);
    profile->mFormats.add(AUDIO_FORMAT_PCM_16_BIT);
    profile->mChannelMasks.add(AUDIO_CHANNEL_IN_MONO);
    profile->mSupportedDevices = AUDIO_DEVICE_IN_BUILTIN_MIC;
    module->mInputProfiles.add(profile);

    mHwModules.add(module);
}

音频模块加载:

系统有不同的音频模块,比如primary,a2dp,usb等,每个模块对应有独立的so.如:

kris@eco:~/rk3399/out/target/product/rk3399_mid/system/vendor/lib/hw$ ls
audio.primary.rk30board.so
kris@eco:~/rk3399/out/target/product/rk3399_mid/system/lib/hw$ ls audio*
audio.a2dp.default.so audio.primary.default.so audio.usb.default.so
audio_policy.default.so audio.r_submix.default.so audio.vr_bee_hidraw.default.s

库名字的形式是 audio.<a2dp/primary/usb>.<device/default>.so这样,优先加载名字是device的so,
没有的话再加载default so。

库是否加载取决于audio_policy.conf中是否有配置,从上面的代码中看出 audio.primary.<default/device>.so肯定要加载!


模块的动态选择:

当前使用哪个模块取决于上层参数的选择,比如拿录音举例:
代码会根据当前app使用的stream type确定对应的device

audio_devices_t AudioPolicyManagerBase::getDeviceForInputSource(int inputSource)
{
......
	case AUDIO_SOURCE_VOICE_RECOGNITION:
    case AUDIO_SOURCE_HOTWORD:
    case AUDIO_SOURCE_VOICE_COMMUNICATION:
        if (mForceUse[AudioSystem::FOR_RECORD] == AudioSystem::FORCE_BT_SCO &&
            mAvailableInputDevices & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
            device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
        } else if (mAvailableInputDevices & AUDIO_DEVICE_IN_WIRED_HEADSET) {
            device = AUDIO_DEVICE_IN_WIRED_HEADSET;
        } else if (mAvailableInputDevices & AUDIO_DEVICE_IN_USB_DEVICE) {
            device = AUDIO_DEVICE_IN_USB_DEVICE;
        } else if (mAvailableInputDevices & AUDIO_DEVICE_IN_BUILTIN_MIC) {
			//比如在audio_policy.conf中配置了
            device = AUDIO_DEVICE_IN_BUILTIN_MIC;
        }
        break;
......
}

选择模块中对应的profile:

AudioPolicyManagerBase::IOProfile *AudioPolicyManagerBase::getInputProfile(audio_devices_t device,
                                                   uint32_t samplingRate,
                                                   audio_format_t format,
                                                   audio_channel_mask_t channelMask)
{
    // Choose an input profile based on the requested capture parameters: select the first available
    // profile supporting all requested parameters.
    for (size_t i = 0; i < mHwModules.size(); i++)
    {
		......
        for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++)
        {
            IOProfile *profile = mHwModules[i]->mInputProfiles[j];
            // profile->log();
            if (profile->isCompatibleProfile(device, samplingRate, format,
                                             channelMask, AUDIO_OUTPUT_FLAG_NONE)) {
                return profile;
            }
        }
    }
    return NULL;
}

匹配规则:

bool AudioPolicyManagerBase::IOProfile::isCompatibleProfile(...) const
{
    if (samplingRate == 0 || !audio_is_valid_format(format) || channelMask == 0) {
         return false;
     }

     if ((mSupportedDevices & device) != device) {
         return false;
     }
     if ((mFlags & flags) != flags) {
         return false;
     }
     size_t i;
     for (i = 0; i < mSamplingRates.size(); i++)
     {
         if (mSamplingRates[i] == samplingRate) {
             break;
         }
     }
     if (i == mSamplingRates.size()) {
         return false;
     }
     for (i = 0; i < mFormats.size(); i++)
     {
         if (mFormats[i] == format) {
             break;
         }
     }
     if (i == mFormats.size()) {
         return false;
     }
     for (i = 0; i < mChannelMasks.size(); i++)
     {
         if (mChannelMasks[i] == channelMask) {
             break;
         }
     }
     if (i == mChannelMasks.size()) {
         return false;
     }
     return true;
}

也就是说app设置的参数,不仅仅是device,还有采样率,格式和通道数要和audio_policy.conf的某个output/input完全匹配才可以。


参考:

audio_policy.conf文件分析

  • 3
    点赞
  • 2
    评论
  • 13
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页

打赏作者

KrisFei

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值