接着上一篇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的分配,释放,以及对象的"复制",这个复制不知道准不准确啊.下次看看.