我的书:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs4WOXl1bOdVYv50MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzEzMxETN0QTMwIDNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
购买链接:
京东购买链接
淘宝购买链接
当当购买链接
AudioFlinger创建
./frameworks/av/media/mediaserver/main_mediaserver.cpp:
47 int main(int argc __unused, char** argv)
48 {
...
135: AudioFlinger::instantiate();
139 AudioPolicyService::instantiate();
140 SoundTriggerHwService::instantiate();
147 ProcessState::self()->startThreadPool();
148 IPCThreadState::self()->joinThreadPool();
}
该文件所在目录的Android.mk文件将其编译成一个可执行程序mediaserver,该程序在/system/bin/mediaserver。
59 LOCAL_MODULE:= mediaserver
60 LOCAL_32_BIT_ONLY := true
61
62 include $(BUILD_EXECUTABLE)
同时在init.rc文件有如下内容:
724 service media /system/bin/mediaserver
725 class main
726 user media
727 group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm qcom_diag
728 ioprio rt 4
也就是将mediaserver执行,即执行其中的main函数。
AudioFlinger的静态初始化
AudioFlinger::instantiate()并不是AudioFlinger的内部静态类,而是BinderService类的一个实现。
class AudioFlinger :
public BinderService<AudioFlinger>,
public BnAudioFlinger
/frameworks/native/include/binder/BinderService.h
33template<typename SERVICE>
34class BinderService
35{
36public:
37 static status_t publish(bool allowIsolated = false) {
38 sp<IServiceManager> sm(defaultServiceManager());
39 return sm->addService(
40 String16(SERVICE::getServiceName()),
41 new SERVICE(), allowIsolated);
42 }
43
44 static void publishAndJoinThreadPool(bool allowIsolated = false) {
45 publish(allowIsolated);
46 joinThreadPool();
47 }
48
49 static void instantiate() { publish(); }//调用的是这里的instantiate
50
51 static status_t shutdown() { return NO_ERROR; }
52
instantiate时,首先将AudioFlinger作为一个服务添加到ServiceManager中,此间会调用AudioFlinger的构造函数。
AudioFlinger::AudioFlinger()
: BnAudioFlinger(),
mPrimaryHardwareDev(NULL),
mAudioHwDevs(NULL),
mHardwareStatus(AUDIO_HW_IDLE),
mMasterVolume(1.0f),
mMasterMute(false),
mNextUniqueId(1),
mMode(AUDIO_MODE_INVALID),
mBtNrecIsOff(false),
mIsLowRamDevice(true),
mIsDeviceTypeKnown(false),
mGlobalEffectEnableTime(0),
mSystemReady(false)
{}
这个构造函数基本上就是对以上变量的初始化。其实际的工作放在了onFirstRef方法中完成了。
BnAudioFlinger类由虚基类RefBase层层继承而来,并且IserviceManager::addService的第二个参数是个强指针引用,所以在AudioFlinger被引用时,onFirstRef将被调用。
void AudioFlinger::onFirstRef()
{
int rc = 0;
Mutex::Autolock _l(mLock);
/* TODO: move all this work into an Init() function */
char val_str[PROPERTY_VALUE_MAX] = { 0 };
if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
uint32_t int_val;
if (1 == sscanf(val_str, "%u", &int_val)) {
mStandbyTimeInNsecs = milliseconds(int_val);
ALOGI("Using %u mSec as standby time.", int_val);
} else {
mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
ALOGI("Using default %u mSec as standby time.",
(uint32_t)(mStandbyTimeInNsecs / 1000000));
}
}
mPatchPanel = new PatchPanel(this);
mMode = AUDIO_MODE_NORMAL;
}
ro.audio.flinger_standbytime_ms属性给用户调节stand_by时间,接下来其它进程可以通过servicemanager来访问,并通过createtrack以及openOutput等接口来驱使Audioflinger为其服务。
AudioFlinger和HAL的交互
<AudioFlinger.cpp>
static const char * const audio_interfaces[] = {
AUDIO_HARDWARE_MODULE_ID_PRIMARY,
AUDIO_HARDWARE_MODULE_ID_A2DP,
AUDIO_HARDWARE_MODULE_ID_USB,
};
#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
在编译的时候,这三种设备分别被编译成audio.primary.xxx.so,audio.a2dp.xxx.so的形式,xxx表示具体的硬件平台,AP会调用AF的函数AudioFlinger::loadHwModule完成对应SO的加载。
audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
{
if (name == NULL) {
return 0;
}
if (!settingsAllowed()) {
return 0;
}
Mutex::Autolock _l(mLock);
return loadHwModule_l(name);//调用loadHwModule_l完成功能
}
loadHwModule_l的实现如下:
audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
{
audio_hw_device_t *dev;
//加载对应的so库文件,通过dlsym的形式打开so文件,加载路径/system/lib/hw或者/vendor/lib/hw
//最终会调用audio_hw_hal.cpp里面的legacy_adev_open来挂载一些钩子函数, int rc = load_audio_interface(name, &dev); mHardwareStatus = AUDIO_HW_INIT; rc = dev->init_check(dev); mHardwareStatus = AUDIO_HW_IDLE;
audio_module_handle_t handle = nextUniqueId();
mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags)); //将设备添加到AF的键值对里
}
在打开so对应的音频库之后,最终调用HAL层的open函数。
static inline int audio_hw_device_open(const struct hw_module_t* module,
struct audio_hw_device** device)
{
return module->methods->open(module, AUDIO_HARDWARE_INTERFACE,
(struct hw_device_t**)device);
}
open函数里会将若干需要的钩子函数添加到audio_hw_device_t表示的结构体里。
AudioFlinger在播放流程中的行为
status_t AudioFlinger::openOutput(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t *devices,
const String8& address,
uint32_t *latencyMs,
audio_output_flags_t flags)
{
//判断要打开的设备参数是否合法
if (*devices == AUDIO_DEVICE_NONE) {
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
//创建playback线程
sp<PlaybackThread> thread = openOutput_l(module, output, config, *devices, address, flags);
if (thread != 0) {
*latencyMs = thread->latency();
// notify client processes of the new output creation
thread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
// the first primary output opened designates the primary hw device
if ((mPrimaryHardwareDev == NULL) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
ALOGI("Using module %d has the primary audio interface", module);
mPrimaryHardwareDev = thread->getOutput()->audioHwDev;
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_MODE;
mPrimaryHardwareDev->hwDevice()->set_mode(mPrimaryHardwareDev->hwDevice(), mMode);
mHardwareStatus = AUDIO_HW_IDLE;
}
return NO_ERROR;
}
return NO_INIT;
}
sp<AudioFlinger::PlaybackThread> AudioFlinger::openOutput_l(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *config,
audio_devices_t devices,
const String8& address,
audio_output_flags_t flags)
{
//根据key-value找到相应的audio interface
AudioHwDevice *outHwDev = findSuitableHwDev_l(module, devices);
if (outHwDev == NULL) {
return 0;
}
audio_hw_device_t *hwDevHal = outHwDev->hwDevice();
if (*output == AUDIO_IO_HANDLE_NONE) {
*output = nextUniqueId();
}
mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
// FOR TESTING ONLY:
// This if statement allows overriding the audio policy settings
// and forcing a specific format or channel mask to the HAL/Sink device for testing.
if (!(flags & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT))) {
// Check only for Normal Mixing mode
if (kEnableExtendedPrecision) {
// Specify format (uncomment one below to choose)
//config->format = AUDIO_FORMAT_PCM_FLOAT;
//config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
//config->format = AUDIO_FORMAT_PCM_32_BIT;
//config->format = AUDIO_FORMAT_PCM_8_24_BIT;
// ALOGV("openOutput_l() upgrading format to %#08x", config->format);
}
if (kEnableExtendedChannels) {
// Specify channel mask (uncomment one below to choose)
//config->channel_mask = audio_channel_out_mask_from_count(4); // for USB 4ch
//config->channel_mask = audio_channel_mask_from_representation_and_bits(
// AUDIO_CHANNEL_REPRESENTATION_INDEX, (1 << 4) - 1); // another 4ch example
}
}
AudioStreamOut *outputStream = NULL;
status_t status = outHwDev->openOutputStream(
&outputStream,
*output,
devices,
flags,
config,
address.string());
mHardwareStatus = AUDIO_HW_IDLE;
if (status == NO_ERROR) {
PlaybackThread *thread;
if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady);
ALOGV("openOutput_l() created offload output: ID %d thread %p", *output, thread);
} else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
|| !isValidPcmSinkFormat(config->format)
|| !isValidPcmSinkChannelMask(config->channel_mask)) {
thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady);
ALOGV("openOutput_l() created direct output: ID %d thread %p ", *output, thread);
//Check if this is DirectPCM, if so
if (flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
thread->mIsDirectPcm = true;
}
} else {
thread = new MixerThread(this, outputStream, *output, devices, mSystemReady);
ALOGV("openOutput_l() created mixer output: ID %d thread %p", *output, thread);
}
mPlaybackThreads.add(*output, thread);
return thread;
}
return 0;
}