hal: add incall music delivery feature
In multisim scenarios, local call hold tone has to be played
to the uplink on the sub on local call hold. Add incall music
delivery feature so that call hold tones can be played to the
uplink.
Change-Id: I8cecf0139926a4bfee603c02542bbedc67720bf4
diff --git a/hal/Android.mk b/hal/Android.mk
index cc6b62e..be67ba0 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -43,6 +43,10 @@
LOCAL_CFLAGS += -DAFE_PROXY_ENABLED
endif
+ifneq ($(strip $(AUDIO_FEATURE_DISABLED_INCALL_MUSIC)),true)
+LOCAL_CFLAGS += -DINCALL_MUSIC_ENABLED
+endif
+
ifneq ($(strip $(AUDIO_FEATURE_DISABLED_FM)),true)
LOCAL_CFLAGS += -DFM_ENABLED
LOCAL_SRC_FILES += audio_extn/fm.c
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 1bcb25a..aa7e6a6 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -114,6 +114,8 @@
[USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
[USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
[USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
+ [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
+ [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
};
@@ -1925,6 +1927,13 @@
ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
__func__, config->offload_info.version,
config->offload_info.bit_rate);
+ } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
+ ret = voice_check_and_set_incall_music_usecase(adev, out);
+ if (ret != 0) {
+ ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
+ __func__, ret);
+ goto error_open;
+ }
} else {
out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
out->config = pcm_config_low_latency;
@@ -2146,6 +2155,7 @@
struct audio_device *adev = (struct audio_device *)dev;
pthread_mutex_lock(&adev->lock);
if (adev->mode != mode) {
+ ALOGD("%s mode %d\n", __func__, mode);
adev->mode = mode;
}
pthread_mutex_unlock(&adev->lock);
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index c43b557..965ac62 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -78,6 +78,9 @@
USECASE_INCALL_REC_DOWNLINK,
USECASE_INCALL_REC_UPLINK_AND_DOWNLINK,
+ USECASE_INCALL_MUSIC_UPLINK,
+ USECASE_INCALL_MUSIC_UPLINK2,
+
AUDIO_USECASE_MAX
} audio_usecase_t;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 134fdbb..1734ced 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -113,6 +113,10 @@
AUDIO_RECORD_PCM_DEVICE},
[USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE,
AUDIO_RECORD_PCM_DEVICE},
+ [USECASE_INCALL_MUSIC_UPLINK] = {INCALL_MUSIC_UPLINK_PCM_DEVICE,
+ INCALL_MUSIC_UPLINK_PCM_DEVICE},
+ [USECASE_INCALL_MUSIC_UPLINK2] = {INCALL_MUSIC_UPLINK2_PCM_DEVICE,
+ INCALL_MUSIC_UPLINK2_PCM_DEVICE},
};
/* Array to store sound devices */
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index fe55f1b..9212307 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -150,6 +150,8 @@
#define VOICE_CALL_PCM_DEVICE 2
#define FM_PLAYBACK_PCM_DEVICE 5
#define FM_CAPTURE_PCM_DEVICE 6
+#define INCALL_MUSIC_UPLINK_PCM_DEVICE 1
+#define INCALL_MUSIC_UPLINK2_PCM_DEVICE 16
#ifdef PLATFORM_MSM8x26
#define VOICE2_CALL_PCM_DEVICE 14
diff --git a/hal/voice.c b/hal/voice.c
index 190df7c..39e2dd9 100755
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -249,6 +249,20 @@
return ret;
}
+int voice_check_and_set_incall_music_usecase(struct audio_device *adev,
+ struct stream_out *out)
+{
+ int ret = 0;
+
+ ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
+ if (ret == -ENOSYS) {
+ /* Incall music delivery is used only for LCH call state */
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
int voice_set_mic_mute(struct audio_device *adev, bool state)
{
int err = 0;
diff --git a/hal/voice.h b/hal/voice.h
index d5e5a8d..7f8b25b 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -38,6 +38,7 @@
struct audio_device;
struct str_parms;
struct stream_in;
+struct stream_out;
struct call_state {
int current;
@@ -67,5 +68,7 @@
bool voice_get_mic_mute(struct audio_device *dev);
int voice_set_volume(struct audio_device *adev, float volume);
int voice_check_and_set_incall_rec_usecase(struct audio_device *adev,
- struct stream_in *in);
+ struct stream_in *in);
+int voice_check_and_set_incall_music_usecase(struct audio_device *adev,
+ struct stream_out *out);
#endif //VOICE_H
diff --git a/hal/voice_extn/voice_extn.c b/hal/voice_extn/voice_extn.c
index 29f12d4..903d2aa 100644
--- a/hal/voice_extn/voice_extn.c
+++ b/hal/voice_extn/voice_extn.c
@@ -17,8 +17,6 @@
* limitations under the License.
*/
-#ifdef MULTI_VOICE_SESSION_ENABLED
-
#define LOG_TAG "voice_extn"
/*#define LOG_NDEBUG 0*/
#define LOG_NDDEBUG 0
@@ -52,6 +50,17 @@
#define CALL_HOLD (BASE_CALL_STATE + 2)
#define CALL_LOCAL_HOLD (BASE_CALL_STATE + 3)
+struct pcm_config pcm_config_incall_music = {
+ .channels = 1,
+ .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
+ .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
+ .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
+ .format = PCM_FORMAT_S16_LE,
+ .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
+ .stop_threshold = INT_MAX,
+ .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
+};
+
extern int start_call(struct audio_device *adev, audio_usecase_t usecase_id);
extern int stop_call(struct audio_device *adev, audio_usecase_t usecase_id);
int voice_extn_update_calls(struct audio_device *adev);
@@ -103,21 +112,28 @@
return usecase_id;
}
-int voice_extn_get_active_session_id(struct audio_device *adev,
- uint32_t *session_id)
+static uint32_t get_session_id_with_state(struct audio_device *adev,
+ int call_state)
{
struct voice_session *session = NULL;
int i = 0;
- *session_id = 0;
+ uint32_t session_id = 0;
for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
session = &adev->voice.session[i];
- if(session->state.current == CALL_ACTIVE){
- *session_id = session->vsid;
+ if(session->state.current == call_state){
+ session_id = session->vsid;
break;
}
}
+ return session_id;
+}
+
+int voice_extn_get_active_session_id(struct audio_device *adev,
+ uint32_t *session_id)
+{
+ *session_id = get_session_id_with_state(adev, CALL_ACTIVE);
return 0;
}
@@ -155,6 +171,7 @@
if (session) {
session->state.new = call_state;
voice_extn_is_in_call(adev, &is_in_call);
+ ALOGD("%s is_in_call:%d mode:%d\n", __func__, is_in_call, adev->mode);
if (is_in_call || adev->mode == AUDIO_MODE_IN_CALL) {
/* Device routing is not triggered for voice calls on the subsequent
* subs, Hence update the call states if voice call is already
@@ -224,7 +241,7 @@
for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
usecase_id = voice_extn_get_usecase_for_session_idx(i);
session = &adev->voice.session[i];
- ALOGV("%s: cur_state=%d new_state=%d vsid=%x",
+ ALOGD("%s: cur_state=%d new_state=%d vsid=%x",
__func__, session->state.current, session->state.new, session->vsid);
switch(session->state.new)
@@ -233,7 +250,7 @@
switch(session->state.current)
{
case CALL_INACTIVE:
- ALOGD("%s: INACTIVE ->ACTIVE vsid:%x", __func__, session->vsid);
+ ALOGD("%s: INACTIVE -> ACTIVE vsid:%x", __func__, session->vsid);
ret = start_call(adev, usecase_id);
if(ret < 0) {
ALOGE("%s: voice_start_call() failed for usecase: %d\n",
@@ -243,15 +260,15 @@
break;
case CALL_HOLD:
- ALOGD("%s: HOLD ->ACTIVE vsid:%x", __func__, session->vsid);
+ ALOGD("%s: HOLD -> ACTIVE vsid:%x", __func__, session->vsid);
session->state.current = session->state.new;
break;
case CALL_LOCAL_HOLD:
- ALOGD("%s: LOCAL_HOLD ->ACTIVE vsid:%x", __func__, session->vsid);
+ ALOGD("%s: LOCAL_HOLD -> ACTIVE vsid:%x", __func__, session->vsid);
lch_mode = VOICE_LCH_STOP;
if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
- ALOGE("LOCAL_HOLD ->ACTIVE failed");
+ ALOGE("LOCAL_HOLD -> ACTIVE failed");
} else {
session->state.current = session->state.new;
}
@@ -270,7 +287,7 @@
case CALL_ACTIVE:
case CALL_HOLD:
case CALL_LOCAL_HOLD:
- ALOGD("%s: ACTIVE/HOLD/LOCAL_HOLD ->INACTIVE vsid:%x", __func__, session->vsid);
+ ALOGD("%s: ACTIVE/HOLD/LOCAL_HOLD -> INACTIVE vsid:%x", __func__, session->vsid);
ret = stop_call(adev, usecase_id);
if(ret < 0) {
ALOGE("%s: voice_end_call() failed for usecase: %d\n",
@@ -290,15 +307,15 @@
switch(session->state.current)
{
case CALL_ACTIVE:
- ALOGD("%s: CALL_ACTIVE ->HOLD vsid:%x", __func__, session->vsid);
+ ALOGD("%s: CALL_ACTIVE -> HOLD vsid:%x", __func__, session->vsid);
session->state.current = session->state.new;
break;
case CALL_LOCAL_HOLD:
- ALOGD("%s: CALL_LOCAL_HOLD ->HOLD vsid:%x", __func__, session->vsid);
+ ALOGD("%s: CALL_LOCAL_HOLD -> HOLD vsid:%x", __func__, session->vsid);
lch_mode = VOICE_LCH_STOP;
if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
- ALOGE("LOCAL_HOLD ->HOLD failed");
+ ALOGE("LOCAL_HOLD -> HOLD failed");
} else {
session->state.current = session->state.new;
}
@@ -316,10 +333,11 @@
{
case CALL_ACTIVE:
case CALL_HOLD:
- ALOGD("%s: ACTIVE/CALL_HOLD ->LOCAL_HOLD vsid:%x", __func__, session->vsid);
+ ALOGD("%s: ACTIVE/CALL_HOLD -> LOCAL_HOLD vsid:%x", __func__,
+ session->vsid);
lch_mode = VOICE_LCH_START;
if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
- ALOGE("LOCAL_HOLD ->HOLD failed");
+ ALOGE("LOCAL_HOLD -> HOLD failed");
} else {
session->state.current = session->state.new;
}
@@ -382,4 +400,25 @@
return ret;
}
-#endif
+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->config = pcm_config_incall_music;
+ out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
+ out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
+
+ return 0;
+}
+
diff --git a/hal/voice_extn/voice_extn.h b/hal/voice_extn/voice_extn.h
index 568f716..a8efef1 100644
--- a/hal/voice_extn/voice_extn.h
+++ b/hal/voice_extn/voice_extn.h
@@ -20,6 +20,7 @@
#ifndef VOICE_EXTN_H
#define VOICE_EXTN_H
+#ifdef MULTI_VOICE_SESSION_ENABLED
int voice_extn_update_calls(struct audio_device *adev);
int voice_extn_get_session_from_use_case(struct audio_device *adev,
const audio_usecase_t usecase_id,
@@ -30,37 +31,48 @@
int voice_extn_is_in_call(struct audio_device *adev, bool *in_call);
int voice_extn_get_active_session_id(struct audio_device *adev,
uint32_t *session_id);
-
-#ifndef MULTI_VOICE_SESSION_ENABLED
-int voice_extn_update_calls(struct audio_device *adev)
+#else
+static int voice_extn_update_calls(struct audio_device *adev)
{
return -ENOSYS;
}
-int voice_extn_get_session_from_use_case(struct audio_device *adev,
- const audio_usecase_t usecase_id,
- struct voice_session **session)
+static int voice_extn_get_session_from_use_case(struct audio_device *adev,
+ const audio_usecase_t usecase_id,
+ struct voice_session **session)
{
return -ENOSYS;
}
-int voice_extn_init(struct audio_device *adev)
+static int voice_extn_init(struct audio_device *adev)
{
return -ENOSYS;
}
-int voice_extn_set_parameters(struct audio_device *adev,
- struct str_parms *parms)
+static int voice_extn_set_parameters(struct audio_device *adev,
+ struct str_parms *parms)
{
return -ENOSYS;
}
-int voice_extn_is_in_call(struct audio_device *adev, bool *in_call)
+static int voice_extn_is_in_call(struct audio_device *adev, bool *in_call)
{
return -ENOSYS;
}
-int voice_extn_get_active_session_id(struct audio_device *adev,
- uint32_t *session_id)
+
+static int voice_extn_get_active_session_id(struct audio_device *adev,
+ uint32_t *session_id)
+{
+ return -ENOSYS;
+}
+#endif
+
+#if defined INCALL_MUSIC_ENABLED && defined MULTI_VOICE_SESSION_ENABLED
+int voice_extn_check_and_set_incall_music_usecase(struct audio_device *adev,
+ struct stream_out *out);
+#else
+static int voice_extn_check_and_set_incall_music_usecase(struct audio_device *adev,
+ struct stream_out *out)
{
return -ENOSYS;
}