hal: Fix incall music delivery during voice call issues
Fix incall music delivery issue by adding support for incall music usecase in out_write and adev_open_output_stream CRs-Fixed:2308665 Change-Id: I26f9f36c29017480ec064b8db2b2b9ae6b357fb5
This commit is contained in:
parent
0dd741a119
commit
7da752abb4
|
@ -4358,6 +4358,8 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
|
|||
struct audio_device *adev = out->dev;
|
||||
ssize_t ret = 0;
|
||||
int channels = 0;
|
||||
const size_t frame_size = audio_stream_out_frame_size(stream);
|
||||
const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
|
||||
|
||||
ATRACE_BEGIN("out_write");
|
||||
lock_output_stream(out);
|
||||
|
@ -4563,8 +4565,35 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
|
|||
return ret;
|
||||
} else {
|
||||
if (out->pcm) {
|
||||
size_t bytes_to_write = bytes;
|
||||
if (out->muted)
|
||||
memset((void *)buffer, 0, bytes);
|
||||
ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
|
||||
__func__, frames, frame_size, bytes_to_write);
|
||||
|
||||
if (out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
|
||||
size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
|
||||
int16_t *src = (int16_t *)buffer;
|
||||
int16_t *dst = (int16_t *)buffer;
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
|
||||
out->format != AUDIO_FORMAT_PCM_16_BIT,
|
||||
"out_write called for incall music use case with wrong properties");
|
||||
|
||||
/*
|
||||
* FIXME: this can be removed once audio flinger mixer supports
|
||||
* mono output
|
||||
*/
|
||||
|
||||
/*
|
||||
* Code below goes over each frame in the buffer and adds both
|
||||
* L and R samples and then divides by 2 to convert to mono
|
||||
*/
|
||||
for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
|
||||
*dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
|
||||
}
|
||||
bytes_to_write /= 2;
|
||||
}
|
||||
|
||||
ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
|
||||
|
||||
|
@ -4574,12 +4603,11 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
|
|||
ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
|
||||
out->config.rate;
|
||||
|
||||
request_out_focus(out, ns);
|
||||
bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
|
||||
|
||||
request_out_focus(out, ns);
|
||||
|
||||
if (use_mmap)
|
||||
ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
|
||||
ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
|
||||
else if (out->hal_op_format != out->hal_ip_format &&
|
||||
out->convert_buffer != NULL) {
|
||||
|
||||
|
@ -4613,7 +4641,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
|
|||
out_get_sample_rate(&out->stream.common));
|
||||
ret = 0;
|
||||
} else
|
||||
ret = pcm_write(out->pcm, (void *)buffer, bytes);
|
||||
ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
|
||||
}
|
||||
|
||||
release_out_focus(out);
|
||||
|
@ -6119,13 +6147,55 @@ int adev_open_output_stream(struct audio_hw_device *dev,
|
|||
create_offload_callback_thread(out);
|
||||
|
||||
} else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
|
||||
switch (config->sample_rate) {
|
||||
case 0:
|
||||
out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
|
||||
break;
|
||||
case 8000:
|
||||
case 16000:
|
||||
case 48000:
|
||||
out->sample_rate = config->sample_rate;
|
||||
break;
|
||||
default:
|
||||
ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
|
||||
config->sample_rate);
|
||||
config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
|
||||
ret = -EINVAL;
|
||||
goto error_open;
|
||||
}
|
||||
//FIXME: add support for MONO stream configuration when audioflinger mixer supports it
|
||||
switch (config->channel_mask) {
|
||||
case AUDIO_CHANNEL_NONE:
|
||||
case AUDIO_CHANNEL_OUT_STEREO:
|
||||
out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
|
||||
break;
|
||||
default:
|
||||
ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
|
||||
config->channel_mask);
|
||||
config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
|
||||
ret = -EINVAL;
|
||||
goto error_open;
|
||||
}
|
||||
switch (config->format) {
|
||||
case AUDIO_FORMAT_DEFAULT:
|
||||
case AUDIO_FORMAT_PCM_16_BIT:
|
||||
out->format = AUDIO_FORMAT_PCM_16_BIT;
|
||||
break;
|
||||
default:
|
||||
ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
|
||||
config->format);
|
||||
config->format = AUDIO_FORMAT_PCM_16_BIT;
|
||||
ret = -EINVAL;
|
||||
goto error_open;
|
||||
}
|
||||
|
||||
ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
|
||||
if (ret != 0) {
|
||||
ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
|
||||
__func__, ret);
|
||||
__func__, ret);
|
||||
goto error_open;
|
||||
}
|
||||
} else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
|
||||
} else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
|
||||
if (config->sample_rate == 0)
|
||||
config->sample_rate = AFE_PROXY_SAMPLING_RATE;
|
||||
if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
|
||||
* Not a contribution.
|
||||
*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
|
@ -594,27 +594,16 @@ void voice_extn_in_get_parameters(struct stream_in *in,
|
|||
voice_extn_compress_voip_in_get_parameters(in, query, reply);
|
||||
}
|
||||
|
||||
#ifdef INCALL_MUSIC_ENABLED
|
||||
int voice_extn_check_and_set_incall_music_usecase(struct audio_device *adev,
|
||||
struct stream_out *out)
|
||||
{
|
||||
uint32_t session_id = 0;
|
||||
|
||||
session_id = get_session_id_with_state(adev, CALL_LOCAL_HOLD);
|
||||
if (session_id == VOICE_VSID) {
|
||||
out->usecase = USECASE_INCALL_MUSIC_UPLINK;
|
||||
} else if (session_id == VOICE2_VSID) {
|
||||
out->usecase = USECASE_INCALL_MUSIC_UPLINK2;
|
||||
} else {
|
||||
ALOGE("%s: Invalid session id %x", __func__, session_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
out->usecase = USECASE_INCALL_MUSIC_UPLINK;
|
||||
out->config = pcm_config_incall_music;
|
||||
out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
|
||||
out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
|
||||
//FIXME: add support for MONO stream configuration when audioflinger mixer supports it
|
||||
out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
|
||||
out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
|
||||
out->config.rate = out->sample_rate;
|
||||
|
||||
ALOGV("%s: mode=%d, usecase id=%d", __func__, adev->mode, out->usecase);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014, 2016-2017, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013-2014, 2016-2018, The Linux Foundation. All rights reserved.
|
||||
* Not a contribution.
|
||||
*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
|
@ -101,13 +101,8 @@ static void __unused voice_extn_out_get_parameters(struct stream_out *out __unus
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef INCALL_MUSIC_ENABLED
|
||||
int voice_extn_check_and_set_incall_music_usecase(struct audio_device *adev,
|
||||
struct stream_out *out);
|
||||
#else
|
||||
#define voice_extn_check_and_set_incall_music_usecase(adev, out) -ENOSYS
|
||||
#endif
|
||||
|
||||
#ifdef COMPRESS_VOIP_ENABLED
|
||||
int voice_extn_compress_voip_close_output_stream(struct audio_stream *stream);
|
||||
int voice_extn_compress_voip_open_output_stream(struct stream_out *out);
|
||||
|
|
Loading…
Reference in New Issue