在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了,声音也有了,耳机图标也没了。 总结:解决问题还是要先花足够的时间确定方向,判断是驱动问题还是上层问题,这一点很重要。
