audio_hal: add incall recording feature
The uplink, downlink and the combination of both can be
recorded using sound recorder app. Add support for incall
recording feature in audio HAL.
Change-Id: Ia828ab5b3af8044d82b6ef8eb989ae0ba9bbba16
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 3155ab6..0411b34 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -90,6 +90,9 @@
[USECASE_VOICE2_CALL] = "voice2-call",
[USECASE_VOLTE_CALL] = "volte-call",
[USECASE_QCHAT_CALL] = "qchat-call",
+ [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",
};
@@ -619,6 +622,14 @@
struct audio_device *adev = in->dev;
ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
+
+ /* Check if source matches incall recording usecase criteria */
+ ret = voice_check_and_set_incall_rec_usecase(adev, in);
+ if (ret)
+ goto error_config;
+ else
+ ALOGV("%s: usecase(%d)", __func__, in->usecase);
+
in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
if (in->pcm_device_id < 0) {
ALOGE("%s: Could not find PCM device id for the usecase(%d)",
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 2eb1616..9b397b4 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -68,6 +68,10 @@
USECASE_VOLTE_CALL,
USECASE_QCHAT_CALL,
+ USECASE_INCALL_REC_UPLINK,
+ USECASE_INCALL_REC_DOWNLINK,
+ USECASE_INCALL_REC_UPLINK_AND_DOWNLINK,
+
AUDIO_USECASE_MAX
} audio_usecase_t;
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index a2eefdd..78d06c5 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -883,3 +883,9 @@
LOGE("%s: Not implemented", __func__);
return -ENOSYS;
}
+
+int platform_set_incall_recoding_session_id(void *platform, uint32_t session_id)
+{
+ LOGE("%s: Not implemented", __func__);
+ return -ENOSYS;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index ee069d7..44d9b42 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -99,7 +99,7 @@
LOWLATENCY_PCM_DEVICE},
[USECASE_AUDIO_PLAYBACK_MULTI_CH] = {MULTI_CHANNEL_PCM_DEVICE,
MULTI_CHANNEL_PCM_DEVICE},
- [USECASE_AUDIO_RECORD] = {DEEP_BUFFER_PCM_DEVICE, DEEP_BUFFER_PCM_DEVICE},
+ [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE},
[USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
LOWLATENCY_PCM_DEVICE},
[USECASE_AUDIO_PLAYBACK_FM] = {FM_PLAYBACK_PCM_DEVICE, FM_CAPTURE_PCM_DEVICE},
@@ -107,6 +107,12 @@
[USECASE_VOICE2_CALL] = {VOICE2_CALL_PCM_DEVICE, VOICE2_CALL_PCM_DEVICE},
[USECASE_VOLTE_CALL] = {VOLTE_CALL_PCM_DEVICE, VOLTE_CALL_PCM_DEVICE},
[USECASE_QCHAT_CALL] = {QCHAT_CALL_PCM_DEVICE, QCHAT_CALL_PCM_DEVICE},
+ [USECASE_INCALL_REC_UPLINK] = {AUDIO_RECORD_PCM_DEVICE,
+ AUDIO_RECORD_PCM_DEVICE},
+ [USECASE_INCALL_REC_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE,
+ AUDIO_RECORD_PCM_DEVICE},
+ [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = {AUDIO_RECORD_PCM_DEVICE,
+ AUDIO_RECORD_PCM_DEVICE},
};
/* Array to store sound devices */
@@ -947,6 +953,36 @@
return ret;
}
+int platform_set_incall_recoding_session_id(void *platform,
+ uint32_t session_id)
+{
+ int ret = 0;
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_device *adev = my_data->adev;
+ struct mixer_ctl *ctl;
+ const char *mixer_ctl_name = "Voc VSID";
+ int num_ctl_values;
+ int i;
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ ret = -EINVAL;
+ } else {
+ num_ctl_values = mixer_ctl_get_num_values(ctl);
+ for (i = 0; i < num_ctl_values; i++) {
+ if (mixer_ctl_set_value(ctl, i, session_id)) {
+ ALOGV("Error: invalid session_id: %x", session_id);
+ ret = -EINVAL;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
void platform_get_parameters(void *platform,
struct str_parms *query,
struct str_parms *reply)
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index dd8dfda..9d0ff24 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -138,6 +138,7 @@
#define AUDIO_CAPTURE_PERIOD_COUNT 2
#define DEEP_BUFFER_PCM_DEVICE 0
+#define AUDIO_RECORD_PCM_DEVICE 0
#define MULTI_CHANNEL_PCM_DEVICE 1
#define VOICE_CALL_PCM_DEVICE 2
#define FM_PLAYBACK_PCM_DEVICE 5
diff --git a/hal/platform_api.h b/hal/platform_api.h
index b1d0420..39c94e8 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -41,6 +41,6 @@
void platform_get_parameters(void *platform, struct str_parms *query,
struct str_parms *reply);
int platform_set_parameters(void *platform, struct str_parms *parms);
-
+int platform_set_incall_recoding_session_id(void *platform, uint32_t session_id);
#endif // QCOM_AUDIO_PLATFORM_API_H
diff --git a/hal/voice.c b/hal/voice.c
index 2b1ac87..7b40d1a 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -119,7 +119,7 @@
struct audio_usecase *uc_info;
int pcm_dev_rx_id, pcm_dev_tx_id;
struct voice_session *session = NULL;
-
+ struct pcm_config voice_config = pcm_config_voice_call;
ALOGD("%s: enter", __func__);
session = (struct voice_session *)voice_get_session_from_use_case(adev, usecase_id);
@@ -150,7 +150,7 @@
__func__, SOUND_CARD, pcm_dev_rx_id);
session->pcm_rx = pcm_open(SOUND_CARD,
pcm_dev_rx_id,
- PCM_OUT, &pcm_config_voice_call);
+ PCM_OUT, &voice_config);
if (session->pcm_rx && !pcm_is_ready(session->pcm_rx)) {
ALOGE("%s: %s", __func__, pcm_get_error(session->pcm_rx));
ret = -EIO;
@@ -161,7 +161,7 @@
__func__, SOUND_CARD, pcm_dev_tx_id);
session->pcm_tx = pcm_open(SOUND_CARD,
pcm_dev_tx_id,
- PCM_IN, &pcm_config_voice_call);
+ PCM_IN, &voice_config);
if (session->pcm_tx && !pcm_is_ready(session->pcm_tx)) {
ALOGE("%s: %s", __func__, pcm_get_error(session->pcm_tx));
ret = -EIO;
@@ -199,6 +199,54 @@
return in_call;
}
+uint32_t voice_get_active_session_id(struct audio_device *adev)
+{
+ int ret = 0;
+ uint32_t session_id;
+
+ ret = voice_extn_get_active_session_id(adev, &session_id);
+ if (ret == -ENOSYS) {
+ session_id = VOICE_VSID;
+ }
+ return session_id;
+}
+
+int voice_check_and_set_incall_rec_usecase(struct audio_device *adev,
+ struct stream_in *in)
+{
+ int ret = 0;
+ uint32_t session_id;
+ int usecase_id;
+
+ if (voice_is_in_call(adev)) {
+ switch (in->source) {
+ case AUDIO_SOURCE_VOICE_UPLINK:
+ in->usecase = USECASE_INCALL_REC_UPLINK;
+ break;
+ case AUDIO_SOURCE_VOICE_DOWNLINK:
+ in->usecase = USECASE_INCALL_REC_DOWNLINK;
+ break;
+ case AUDIO_SOURCE_VOICE_CALL:
+ in->usecase = USECASE_INCALL_REC_UPLINK_AND_DOWNLINK;
+ break;
+ default:
+ ALOGV("%s: Source type %d doesnt match incall recording criteria",
+ __func__, in->source);
+ return ret;
+ }
+
+ in->config = pcm_config_voice_call;
+ session_id = voice_get_active_session_id(adev);
+ ret = platform_set_incall_recoding_session_id(adev->platform,
+ session_id);
+ ALOGV("%s: Update usecase to %d",__func__, in->usecase);
+ } else {
+ ALOGV("%s: voice call not active", __func__);
+ }
+
+ 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 22c359d..d5e5a8d 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -37,6 +37,7 @@
struct audio_device;
struct str_parms;
+struct stream_in;
struct call_state {
int current;
@@ -65,4 +66,6 @@
int voice_set_mic_mute(struct audio_device *dev, bool state);
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);
#endif //VOICE_H
diff --git a/hal/voice_extn/voice_extn.c b/hal/voice_extn/voice_extn.c
index ac3d9f2..29f12d4 100644
--- a/hal/voice_extn/voice_extn.c
+++ b/hal/voice_extn/voice_extn.c
@@ -103,6 +103,24 @@
return usecase_id;
}
+int voice_extn_get_active_session_id(struct audio_device *adev,
+ uint32_t *session_id)
+{
+ struct voice_session *session = NULL;
+ int i = 0;
+ *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;
+ break;
+ }
+ }
+
+ return 0;
+}
+
int voice_extn_is_in_call(struct audio_device *adev, bool *in_call)
{
struct voice_session *session = NULL;
diff --git a/hal/voice_extn/voice_extn.h b/hal/voice_extn/voice_extn.h
index ae983e1..568f716 100644
--- a/hal/voice_extn/voice_extn.h
+++ b/hal/voice_extn/voice_extn.h
@@ -28,6 +28,8 @@
int voice_extn_set_parameters(struct audio_device *adev,
struct str_parms *parms);
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)
@@ -57,6 +59,11 @@
{
return -ENOSYS;
}
+int voice_extn_get_active_session_id(struct audio_device *adev,
+ uint32_t *session_id)
+{
+ return -ENOSYS;
+}
#endif
#endif //VOICE_EXTN_H