08.音频系统:第004课_Android音频系统详解:第004节_AudioPolicyService启动过程分析

经过前面小节的学习我们知道android音频系统中有两个服务:AudioFlinger与AudioPolicyService。该小节我们讲解AudioPolicyService,他会做哪些事情呢?

比如应用程序要播放声音,那么这个声音从哪个设备播放出来,其就是通过AudioPolicyService来决定的。假设android系统中有两个声卡设备,如下图所示:
在这里插入图片描述
那么他的默认声卡是谁?在声卡一上面有耳机插孔以及喇叭,其如何告知android系统?(都由参加决定,用一个配置文件)。
在前面的小姐我们提到过,逻辑意义上,AudioFlinger中的每个output都对应一个设备以及一个线程,对于硬件的访问操作,都是由AudioFlinger完成的。

AudioPolicyService一般动作如下(AudioPolicyService是不能主动做任何事情的):
1.读取解析配置文件。
2.根据配置文件调用AudioFlinger的服务,打开output,创建线程(有了这些线程之后,我们的程序就可以把声音数据发送给这些线程了)

现在我们开始分析源代码,下面是AudioPolicyService调用的时序图
在这里插入图片描述
从图中我们可以知道,AudioPolicyService会调用其instantiate()函数(在BinderService.h中实现),最终调用到AudioPolicyService.cpp中的void AudioPolicyService::onFirstRef()函数:

void AudioPolicyService::onFirstRef()
    // start tone playback thread
    mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
    // start audio commands thread
    mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
    // start output activity command thread
    mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
	mAudioPolicyClient = new AudioPolicyClient(this);
	mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);

可以看到起创建了3个线程,该些线程后续讲解,其余硬件无关。可以看到起创建了一个mAudioPolicyClient = new AudioPolicyClient(this),之前我们提到过,AudioPolicyService要使用AudioFlinger提供的服务,这个就是AudioFlinger的客户端,以后我们可以通过AudioPolicyClient使用AudioFlinger提供的服务访问硬件。AudioPolicyClient是在AudioPolicyClientImpl.cpp文件中实现的。

createAudioPolicyManager是厂家提供的,这个函数会穿什么事情呢?:
在这里插入图片描述
我们先分析一下AudioPolicyManagerBase,其中存在函数

status_t AudioPolicyManagerBase::loadAudioPolicyConfig(const char *path)
status_t AudioPolicyManagerBase::loadOutput(cnode *root, HwModule *module)
void AudioPolicyManagerBase::loadHwModule(cnode *root)

AudioPolicyManagerBase得构造函数如下:

AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
	/*
	#define AUDIO_POLICY_CONFIG_FILE "/system/etc/audio_policy.conf"
	#define AUDIO_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_policy.conf"
	*/
    if (loadAudioPolicyConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE) != NO_ERROR) {

可以知道,其会从/system/etc/audio_policy.conf与/vendor/etc/audio_policy.conf中加载配置文件,我们的开发板是在/system/etc/audio_policy.conf路径下面,其内容如下:

/*描述多个modules*/
audio_hw_modules {
  primary { //一个modules对应一个厂家提供的so文件
    outputs { //一个modules可以有多个output
      primary {//一个output表明他的参数(primary代表默认设备)
        sampling_rates  44100|48000 //采样率
        channel_masks AUDIO_CHANNEL_OUT_STEREO //通道
        formats AUDIO_FORMAT_PCM_16_BIT //格式
        /*有哪些device,如喇叭,耳机等等*/
        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
      }
      spdif_passthrough {
        sampling_rates 44100|48000
        channel_masks AUDIO_CHANNEL_OUT_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_SPDIF
        flags AUDIO_OUTPUT_FLAG_DIRECT
      }

      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
      }
    }
    inputs {//一个modules可以有多个input
      primary {
        sampling_rates 8000|11025|16000|22050|32000|44100|48000
        channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_WIRED_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
      }
    }
  }
  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 dynamic
        channel_masks dynamic
        formats dynamic
        devices AUDIO_DEVICE_OUT_USB_DEVICE
      }
    }
    inputs {
      usb_device {
        sampling_rates dynamic
        channel_masks AUDIO_CHANNEL_IN_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_IN_USB_DEVICE
      }
    }
  }
  r_submix {
    outputs {
      submix {
        sampling_rates 48000
        channel_masks AUDIO_CHANNEL_OUT_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX
      }
    }
    inputs {
      submix {
        sampling_rates 48000
        channel_masks AUDIO_CHANNEL_IN_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_IN_REMOTE_SUBMIX
      }
    }
  }
}

audio_policy.conf这个文件是非常重要的,其中primary,a2dp,usb,r_submix节点间我们称为modle。现在我们看看源码,其是怎么解析的:

status_t AudioPolicyManagerBase::loadAudioPolicyConfig(const char *path)
	cnode *root;
	/*加载文件*/
	data = (char *)load_file(path, NULL);
	/*解析文件,得到一系列的cnode *root节点*/
	config_load(root, data);
	/*对global_configuration节点的处理,在我们的开发板的配置文件,没有节点间*/
	loadGlobalConfig(root);
		/*取出第一个子节点*/
		node = node->first_child;/*循环获得*/
		while (node) {
			/*#define ATTACHED_OUTPUT_DEVICES_TAG "attached_output_devices"
			#define DEFAULT_OUTPUT_DEVICE_TAG "default_output_device"
			#define ATTACHED_INPUT_DEVICES_TAG "attached_input_devices"
			#define SPEAKER_DRC_ENABLED_TAG "speaker_drc_enabled"
			#define AUDIO_HAL_VERSION_TAG "audio_hal_version"*/
			 mAttachedOutputDevices = parseDeviceNames((char *)node->value);
			 mDefaultOutputDevice = (audio_devices_t)stringToEnum(sDeviceNameToEnumTable,                                           ARRAY_SIZE(sDeviceNameToEnumTable),(char *)node->value);
			 mAvailableInputDevices = parseDeviceNames((char *)node->value) & ~AUDIO_DEVICE_BIT_IN;
			 mSpeakerDrcEnabled = stringToBool((char *)node->value);
	/*解析audio_hw_modules结点*/
	loadHwModules(root);
		loadHwModule(node);

其中loadHwModules的实现如下:

void AudioPolicyManagerBase::loadHwModule(cnode *root)
{
    cnode *node = config_find(root, OUTPUTS_TAG);
    status_t status = NAME_NOT_FOUND;

    HwModule *module = new HwModule(root->name);

    if (node != NULL) {
        if (strcmp(root->name, AUDIO_HARDWARE_MODULE_ID_A2DP) == 0) {
            mHasA2dp = true;
        } else if (strcmp(root->name, AUDIO_HARDWARE_MODULE_ID_USB) == 0) {
            mHasUsb = true;
        } else if (strcmp(root->name, AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX) == 0) {
            mHasRemoteSubmix = true;
        }

        node = node->first_child;
        while (node) {
            ALOGV("loadHwModule() loading output %s", node->name);
            status_t tmpStatus = loadOutput(node, module);
            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
                status = tmpStatus;
            }
            node = node->next;
        }
    }
    node = config_find(root, INPUTS_TAG);
    if (node != NULL) {
        node = node->first_child;
        while (node) {
            ALOGV("loadHwModule() loading input %s", node->name);
            status_t tmpStatus = loadInput(node, module);
            if (status == NAME_NOT_FOUND || status == NO_ERROR) {
                status = tmpStatus;
            }
            node = node->next;
        }
    }
    if (status == NO_ERROR) {
        mHwModules.add(module);
    } else {
        delete module;
    }
}

下面我们做一些总结:
在这里插入图片描述
对于每一个audio_policy.conf中 的每一个modules,使用函数loadHwModule来处理:
1.创建一个HwModule *module = new HwModule(root->name),这个名字分别为:primary ,a2dp,usbr_submix。
2.这个module 中存在两个量表
mOutputProfiles:每一项对应一个output的profile(配置:其来自配置文件的参数)
mInputProfiles:每一项对应一个Input的profile(配置:其来自配置文件的参数)

该小节我们讲解了配置文件的加载过程,下小节我们讲解,解析完配置之后,android系统是如何使用的。

下面是文字对该小节的总结:

AudioPolicyService启动过程分析
a. 加载解析/vendor/etc/audio_policy.conf或/system/etc/audio_policy.conf
   对于配置文件里的每一个module项, new HwModule(name), 放入mHwModules数组
   对于module里的每一个output, new IOProfile, 放入module的mOutputProfiles
   对于module里的每一个input, new IOProfile, 放入module的mInputProfiles

/*以下为之后小节讲解类容*/
b. 根据module的name加载厂家提供的so文件 (通过AudioFlinger来加载)
c. 打开对应的output                     (通过AudioFlinger来open output)

猜你喜欢

转载自blog.csdn.net/weixin_43013761/article/details/89468067