接着上一篇AudioPolicyService代码,目录:
E:\liuzhibao\android\android\frameworks\av\services\audioflinger
直接看代码:主要看构造函数内:
// ----------------------------------------------------------------------------
AudioPolicyService::AudioPolicyService()
: BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL)
{
char value[PROPERTY_VALUE_MAX];
const struct hw_module_t *module;
int forced_val;
int rc;
Mutex::Autolock _l(mLock);
// start tone playback thread
mTonePlaybackThread = new AudioCommandThread(String8(""));
// start audio commands thread
mAudioCommandThread = new AudioCommandThread(String8("ApmCommand"));
/* instantiate the audio policy manager */
rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
if (rc)
return;
rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
if (rc)
return;
rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
&mpAudioPolicy);
ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
if (rc)
return;
rc = mpAudioPolicy->init_check(mpAudioPolicy);
ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
if (rc)
return;
ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);
// load audio pre processing modules
if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
loadPreProcessorConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
} else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
loadPreProcessorConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
}
}
其中:
// start tone playback thread
mTonePlaybackThread = new AudioCommandThread(String8(""));
// start audio commands thread
mAudioCommandThread = new AudioCommandThread(String8("ApmCommand"));
这里面的AudioCommandThread : 所有的命令(音量控制,输入、输出的切换等)最终都会在该线程中排队执行.
下面有一个对应HAL的结构体:
const struct hw_module_t *module;
对应一共是三个:
struct hw_module_t;
struct hw_module_methods_t;
struct hw_device_t;
对应开发的需要调整,比如,如果是一个led灯的控制,可以改如下:
struct led_module_t;
struct led_module_methods_t;
struct led_device_t;
这几个结构体的定义是在hardware.h中,有兴趣的,也必须要要看这几个结构体的作用,因为library层全部要用,不看懂完全都不知道这三个家伙是干什么的,也可以查看网上面关于HAL开发文章,还是比较简单的,主要是它有一套规则,定义方式基本上是死的.如果自己需要改的话,可以调整:
struct *_module_t;
struct *_module_methods_t;
struct *_device_t;
*改成你的设备名称,如上面的led等控制,这样library库层就可以直接使用调用了,这个library库层的开发和linux的设备使用开发基本上是一样的,打开设备,控制设备,读写设备.具体可以详读:Android深度探索这本书.
继续看代码
rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
打开设备:
rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
if (rc)
return;
上面还好,最重要的一句话:
rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
&mpAudioPolicy);
其中:
struct audio_policy_device *mpAudioPolicyDev;
audio_policy这是一个类似虚拟设备,它在linux并没有驱动节点,但是它又是类似一个linux驱动节点:程序可以查看Audio_policy.cpp,你会发现生成的audio_policy.default.so文件:
想上个图片,可以用adb 到/system/lib/hw下面看到有audio_policy.default.so这个东东了
typedef struct audio_policy_module {
struct hw_module_t common;
} audio_policy_module_t;
struct audio_policy_device {
struct hw_device_t common;
int (*create_audio_policy)(const struct audio_policy_device *device,
struct audio_policy_service_ops *aps_ops,
void *service,
struct audio_policy **ap);
int (*destroy_audio_policy)(const struct audio_policy_device *device,
struct audio_policy *ap);
};
看了上面的就知道了它也是个类似HAL访问驱动节点的,不过它是虚拟的.
那么上面那个create_audio_policy(...)就要查看HAL层的Audio_policy.c文件
static int legacy_ap_dev_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
struct legacy_ap_device *dev;
if (strcmp(name, AUDIO_POLICY_INTERFACE) != 0)
return -EINVAL;
dev = (struct legacy_ap_device *)calloc(1, sizeof(*dev));
if (!dev)
return -ENOMEM;
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = 0;
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = legacy_ap_dev_close;
dev->device.create_audio_policy = create_legacy_ap;
dev->device.destroy_audio_policy = destroy_legacy_ap;
*device = &dev->device.common;
return 0;
}
上面的一看create_audio_policy实际上调用的是create_legacy_ap函数,感觉这个HAL不是去体验linux层的驱动节点,而是做了一下转手,那么该函数:
static int create_legacy_ap(const struct audio_policy_device *device,
struct audio_policy_service_ops *aps_ops,
void *service,
struct audio_policy **ap)
函数里面程序有点多,截取其中一段关心的:
lap->aps_ops = aps_ops;
lap->service_client =
new AudioPolicyCompatClient(aps_ops, service);
if (!lap->service_client) {
ret = -ENOMEM;
goto err_new_compat_client;
}
lap->apm = createAudioPolicyManager(lap->service_client);
if (!lap->apm) {
ret = -ENOMEM;
goto err_create_apm;
}
*ap = &lap->policy;
一看上面的AudioPolicyCompatClient,AudioPolicyManager创建,感觉绕了这么一大圈,从HAL层又有点绕上来了.
继续看AudioPolicyManager这个类,先看它的头文件AudioPolicyManager.h,原来它又是继承了AudioPolicyManagerBase这个类的:
class AudioPolicyManager: public AudioPolicyManagerBase
看一下它的构造函数,想所有的人都非常关注,上面既然是个虚拟设备,那总的调用实际设备吧,那么这里面就开始了:
mA2dpDeviceAddress = String8("");
mScoDeviceAddress = String8("");
mUsbCardAndDevice = String8("");
if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {
if (loadAudioPolicyConfig(AUDIO_POLICY_CONFIG_FILE) != NO_ERROR) {
ALOGE("could not load audio policy configuration file, setting defaults");
defaultAudioPolicyConfig();
}
}
其中上面那个AudioPolicyConfig配置参数:Audio_policy_conf.h文件中
#define AUDIO_POLICY_CONFIG_FILE "/system/etc/audio_policy.conf"
#define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf"
这就是很多网友提到的audio设备配置.就是在这里面进行加载.conf文件大致内容:
# Global configuration section: lists input and output devices always present on the device
# as well as the output device selected by default.
# Devices are designated by a string that corresponds to the enum in audio.h
global_configuration {
attached_output_devices AUDIO_DEVICE_OUT_SPEAKER
default_output_device AUDIO_DEVICE_OUT_SPEAKER
attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC
}
# audio hardware module section: contains descriptors for all audio hw modules present on the
# device. Each hw module node is named after the corresponding hw module library base name.
# For instance, "primary" corresponds to audio.primary.<device>.so.
# The "primary" module is mandatory and must include at least one output with
# AUDIO_OUTPUT_FLAG_PRIMARY flag.
# Each module descriptor contains one or more output profile descriptors and zero or more
# input profile descriptors. Each profile lists all the parameters supported by a given output
# or input stream category.
# The "channel_masks", "formats", "devices" and "flags" are specified using strings corresponding
# to enums in audio.h and audio_policy.h. They are concatenated by use of "|" without space or "\n".
audio_hw_modules {
primary {
outputs {
primary {
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET|AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET|AUDIO_DEVICE_OUT_ALL_SCO
flags AUDIO_OUTPUT_FLAG_PRIMARY
}
hdmi {
sampling_rates dynamic
channel_masks dynamic
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_AUX_DIGITAL
flags AUDIO_OUTPUT_FLAG_DIRECT
}
bt {
sampling_rates 8000
channel_masks AUDIO_CHANNEL_OUT_MONO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_ALL_SCO
flags AUDIO_OUTPUT_FLAG_DIRECT
}
usb {
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET|AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET
flags AUDIO_OUTPUT_FLAG_DIRECT
}
}
inputs {
primary {
sampling_rates 8000|11025|16000|22050|24000|32000|44100|48000
channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_USB_DEVICE|AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET|AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET
}
}
}
a2dp {
outputs {
a2dp {
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_ALL_A2DP
}
}
}
r_submix {
outputs {
submix {
sampling_rates 44100|48000
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX
}
}
inputs {
submix {
sampling_rates 44100|48000
channel_masks AUDIO_CHANNEL_IN_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_IN_REMOTE_SUBMIX
}
}
}
usb {
outputs {
usb_accessory {
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_USB_ACCESSORY
}
usb_device {
sampling_rates 44100
channel_masks AUDIO_CHANNEL_OUT_STEREO
formats AUDIO_FORMAT_PCM_16_BIT
devices AUDIO_DEVICE_OUT_USB_DEVICE
}
}
}
}
回到前面的代码AudioPolicyManagerBase,下面就是加载所有的设备,并且打开它们各自的流:
// open all output streams needed to access attached devices
for (size_t i = 0; i < mHwModules.size(); i++) {
mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->mName);
if (mHwModules[i]->mHandle == 0) {
ALOGW("could not open HW module %s", mHwModules[i]->mName);
continue;
}
// open all output streams needed to access attached devices
for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
{
const IOProfile *outProfile = mHwModules[i]->mOutputProfiles[j];
if (outProfile->mSupportedDevices & mAttachedOutputDevices && !(outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(outProfile);
outputDesc->mDevice = (audio_devices_t)(mDefaultOutputDevice &
outProfile->mSupportedDevices);
audio_io_handle_t output = mpClientInterface->openOutput(
outProfile->mModule->mHandle,
&outputDesc->mDevice,
&outputDesc->mSamplingRate,
&outputDesc->mFormat,
&outputDesc->mChannelMask,
&outputDesc->mLatency,
outputDesc->mFlags);
打开所有的设备,并且等待对应的数据流进行处理,那么还需要提供一个策略方式,不可能一个数据过来了,所有的output设备都去播放,那speaker,receiver,蓝牙(如果连上)都会同时播放出声音,那不是很混乱.
这里提供了一个策略:算是默认的.
updateDevicesAndOutputs();
... ...
走完上面一路下来,重要需要注意的是上面那个虚拟设备的地方,绕了一个大弯,因为一般情况下,我们遇到下面结构体以后,都会认为要去linux的驱动设备节点了:
struct hw_module_t;
struct hw_module_methods_t;
struct hw_device_t;
但是上面很显然没有.
Binder呢??
这个在Android Audio起着非常重要的作用,但是没有太多好说的,因为Audio就是用binder的机制:主要的感觉是在数据memory的分配,释放,以及对象的"复制",这个复制不知道准不准确啊.下次看看.