Home | History | Annotate | Download | only in hal
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "voice"
     18 /*#define LOG_NDEBUG 0*/
     19 #define LOG_NDDEBUG 0
     20 
     21 #include <stdlib.h>
     22 #include <errno.h>
     23 #include <math.h>
     24 #include <cutils/log.h>
     25 #include <cutils/str_parms.h>
     26 
     27 #include "audio_hw.h"
     28 #include "voice.h"
     29 #include "voice_extn/voice_extn.h"
     30 #include "platform.h"
     31 #include "platform_api.h"
     32 #include "audio_extn/tfa_98xx.h"
     33 
     34 struct pcm_config pcm_config_voice_call = {
     35     .channels = 1,
     36     .rate = 8000,
     37     .period_size = 160,
     38     .period_count = 2,
     39     .format = PCM_FORMAT_S16_LE,
     40 };
     41 
     42 static struct voice_session *voice_get_session_from_use_case(struct audio_device *adev,
     43                               audio_usecase_t usecase_id)
     44 {
     45     struct voice_session *session = NULL;
     46     int ret = 0;
     47 
     48     ret = voice_extn_get_session_from_use_case(adev, usecase_id, &session);
     49     if (ret == -ENOSYS) {
     50         session = &adev->voice.session[VOICE_SESS_IDX];
     51     }
     52 
     53     return session;
     54 }
     55 
     56 static bool voice_is_sidetone_device(snd_device_t out_device,
     57             char *mixer_path)
     58 {
     59     bool is_sidetone_dev = true;
     60 
     61     switch (out_device) {
     62     case SND_DEVICE_OUT_VOICE_HAC_HANDSET:
     63         strlcpy(mixer_path, "sidetone-hac-handset", MIXER_PATH_MAX_LENGTH);
     64         break;
     65     case SND_DEVICE_OUT_VOICE_HANDSET:
     66         strlcpy(mixer_path, "sidetone-handset", MIXER_PATH_MAX_LENGTH);
     67         break;
     68     case SND_DEVICE_OUT_VOICE_HEADPHONES:
     69         strlcpy(mixer_path, "sidetone-headphones", MIXER_PATH_MAX_LENGTH);
     70         break;
     71     case SND_DEVICE_OUT_VOICE_USB_HEADSET:
     72     case SND_DEVICE_OUT_USB_HEADSET:
     73         // USB does not use a QC mixer.
     74         mixer_path[0] = '\0';
     75         break;
     76     default:
     77         ALOGW("%s: %d is not a sidetone device", __func__, out_device);
     78         is_sidetone_dev = false;
     79         break;
     80     }
     81 
     82     return is_sidetone_dev;
     83 }
     84 
     85 void voice_set_sidetone(struct audio_device *adev,
     86         snd_device_t out_snd_device, bool enable)
     87 {
     88     char mixer_path[MIXER_PATH_MAX_LENGTH];
     89     bool is_sidetone_dev;
     90 
     91     ALOGD("%s: %s, out_snd_device: %d\n",
     92           __func__, (enable ? "enable" : "disable"),
     93           out_snd_device);
     94 
     95     if (voice_is_sidetone_device(out_snd_device, mixer_path))
     96         platform_set_sidetone(adev, out_snd_device, enable, mixer_path);
     97 
     98     return;
     99 }
    100 
    101 int voice_stop_usecase(struct audio_device *adev, audio_usecase_t usecase_id)
    102 {
    103     int i, ret = 0;
    104     struct audio_usecase *uc_info;
    105     struct voice_session *session = NULL;
    106 
    107     ALOGD("%s: enter usecase:%s", __func__, use_case_table[usecase_id]);
    108 
    109     session = (struct voice_session *)voice_get_session_from_use_case(adev, usecase_id);
    110 
    111     uc_info = get_usecase_from_list(adev, usecase_id);
    112     if (uc_info == NULL) {
    113         ALOGE("%s: Could not find the usecase (%d) in the list",
    114               __func__, usecase_id);
    115         return -EINVAL;
    116     }
    117 
    118     session->state.current = CALL_INACTIVE;
    119 
    120     /* Disable sidetone only when no calls are active */
    121     if (!voice_is_call_state_active(adev))
    122         voice_set_sidetone(adev, uc_info->out_snd_device, false);
    123 
    124     ret = platform_stop_voice_call(adev->platform, session->vsid);
    125 
    126     /* 1. Close the PCM devices */
    127     if (session->pcm_rx) {
    128         pcm_close(session->pcm_rx);
    129         session->pcm_rx = NULL;
    130     }
    131     if (session->pcm_tx) {
    132         pcm_close(session->pcm_tx);
    133         session->pcm_tx = NULL;
    134     }
    135 
    136     /* 2. Get and set stream specific mixer controls */
    137     disable_audio_route(adev, uc_info);
    138 
    139     /* 3. Disable the rx and tx devices */
    140     disable_snd_device(adev, uc_info->out_snd_device);
    141     disable_snd_device(adev, uc_info->in_snd_device);
    142 
    143     if (audio_extn_tfa_98xx_is_supported() && voice_get_mic_mute(adev)) {
    144         voice_set_mic_mute(adev, false);
    145         ALOGD("%s: unMute voice Tx", __func__);
    146     }
    147 
    148     list_remove(&uc_info->list);
    149     free(uc_info);
    150 
    151     ALOGD("%s: exit: status(%d)", __func__, ret);
    152     return ret;
    153 }
    154 
    155 int voice_start_usecase(struct audio_device *adev, audio_usecase_t usecase_id)
    156 {
    157     int i, ret = 0;
    158     struct audio_usecase *uc_info;
    159     int pcm_dev_rx_id, pcm_dev_tx_id;
    160     struct voice_session *session = NULL;
    161     struct pcm_config voice_config = pcm_config_voice_call;
    162 
    163     ALOGD("%s: enter usecase:%s", __func__, use_case_table[usecase_id]);
    164 
    165     session = (struct voice_session *)voice_get_session_from_use_case(adev, usecase_id);
    166     uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
    167     uc_info->id = usecase_id;
    168     uc_info->type = VOICE_CALL;
    169     uc_info->stream.out = adev->current_call_output ;
    170     uc_info->devices = adev->current_call_output ->devices;
    171     uc_info->in_snd_device = SND_DEVICE_NONE;
    172     uc_info->out_snd_device = SND_DEVICE_NONE;
    173 
    174     list_add_tail(&adev->usecase_list, &uc_info->list);
    175 
    176     select_devices(adev, usecase_id);
    177 
    178     pcm_dev_rx_id = platform_get_pcm_device_id(uc_info->id, PCM_PLAYBACK);
    179     pcm_dev_tx_id = platform_get_pcm_device_id(uc_info->id, PCM_CAPTURE);
    180 
    181     if (pcm_dev_rx_id < 0 || pcm_dev_tx_id < 0) {
    182         ALOGE("%s: Invalid PCM devices (rx: %d tx: %d) for the usecase(%d)",
    183               __func__, pcm_dev_rx_id, pcm_dev_tx_id, uc_info->id);
    184         ret = -EIO;
    185         goto error_start_voice;
    186     }
    187 
    188     ALOGV("%s: Opening PCM capture device card_id(%d) device_id(%d)",
    189           __func__, adev->snd_card, pcm_dev_tx_id);
    190     session->pcm_tx = pcm_open(adev->snd_card,
    191                                pcm_dev_tx_id,
    192                                PCM_IN, &voice_config);
    193     if (session->pcm_tx && !pcm_is_ready(session->pcm_tx)) {
    194         ALOGE("%s: %s", __func__, pcm_get_error(session->pcm_tx));
    195         ret = -EIO;
    196         goto error_start_voice;
    197     }
    198 
    199     ALOGV("%s: Opening PCM playback device card_id(%d) device_id(%d)",
    200           __func__, adev->snd_card, pcm_dev_rx_id);
    201     session->pcm_rx = pcm_open(adev->snd_card,
    202                                pcm_dev_rx_id,
    203                                PCM_OUT, &voice_config);
    204     if (session->pcm_rx && !pcm_is_ready(session->pcm_rx)) {
    205         ALOGE("%s: %s", __func__, pcm_get_error(session->pcm_rx));
    206         ret = -EIO;
    207         goto error_start_voice;
    208     }
    209 
    210     pcm_start(session->pcm_tx);
    211     pcm_start(session->pcm_rx);
    212 
    213     audio_extn_tfa_98xx_enable_speaker();
    214 
    215     /* Enable sidetone only when no calls are already active */
    216     if (!voice_is_call_state_active(adev))
    217         voice_set_sidetone(adev, uc_info->out_snd_device, true);
    218 
    219     voice_set_volume(adev, adev->voice.volume);
    220 
    221     ret = platform_start_voice_call(adev->platform, session->vsid);
    222     if (ret < 0) {
    223         ALOGE("%s: platform_start_voice_call error %d\n", __func__, ret);
    224         goto error_start_voice;
    225     }
    226 
    227     session->state.current = CALL_ACTIVE;
    228     goto done;
    229 
    230 error_start_voice:
    231     voice_stop_usecase(adev, usecase_id);
    232 
    233 done:
    234     ALOGD("%s: exit: status(%d)", __func__, ret);
    235     return ret;
    236 }
    237 
    238 bool voice_is_call_state_active(struct audio_device *adev)
    239 {
    240     bool call_state = false;
    241     int ret = 0;
    242 
    243     ret = voice_extn_is_call_state_active(adev, &call_state);
    244     if (ret == -ENOSYS) {
    245         call_state = (adev->voice.session[VOICE_SESS_IDX].state.current == CALL_ACTIVE) ? true : false;
    246     }
    247 
    248     return call_state;
    249 }
    250 
    251 bool voice_is_in_call(struct audio_device *adev)
    252 {
    253     return adev->voice.in_call;
    254 }
    255 
    256 bool voice_is_in_call_rec_stream(struct stream_in *in)
    257 {
    258     bool in_call_rec = false;
    259     int ret = 0;
    260 
    261     ret = voice_extn_is_in_call_rec_stream(in, &in_call_rec);
    262     if (ret == -ENOSYS) {
    263         in_call_rec = false;
    264     }
    265 
    266     return in_call_rec;
    267 }
    268 
    269 uint32_t voice_get_active_session_id(struct audio_device *adev)
    270 {
    271     int ret = 0;
    272     uint32_t session_id;
    273 
    274     ret = voice_extn_get_active_session_id(adev, &session_id);
    275     if (ret == -ENOSYS) {
    276         session_id = VOICE_VSID;
    277     }
    278     return session_id;
    279 }
    280 
    281 int voice_check_and_set_incall_rec_usecase(struct audio_device *adev,
    282                                            struct stream_in *in)
    283 {
    284     int ret = 0;
    285     uint32_t session_id;
    286     int usecase_id;
    287     int rec_mode = INCALL_REC_NONE;
    288 
    289     if (voice_is_call_state_active(adev)) {
    290         switch (in->source) {
    291         case AUDIO_SOURCE_VOICE_UPLINK:
    292             in->usecase = USECASE_INCALL_REC_UPLINK;
    293             rec_mode = INCALL_REC_UPLINK;
    294             break;
    295         case AUDIO_SOURCE_VOICE_DOWNLINK:
    296             in->usecase = USECASE_INCALL_REC_DOWNLINK;
    297             rec_mode = INCALL_REC_DOWNLINK;
    298             break;
    299         case AUDIO_SOURCE_VOICE_CALL:
    300             in->usecase = USECASE_INCALL_REC_UPLINK_AND_DOWNLINK;
    301             rec_mode = INCALL_REC_UPLINK_AND_DOWNLINK;
    302             break;
    303         default:
    304             ALOGV("%s: Source type %d doesnt match incall recording criteria",
    305                   __func__, in->source);
    306             return ret;
    307         }
    308 
    309         session_id = voice_get_active_session_id(adev);
    310         ret = platform_set_incall_recording_session_id(adev->platform,
    311                                                        session_id, rec_mode);
    312         ALOGV("%s: Update usecase to %d",__func__, in->usecase);
    313     } else {
    314         ALOGV("%s: voice call not active", __func__);
    315     }
    316 
    317     return ret;
    318 }
    319 
    320 int voice_check_and_stop_incall_rec_usecase(struct audio_device *adev,
    321                                             struct stream_in *in)
    322 {
    323     int ret = 0;
    324 
    325     if (in->source == AUDIO_SOURCE_VOICE_UPLINK ||
    326         in->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
    327         in->source == AUDIO_SOURCE_VOICE_CALL) {
    328         ret = platform_stop_incall_recording_usecase(adev->platform);
    329         ALOGV("%s: Stop In-call recording", __func__);
    330     }
    331 
    332     return ret;
    333 }
    334 
    335 int voice_check_and_set_incall_music_usecase(struct audio_device *adev,
    336                                              struct stream_out *out)
    337 {
    338     int ret = 0;
    339 
    340     ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
    341     if (ret == -ENOSYS) {
    342         /* Incall music delivery is used only for LCH call state */
    343         ret = -EINVAL;
    344     }
    345 
    346     return ret;
    347 }
    348 
    349 int voice_set_mic_mute(struct audio_device *adev, bool state)
    350 {
    351     int err = 0;
    352 
    353     adev->voice.mic_mute = state;
    354     if (adev->mode == AUDIO_MODE_IN_CALL ||
    355         adev->mode == AUDIO_MODE_IN_COMMUNICATION)
    356         err = platform_set_mic_mute(adev->platform, state);
    357 
    358     return err;
    359 }
    360 
    361 bool voice_get_mic_mute(struct audio_device *adev)
    362 {
    363     return adev->voice.mic_mute;
    364 }
    365 
    366 int voice_set_volume(struct audio_device *adev, float volume)
    367 {
    368     int vol, err = 0;
    369 
    370     adev->voice.volume = volume;
    371     if (adev->mode == AUDIO_MODE_IN_CALL) {
    372         if (volume < 0.0) {
    373             volume = 0.0;
    374         } else if (volume > 1.0) {
    375             volume = 1.0;
    376         }
    377 
    378         vol = lrint(volume * 100.0);
    379 
    380         // Voice volume levels from android are mapped to driver volume levels as follows.
    381         // 0 -> 5, 20 -> 4, 40 ->3, 60 -> 2, 80 -> 1, 100 -> 0
    382         // So adjust the volume to get the correct volume index in driver
    383         vol = 100 - vol;
    384 
    385         err = platform_set_voice_volume(adev->platform, vol);
    386     }
    387 
    388     return err;
    389 }
    390 
    391 int voice_start_call(struct audio_device *adev)
    392 {
    393     int ret = 0;
    394 
    395     adev->voice.in_call = true;
    396 
    397     voice_set_mic_mute(adev, adev->voice.mic_mute);
    398 
    399     ret = voice_extn_start_call(adev);
    400     if (ret == -ENOSYS) {
    401         ret = voice_start_usecase(adev, USECASE_VOICE_CALL);
    402     }
    403 
    404     return ret;
    405 }
    406 
    407 int voice_stop_call(struct audio_device *adev)
    408 {
    409     int ret = 0;
    410 
    411     adev->voice.in_call = false;
    412     ret = voice_extn_stop_call(adev);
    413     if (ret == -ENOSYS) {
    414         ret = voice_stop_usecase(adev, USECASE_VOICE_CALL);
    415     }
    416 
    417     return ret;
    418 }
    419 
    420 void voice_get_parameters(struct audio_device *adev,
    421                           struct str_parms *query,
    422                           struct str_parms *reply)
    423 {
    424     voice_extn_get_parameters(adev, query, reply);
    425 }
    426 
    427 int voice_set_parameters(struct audio_device *adev, struct str_parms *parms)
    428 {
    429     char *str;
    430     char value[32];
    431     int val;
    432     int ret = 0, err;
    433     char *kv_pairs = str_parms_to_str(parms);
    434 
    435     ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs);
    436 
    437     ret = voice_extn_set_parameters(adev, parms);
    438     if (ret != 0) {
    439         if (ret == -ENOSYS) {
    440             ret = 0; /* ignore error */
    441         } else {
    442             goto done;
    443         }
    444     }
    445 
    446     err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_TTY_MODE, value, sizeof(value));
    447     if (err >= 0) {
    448         int tty_mode;
    449         str_parms_del(parms, AUDIO_PARAMETER_KEY_TTY_MODE);
    450         if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_OFF) == 0)
    451             tty_mode = TTY_MODE_OFF;
    452         else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_VCO) == 0)
    453             tty_mode = TTY_MODE_VCO;
    454         else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_HCO) == 0)
    455             tty_mode = TTY_MODE_HCO;
    456         else if (strcmp(value, AUDIO_PARAMETER_VALUE_TTY_FULL) == 0)
    457             tty_mode = TTY_MODE_FULL;
    458         else {
    459             ret = -EINVAL;
    460             goto done;
    461         }
    462 
    463         if (tty_mode != adev->voice.tty_mode) {
    464             adev->voice.tty_mode = tty_mode;
    465             adev->acdb_settings = (adev->acdb_settings & TTY_MODE_CLEAR) | tty_mode;
    466             if (voice_is_call_state_active(adev))
    467                voice_update_devices_for_all_voice_usecases(adev);
    468         }
    469     }
    470 
    471     err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_HAC,
    472                             value, sizeof(value));
    473     if (err >= 0) {
    474         bool hac = false;
    475         str_parms_del(parms, AUDIO_PARAMETER_KEY_HAC);
    476         if (strcmp(value, AUDIO_PARAMETER_VALUE_HAC_ON) == 0)
    477             hac = true;
    478 
    479         if (hac != adev->voice.hac) {
    480             adev->voice.hac = hac;
    481             if (voice_is_in_call(adev))
    482                 voice_update_devices_for_all_voice_usecases(adev);
    483         }
    484      }
    485 
    486     err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_INCALLMUSIC,
    487                             value, sizeof(value));
    488     if (err >= 0) {
    489         str_parms_del(parms, AUDIO_PARAMETER_KEY_INCALLMUSIC);
    490         if (strcmp(value, AUDIO_PARAMETER_VALUE_TRUE) == 0)
    491             platform_start_incall_music_usecase(adev->platform);
    492         else
    493             platform_stop_incall_music_usecase(adev->platform);
    494      }
    495 
    496 done:
    497     ALOGV("%s: exit with code(%d)", __func__, ret);
    498     free(kv_pairs);
    499     return ret;
    500 }
    501 
    502 void voice_init(struct audio_device *adev)
    503 {
    504     int i = 0;
    505 
    506     memset(&adev->voice, 0, sizeof(adev->voice));
    507     adev->voice.tty_mode = TTY_MODE_OFF;
    508     adev->voice.hac = false;
    509     adev->voice.volume = 1.0f;
    510     adev->voice.mic_mute = false;
    511     adev->voice.in_call = false;
    512     for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
    513         adev->voice.session[i].pcm_rx = NULL;
    514         adev->voice.session[i].pcm_tx = NULL;
    515         adev->voice.session[i].state.current = CALL_INACTIVE;
    516         adev->voice.session[i].state.new = CALL_INACTIVE;
    517         adev->voice.session[i].vsid = VOICE_VSID;
    518     }
    519 
    520     voice_extn_init(adev);
    521 }
    522 
    523 void voice_update_devices_for_all_voice_usecases(struct audio_device *adev)
    524 {
    525     struct listnode *node;
    526     struct audio_usecase *usecase;
    527 
    528     list_for_each(node, &adev->usecase_list) {
    529         usecase = node_to_item(node, struct audio_usecase, list);
    530         if (usecase->type == VOICE_CALL) {
    531             ALOGV("%s: updating device for usecase:%s", __func__,
    532                   use_case_table[usecase->id]);
    533             usecase->stream.out = adev->current_call_output;
    534             select_devices(adev, usecase->id);
    535             audio_extn_tfa_98xx_update();
    536         }
    537     }
    538 }
    539 
    540 
    541