在audio hal代码中可以看到,hal模块初始化时确实将输出设备设定为喇叭模式,如红色部分:
AUDIO_DEVICE_OUT_SPEAKER
static int adev_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
struct sunxi_audio_device *adev;
int ret;
if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
return -EINVAL;
adev = calloc(1, sizeof(struct sunxi_audio_device));
if (!adev)
return -ENOMEM;
adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
adev->hw_device.common.module = (struct hw_module_t *) module;
adev->hw_device.common.close = adev_close;
adev->hw_device.init_check = adev_init_check;
adev->hw_device.set_voice_volume = adev_set_voice_volume;
adev->hw_device.set_master_volume = adev_set_master_volume;
adev->hw_device.get_master_volume = adev_get_master_volume;
adev->hw_device.set_mode = adev_set_mode;
adev->hw_device.set_mic_mute = adev_set_mic_mute;
adev->hw_device.get_mic_mute = adev_get_mic_mute;
adev->hw_device.set_parameters = adev_set_parameters;
adev->hw_device.get_parameters = adev_get_parameters;
adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
adev->hw_device.open_output_stream = adev_open_output_stream;
adev->hw_device.close_output_stream = adev_close_output_stream;
adev->hw_device.open_input_stream = adev_open_input_stream;
adev->hw_device.close_input_stream = adev_close_input_stream;
adev->hw_device.dump = adev_dump;
adev->raw_flag = false;
/* Set the default route before the PCM stream is opened */
pthread_mutex_lock(&adev->lock);
adev->mode = AUDIO_MODE_NORMAL;
adev->out_device = AUDIO_DEVICE_OUT_SPEAKER;
adev->in_device = AUDIO_DEVICE_IN_BUILTIN_MIC & ~AUDIO_DEVICE_BIT_IN;
adev->ar = audio_route_init(MIXER_CARD, AC100_XML_PATH);
//select_device(adev);
adev->pcm_modem_dl = NULL;
adev->pcm_modem_ul = NULL;
adev->voice_volume = 1.0f;
adev->tty_mode = TTY_MODE_OFF;
adev->bluetooth_nrec = false;
adev->wb_amr = 0;
adev->fm_mode = 2;
//adev->vol_array =
adev->mixer = mixer_open(MIXER_CARD);
if (!adev->mixer) {
ALOGE("Unable to open the mixer, aborting.");
}
/*volume ctl*/
adev->mixer_volumectls.hpvolume = mixer_get_ctl_by_name(adev->mixer,
MIXER_HP_VOLUME);
adev->mixer_volumectls.spkvolume = mixer_get_ctl_by_name(adev->mixer,
MIXER_SPK_VOLUME);
adev->mixer_volumectls.earpiecevolume = mixer_get_ctl_by_name(adev->mixer,
MIXER_EARPIECE_VOLUME);
pthread_mutex_unlock(&adev->lock);
*device = &adev->hw_device.common;
adev->vol_array = calloc(1, sizeof(struct volume_array));
codec_voice_volume_init(adev->vol_array);
ALOGD("line:%d,func:%s\n", __LINE__, __FUNCTION__);
if (ril_dev_init() < 0 ) {
ALOGE("err: ril_dev_init ****LINE:%d,FUNC:%s",__LINE__,__FUNCTION__);
}
case_init();
return 0;
error_out:
free(adev);
return -EINVAL;
}
但是从log得知,这个
out_device 后来被修改成AUDIO_DEVICE_OUT_EARPIECE。
在函数out_set_parameters()中修改了out_device的值,
static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
{
。
。
。
/* force standby if moving to/from HDMI */
if (((val & AUDIO_DEVICE_OUT_AUX_DIGITAL) ^
(adev->out_device & AUDIO_DEVICE_OUT_AUX_DIGITAL)) ||
((val & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) ^
(adev->out_device & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET)))
do_output_standby(out);
}
adev->out_device = val;
select_output_device(adev);
。
。
。
return ret;
}
这个接口是注册到jni直接给上层调用的,找到了调用的地方,加了打印但发现并不是那里调的,索性先把这块暴力
修改一下:
if(8 == val)
val = 2;//8和2分别对应耳机模式和外放模式的宏值,我索性直接这样写了,编译push,重启
机器,果然有声音了,但是状态栏的耳机模式图标仍然在那里。
善始善终,这样多别扭而且不规范,但是又找不到哪里调用的out_set_parameters,索性找到耳机状态栏图标给它裁掉,在systemUI中找到了
并直接删除,从layout数组中剔除,结果编译失败了,想想还是不走这步了,应该是驱动上报的有问题。
adb getevent -i
根据节点信息在内核代码中找到了驱动代码,发现在驱动初始化中有这么一段:
//jack_type = SND_JACK_HEADPHONE;
jack_type = SND_JACK_AVOUT;
if (jack_type != ctx->switch_status) {
printk("mrzhang debug2 in %s : jack_type=%d, ctx->switch_status=%d\n",__FUNCTION__,jack_type,ctx->switch_status);
ctx->switch_status = jack_type;
snd_jack_report(ctx->jack.jack, jack_type);
pr_debug("switch:%d\n",jack_type);
switch_state = jack_type;
}
可知驱动挂载直接就上报了耳机模式,那么改一下,OK了,声音也有了,耳机图标也没了。
总结:解决问题还是要先花足够的时间确定方向,判断是驱动问题还是上层问题,这一点很重要。