hal: In-call recording and In-call music support on APQ targets

-In-call recording feature support is added in APQ.
-In-call music delivery support is added in APQ.

Change-Id: Id473eac87da33f1f566b6910ec1feadcd3f08317
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index df040e2..a35fc43 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -734,6 +734,9 @@
         return -EINVAL;
     }
 
+    /* Close in-call recording streams */
+    voice_check_and_stop_incall_rec_usecase(adev, in);
+
     /* 1. Disable stream specific mixer controls */
     disable_audio_route(adev, uc_info, true);
 
@@ -2323,6 +2326,7 @@
     int ret;
 
     pthread_mutex_lock(&adev->lock);
+    ALOGD("%s state %d\n", __func__, state);
     ret = voice_set_mic_mute((struct audio_device *)dev, state);
     pthread_mutex_unlock(&adev->lock);
 
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index a207c2f..3b736f0 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -1326,8 +1326,8 @@
     return ret;
 }
 
-int platform_set_incall_recoding_session_id(void *platform,
-                                            uint32_t session_id)
+int platform_set_incall_recording_session_id(void *platform,
+                                             uint32_t session_id, int rec_mode)
 {
     int ret = 0;
     struct platform_data *my_data = (struct platform_data *)platform;
@@ -1353,6 +1353,62 @@
         }
     }
 
+    if (my_data->csd != NULL) {
+        ret = my_data->csd->start_record(ALL_SESSION_VSID, rec_mode);
+        if (ret < 0) {
+            ALOGE("%s: csd_client_start_record failed, error %d",
+                  __func__, ret);
+        }
+    }
+
+    return ret;
+}
+
+int platform_stop_incall_recording_usecase(void *platform)
+{
+    int ret = 0;
+    struct platform_data *my_data = (struct platform_data *)platform;
+
+    if (my_data->csd != NULL) {
+        ret = my_data->csd->stop_record(ALL_SESSION_VSID);
+        if (ret < 0) {
+            ALOGE("%s: csd_client_stop_record failed, error %d",
+                  __func__, ret);
+        }
+    }
+
+    return ret;
+}
+
+int platform_start_incall_music_usecase(void *platform)
+{
+    int ret = 0;
+    struct platform_data *my_data = (struct platform_data *)platform;
+
+    if (my_data->csd != NULL) {
+        ret = my_data->csd->start_playback(ALL_SESSION_VSID);
+        if (ret < 0) {
+            ALOGE("%s: csd_client_start_playback failed, error %d",
+                  __func__, ret);
+        }
+    }
+
+    return ret;
+}
+
+int platform_stop_incall_music_usecase(void *platform)
+{
+    int ret = 0;
+    struct platform_data *my_data = (struct platform_data *)platform;
+
+    if (my_data->csd != NULL) {
+        ret = my_data->csd->stop_playback(ALL_SESSION_VSID);
+        if (ret < 0) {
+            ALOGE("%s: csd_client_stop_playback failed, error %d",
+                  __func__, ret);
+        }
+    }
+
     return ret;
 }
 
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 7d80906..bc054cf 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -215,7 +215,7 @@
 typedef int (*start_playback_t)(uint32_t);
 typedef int (*stop_playback_t)(uint32_t);
 typedef int (*start_record_t)(uint32_t, int);
-typedef int (*stop_record_t)(uint32_t, int);
+typedef int (*stop_record_t)(uint32_t);
 /* CSD Client structure */
 struct csd_data {
     void *csd_client;
diff --git a/hal/platform_api.h b/hal/platform_api.h
index a829365..4096ef0 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -46,8 +46,11 @@
 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);
-
+int platform_set_incall_recording_session_id(void *platform, uint32_t session_id,
+                                             int rec_mode);
+int platform_stop_incall_recording_usecase(void *platform);
+int platform_start_incall_music_usecase(void *platform);
+int platform_stop_incall_music_usecase(void *platform);
 /* returns the latency for a usecase in Us */
 int64_t platform_render_latency(audio_usecase_t usecase);
 int platform_update_usecase_from_source(int source, audio_usecase_t usecase);
diff --git a/hal/voice.c b/hal/voice.c
index c6c513a..25b53d4 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -202,22 +202,26 @@
 }
 
 int voice_check_and_set_incall_rec_usecase(struct audio_device *adev,
-                                       struct stream_in *in)
+                                           struct stream_in *in)
 {
     int ret = 0;
     uint32_t session_id;
     int usecase_id;
+    int rec_mode = INCALL_REC_NONE;
 
     if (voice_is_in_call(adev)) {
         switch (in->source) {
         case AUDIO_SOURCE_VOICE_UPLINK:
             in->usecase = USECASE_INCALL_REC_UPLINK;
+            rec_mode = INCALL_REC_UPLINK;
             break;
         case AUDIO_SOURCE_VOICE_DOWNLINK:
             in->usecase = USECASE_INCALL_REC_DOWNLINK;
+            rec_mode = INCALL_REC_DOWNLINK;
             break;
         case AUDIO_SOURCE_VOICE_CALL:
             in->usecase = USECASE_INCALL_REC_UPLINK_AND_DOWNLINK;
+            rec_mode = INCALL_REC_UPLINK_AND_DOWNLINK;
             break;
         default:
             ALOGV("%s: Source type %d doesnt match incall recording criteria",
@@ -226,8 +230,8 @@
         }
 
         session_id = voice_get_active_session_id(adev);
-        ret = platform_set_incall_recoding_session_id(adev->platform,
-                                                      session_id);
+        ret = platform_set_incall_recording_session_id(adev->platform,
+                                                       session_id, rec_mode);
         ALOGV("%s: Update usecase to %d",__func__, in->usecase);
     } else {
         ALOGV("%s: voice call not active", __func__);
@@ -236,6 +240,21 @@
     return ret;
 }
 
+int voice_check_and_stop_incall_rec_usecase(struct audio_device *adev,
+                                            struct stream_in *in)
+{
+    int ret = 0;
+
+    if (in->source == AUDIO_SOURCE_VOICE_UPLINK ||
+        in->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
+        in->source == AUDIO_SOURCE_VOICE_CALL) {
+        ret = platform_stop_incall_recording_usecase(adev->platform);
+        ALOGV("%s: Stop In-call recording", __func__);
+    }
+
+    return ret;
+}
+
 int voice_check_and_set_incall_music_usecase(struct audio_device *adev,
                                              struct stream_out *out)
 {
@@ -358,6 +377,16 @@
         }
     }
 
+    ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_INCALLMUSIC,
+                            value, sizeof(value));
+    if (ret >= 0) {
+        str_parms_del(parms, AUDIO_PARAMETER_KEY_INCALLMUSIC);
+        if (strcmp(value, AUDIO_PARAMETER_VALUE_TRUE) == 0)
+            platform_start_incall_music_usecase(adev->platform);
+        else
+            platform_stop_incall_music_usecase(adev->platform);
+     }
+
 done:
     ALOGV("%s: exit with code(%d)", __func__, ret);
     return ret;
diff --git a/hal/voice.h b/hal/voice.h
index 7f8b25b..eeb65dc 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -35,6 +35,9 @@
 
 #define VOICE_VSID  0x10C01000
 
+#define AUDIO_PARAMETER_KEY_INCALLMUSIC "incall_music_enabled"
+#define AUDIO_PARAMETER_VALUE_TRUE "true"
+
 struct audio_device;
 struct str_parms;
 struct stream_in;
@@ -59,6 +62,13 @@
     float volume;
 };
 
+enum {
+    INCALL_REC_NONE = -1,
+    INCALL_REC_UPLINK,
+    INCALL_REC_DOWNLINK,
+    INCALL_REC_UPLINK_AND_DOWNLINK,
+};
+
 int voice_start_call(struct audio_device *adev);
 int voice_stop_call(struct audio_device *adev);
 int voice_set_parameters(struct audio_device *adev, struct str_parms *parms);
@@ -71,4 +81,6 @@
                                            struct stream_in *in);
 int voice_check_and_set_incall_music_usecase(struct audio_device *adev,
                                              struct stream_out *out);
+int voice_check_and_stop_incall_rec_usecase(struct audio_device *adev,
+                                            struct stream_in *in);
 #endif //VOICE_H