在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了,聲音也有了,耳機圖標也沒了。
總結:解決問題還是要先花足夠的時間確定方向,判斷是驅動問題還是上層問題,這一點很重要。