http://blog.sina.com.cn/s/blog_645b74b90101ar9n.html
转载+原创
背景:做了一个需求,就是在手机开机的时候实现一个开机动画的功能,这个应当各个厂商的手机都有,问题是这样的,兄弟组合入这个需求验证的时候发现开机过程中,光有动画没有声音,声音这块是我们负责,我们就要协助处理一下了,好吧,开始分析,中间还小插曲了一下,由于K3手机音频使用的不是audio_policy.default.so这个库,我们一直替换这个库,导致调试始终有问题,浪费了一点时间,好了,下面分析该问题的原因。
需求中播放声音过程很简单,就是简单的调用播放器播放一个ogg的音频文件,而且播放过程也没有报什么错误,但是就是没有听到什么声音,我们就从声音的大小入手。
我们在BootAnimation的threadLooper()函数中增加了一段代码:
int volumnIndex = -1;
if(NO_ERROR != AudioSystem::getStreamVolumeIndex(AUDIO_STREAM_RING, &volumnIndex)) {
}
if(NO_ERROR != AudioSystem::setStreamVolumeIndex(AUDIO_STREAM_RING, 6)) {
LOGE("coming here.....");
}
if(NO_ERROR != AudioSystem::getStreamVolumeIndex(AUDIO_STREAM_RING, &volumnIndex)) {
}
通过上面的代码,我们就是想知道,代码执行到这里的时候是否能够获取和设置这个音频流的声音的最大值,结果我们发现:
getStreamVolumeIndex()返回的值为0,因为我们没有播放任何东西,没有设置音量,为0正常,至少表明音频通路没有问题;
问题出现在这里,我们开始想设置我们的音频流的声音的index最大为6,结果函数返回了一个ERROR,而当我们将index最大设为1时,函数能够正确返回,设置6的时候返回的错误是BAD_VALUE,所以我们就要分析为什么不能将最大音量设置为6级了
下面就是跟踪函数setStreamVolumeIndex()的流程:
//AudioSystem.cpp
status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream, int index)
{
const sp& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->setStreamVolumeIndex(stream, index);
}
//AudioPolicyService.cpp
status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream, int index)
{
if (mpAudioPolicy == NULL) {
return NO_INIT;
}
if (!checkPermission()) {
return PERMISSION_DENIED;
}
if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
return BAD_VALUE;
}
return mpAudioPolicy->set_stream_volume_index(mpAudioPolicy, stream, index);
}
/////////////////////////////////////////////////////////////////////
audio_policy_hal.cpp类中create_legacy_ap()函数注册了一个函数指针对应表
lap->policy.set_stream_volume_index = ap_set_stream_volume_index;
lap->policy.get_stream_volume_index = ap_get_stream_volume_index;
/////////////////////////////////////////////////////////////////////
//audio_policy_hal.cpp
static int ap_get_stream_volume_index(const struct audio_policy *pol,
audio_stream_type_t stream,
int *index)
{
const struct legacy_audio_policy *lap = to_clap(pol);
r
eturn lap->apm->setStreamVolumeIndex((AudioSystem::stream_type)stream,
index);
}
//AudioPolicyManagerBase.cpp
status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
{
if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
return BAD_VALUE;
}
// Force max volume if stream cannot be muted
if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;
LOGV("setStreamVolumeIndex() stream %d, index %d", stream, index);
mStreams[stream].mIndexCur = index;
// compute and apply stream volume on all outputs according to connected device
status_t status = NO_ERROR;
for (size_t i = 0; i < mOutputs.size(); i++) {
status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), mOutputs.valueAt(i)->device());
if (volStatus != NO_ERROR) {
status = volStatus;
}
}
return status;
}
问题最可能就出现在最下面的蓝色部分,1可以正常设置,而6不能正常设置,问题可能就是6超过了min--max的范围。
所以我们要看min-max的范围到底是多少
StreamDescriptor mStreams[AudioSystem::NUM_STREAM_TYPES]; // stream descriptors for volume control
我们看这个类的构造函数
StreamDescriptor()
:
mIndexMin(0), mIndexMax(1), mIndexCur(1), mCanBeMuted(true) {}
这下明白了吧,我们初始化各个音频流的最大声音级别为1,所以我们设置为6的时候就会报bad_value错误了,
而这个1也正是开机动画中没有声音的原因,其实不是没有声音,而是声音太小了,根本听不清。
找到原因之后,我们尝试将这个值改大比如说15,验证声音果然出来了,问题解决。
后记:
由于开机动画是在开机中media_server和system_server刚起来的阶段,此时还没有从setting模块中读取数据库中的记录为各个流设置最大的index,所以此时的index还是使用默认的值,故而不能正常播放音乐。
正常在开机完成后,读取setting中的数据库,调用下面的函数对各个流的音量进行设置:
void AudioPolicyManagerBase::initStreamVolume(AudioSystem::stream_type stream,
int indexMin,
int indexMax)
{
LOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
if (indexMin < 0 || indexMin >= indexMax) {
LOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d", stream , indexMin, indexMax);
return;
}
mStreams[stream].mIndexMin = indexMin;
mStreams[stream].mIndexMax = indexMax;