现在的位置: 首页 > 综合 > 正文

Android如何找到正确的ALSA底层kcontrol接口?(转)

2012年10月05日 ⁄ 综合 ⁄ 共 5297字 ⁄ 字号 评论关闭

昨天分析了一把snd_kcontrol,可以认为上层应用的确是通过名称标识name来遍历底层的snd_kcontrol链表,从而找到相匹配的kcontrol。见snd_ctl_find_id函数

/**
 * snd_ctl_find_id - find the control instance with the given id
 * @card: the card instance
 * @id: the id to search
 *
 * Finds the control instance with the given id from the card.
 *
 * Returns the pointer of the instance if found, or NULL if not.
 *
 * The caller must down card->controls_rwsem before calling this function
 * (if the race condition can happen).
 */
struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
				     struct snd_ctl_elem_id *id)
{
	struct snd_kcontrol *kctl;

	if (snd_BUG_ON(!card || !id))
		return NULL;
	if (id->numid != 0)
		return snd_ctl_find_numid(card, id->numid);
	list_for_each_entry(kctl, &card->controls, list) {
		if (kctl->id.iface != id->iface)
			continue;
		if (kctl->id.device != id->device)
			continue;
		if (kctl->id.subdevice != id->subdevice)
			continue;
		if (strncmp(kctl->id.name, id->name, sizeof(kctl->id.name)))
			continue;
		if (kctl->id.index > id->index)
			continue;
		if (kctl->id.index + kctl->count <= id->index)
			continue;
		return kctl;
	}
	return NULL;
}


今天继续跟踪Android音频系统时,发现无论如何都找不到Android与snd_kcontrol的联结点,无论是name还是numid(alsa_amixer controls打印出来的那个numid,即是内核层snd_kcontrol链表元素的numid)都找不到相关关键字。但是它确实可以进行调节音量等控制。后来我修改内核的Codec驱动,将音量控制的kcontrol.name换成其他字符串,重新编译,Android还是可以进行音量控制。

看起来有点像是通过numid来控制的,《Android音频HAL移植》一文有提到:“设备的切换就需要和驱动联调。例如,目前earpiece的id为10,那么就可以通过ALSA的amixer设置earpiece的开和关,以及大小。而id的值就需要做驱动的同事提供。”但是还不能就此肯定。目前也没有找到保存这些值的脚本文件。


继续以上问题,我在调节音量时,打印Codec寄存器的值,发现volume寄存器的值根本不会发生变化,但是音量确确实实是变化的。那时就在怀疑我们Android的音量调节不是通过硬件来实现的,而是有自身的sw mixer机制。晚上和Vic一起吃饭时,聊起这个,肯定了我的猜测。

今天继续跟踪Android音频系统时,发现无论如何都找不到Android与snd_kcontrol的联结点,无论是name还是numid(alsa_amixer controls打印出来的那个numid,即是内核层snd_kcontrol链表元素的numid)都找不到相关关键字。但是它确实可以进行调节音量等控制。后来我修改内核的Codec驱动,将音量控制的kcontrol.name换成其他字符串,重新编译,Android还是可以进行音量控制。

看起来有点像是通过numid来控制的,《Android音频HAL移植》一文有提到:“设备的切换就需要和驱动联调。例如,目前earpiece的id为10,那么就可以通过ALSA的amixer设置earpiece的开和关,以及大小。而id的值就需要做驱动的同事提供。”但是还不能就此肯定。目前也没有找到保存这些值的脚本文件。


继续以上问题,我在调节音量时,打印Codec寄存器的值,发现volume寄存器的值根本不会发生变化,但是音量确确实实是变化的。那时就在怀疑我们Android的音量调节不是通过硬件来实现的,而是有自身的sw mixer机制。晚上和Vic一起吃饭时,聊起这个,肯定了我的猜测。

今天继续跟踪Android音频系统时,发现无论如何都找不到Android与snd_kcontrol的联结点,无论是name还是numid(alsa_amixer controls打印出来的那个numid,即是内核层snd_kcontrol链表元素的numid)都找不到相关关键字。但是它确实可以进行调节音量等控制。后来我修改内核的Codec驱动,将音量控制的kcontrol.name换成其他字符串,重新编译,Android还是可以进行音量控制。

看起来有点像是通过numid来控制的,《Android音频HAL移植》一文有提到:“设备的切换就需要和驱动联调。例如,目前earpiece的id为10,那么就可以通过ALSA的amixer设置earpiece的开和关,以及大小。而id的值就需要做驱动的同事提供。”但是还不能就此肯定。目前也没有找到保存这些值的脚本文件。


继续以上问题,我在调节音量时,打印Codec寄存器的值,发现volume寄存器的值根本不会发生变化,但是音量确确实实是变化的。那时就在怀疑我们Android的音量调节不是通过硬件来实现的,而是有自身的sw mixer机制。晚上和Vic一起吃饭时,聊起这个,肯定了我的猜测。

status_t AudioFlinger::setMasterVolume(float value)
{
    // check calling permissions
    if (!settingsAllowed()) {
        return PERMISSION_DENIED;
    }

    // when hw supports master volume, don't scale in sw mixer
    AutoMutex lock(mHardwareLock);
    mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
    if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
        value = 1.0f;
    }
    mHardwareStatus = AUDIO_HW_IDLE;

    mMasterVolume = value;
    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
       mPlaybackThreads.valueAt(i)->setMasterVolume(value);

    return NO_ERROR;
}

今天继续跟踪Android音频系统时,发现无论如何都找不到Android与snd_kcontrol的联结点,无论是name还是numid(alsa_amixer controls打印出来的那个numid,即是内核层snd_kcontrol链表元素的numid)都找不到相关关键字。但是它确实可以进行调节音量等控制。后来我修改内核的Codec驱动,将音量控制的kcontrol.name换成其他字符串,重新编译,Android还是可以进行音量控制。

看起来有点像是通过numid来控制的,《Android音频HAL移植》一文有提到:“设备的切换就需要和驱动联调。例如,目前earpiece的id为10,那么就可以通过ALSA的amixer设置earpiece的开和关,以及大小。而id的值就需要做驱动的同事提供。”但是还不能就此肯定。目前也没有找到保存这些值的脚本文件。


继续以上问题,我在调节音量时,打印Codec寄存器的值,发现volume寄存器的值根本不会发生变化,但是音量确确实实是变化的。那时就在怀疑我们Android的音量调节不是通过硬件来实现的,而是有自身的sw mixer机制。晚上和Vic一起吃饭时,聊起这个,肯定了我的猜测。

今天继续跟踪Android音频系统时,发现无论如何都找不到Android与snd_kcontrol的联结点,无论是name还是numid(alsa_amixer controls打印出来的那个numid,即是内核层snd_kcontrol链表元素的numid)都找不到相关关键字。但是它确实可以进行调节音量等控制。后来我修改内核的Codec驱动,将音量控制的kcontrol.name换成其他字符串,重新编译,Android还是可以进行音量控制。

看起来有点像是通过numid来控制的,《Android音频HAL移植》一文有提到:“设备的切换就需要和驱动联调。例如,目前earpiece的id为10,那么就可以通过ALSA的amixer设置earpiece的开和关,以及大小。而id的值就需要做驱动的同事提供。”但是还不能就此肯定。目前也没有找到保存这些值的脚本文件。


继续以上问题,我在调节音量时,打印Codec寄存器的值,发现volume寄存器的值根本不会发生变化,但是音量确确实实是变化的。那时就在怀疑我们Android的音量调节不是通过硬件来实现的,而是有自身的sw mixer机制。晚上和Vic一起吃饭时,聊起这个,肯定了我的猜测。

应该是Android允许开发者在HAL层实现hw mixer,当AudioFlinger探测到存在hw mixer时,则调用mAudioHardware->setMasterVolume()对volume寄存器进行设置,也不会对volume值进行scale。至于sw mixer如何使用scale值的,我没有深入探究。

以后实现hw mixer看看(反正到时也要实现EQ)效果,现在这个音量设置不是线性的,用硬件控制应该更好一点。


PS:标题就不用管它了,默认下Android根本不去找底层的kcontrol接口,而是使用自身的sw mixer。

今天继续跟踪Android音频系统时,发现无论如何都找不到Android与snd_kcontrol的联结点,无论是name还是numid(alsa_amixer controls打印出来的那个numid,即是内核层snd_kcontrol链表元素的numid)都找不到相关关键字。但是它确实可以进行调节音量等控制。后来我修改内核的Codec驱动,将音量控制的kcontrol.name换成其他字符串,重新编译,Android还是可以进行音量控制。

看起来有点像是通过numid来控制的,《Android音频HAL移植》一文有提到:“设备的切换就需要和驱动联调。例如,目前earpiece的id为10,那么就可以通过ALSA的amixer设置earpiece的开和关,以及大小。而id的值就需要做驱动的同事提供。”但是还不能就此肯定。目前也没有找到保存这些值的脚本文件。


继续以上问题,我在调节音量时,打印Codec寄存器的值,发现volume寄存器的值根本不会发生变化,但是音量确确实实是变化的。那时就在怀疑我们Android的音量调节不是通过硬件来实现的,而是有自身的sw mixer机制。晚上和Vic一起吃饭时,聊起这个,肯定了我的猜测。

今天继续跟踪Android音频系统时,发现无论如何都找不到Android与snd_kcontrol的联结点,无论是name还是numid(alsa_amixer controls打印出来的那个numid,即是内核层snd_kcontrol链表元素的numid)都找不到相关关键字。但是它确实可以进行调节音量等控制。后来我修改内核的Codec驱动,将音量控制的kcontrol.name换成其他字符串,重新编译,Android还是可以进行音量控制。

看起来有点像是通过numid来控制的,《Android音频HAL移植》一文有提到:“设备的切换就需要和驱动联调。例如,目前earpiece的id为10,那么就可以通过ALSA的amixer设置earpiece的开和关,以及大小。而id的值就需要做驱动的同事提供。”但是还不能就此肯定。目前也没有找到保存这些值的脚本文件。


继续以上问题,我在调节音量时,打印Codec寄存器的值,发现volume寄存器的值根本不会发生变化,但是音量确确实实是变化的。那时就在怀疑我们Android的音量调节不是通过硬件来实现的,而是有自身的sw mixer机制。晚上和Vic一起吃饭时,聊起这个,肯定了我的猜测。

抱歉!评论已关闭.