Home | History | Annotate | Download | only in voice_extn
      1 /*
      2  * Copyright (C) 2014-2016 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_extn"
     18 /*#define LOG_NDEBUG 0*/
     19 #define LOG_NDDEBUG 0
     20 
     21 #include <errno.h>
     22 #include <math.h>
     23 #include <stdlib.h>
     24 #include <cutils/log.h>
     25 #include <cutils/str_parms.h>
     26 #include <sys/ioctl.h>
     27 #include <sound/voice_params.h>
     28 
     29 #include "audio_hw.h"
     30 #include "voice.h"
     31 #include "platform.h"
     32 #include "platform_api.h"
     33 #include "voice_extn.h"
     34 
     35 #define AUDIO_PARAMETER_KEY_VSID                "vsid"
     36 #define AUDIO_PARAMETER_KEY_CALL_STATE          "call_state"
     37 #define AUDIO_PARAMETER_KEY_AUDIO_MODE          "audio_mode"
     38 #define AUDIO_PARAMETER_KEY_ALL_CALL_STATES     "all_call_states"
     39 #define AUDIO_PARAMETER_KEY_DEVICE_MUTE         "device_mute"
     40 #define AUDIO_PARAMETER_KEY_DIRECTION           "direction"
     41 
     42 #define VOICE_EXTN_PARAMETER_VALUE_MAX_LEN 256
     43 
     44 #define VOICE2_VSID              0x10DC1000
     45 #define VOLTE_VSID               0x10C02000
     46 #define QCHAT_VSID               0x10803000
     47 #define VOWLAN_VSID              0x10002000
     48 #define VOICEMMODE1_VSID         0x11C05000
     49 #define VOICEMMODE2_VSID         0x11DC5000
     50 #define ALL_VSID                 0xFFFFFFFF
     51 
     52 /* Voice Session Indices */
     53 #define VOICE2_SESS_IDX    (VOICE_SESS_IDX + 1)
     54 #define VOLTE_SESS_IDX     (VOICE_SESS_IDX + 2)
     55 #define QCHAT_SESS_IDX     (VOICE_SESS_IDX + 3)
     56 #define VOWLAN_SESS_IDX    (VOICE_SESS_IDX + 4)
     57 #define MMODE1_SESS_IDX    (VOICE_SESS_IDX + 5)
     58 #define MMODE2_SESS_IDX    (VOICE_SESS_IDX + 6)
     59 
     60 /* Call States */
     61 #define CALL_HOLD           (BASE_CALL_STATE + 2)
     62 #define CALL_LOCAL_HOLD     (BASE_CALL_STATE + 3)
     63 
     64 struct pcm_config pcm_config_incall_music = {
     65     .channels = 1,
     66     .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
     67     .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
     68     .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
     69     .format = PCM_FORMAT_S16_LE,
     70     .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
     71     .stop_threshold = INT_MAX,
     72     .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
     73 };
     74 
     75 int voice_extn_is_call_state_active(struct audio_device *adev, bool *is_call_active);
     76 
     77 static bool is_valid_call_state(int call_state)
     78 {
     79     if (call_state < CALL_INACTIVE || call_state > CALL_LOCAL_HOLD)
     80         return false;
     81     else
     82         return true;
     83 }
     84 
     85 static bool is_valid_vsid(uint32_t vsid)
     86 {
     87     if (vsid == VOICE_VSID ||
     88         vsid == VOICE2_VSID ||
     89         vsid == VOLTE_VSID ||
     90         vsid == QCHAT_VSID ||
     91         vsid == VOICEMMODE1_VSID ||
     92         vsid == VOICEMMODE2_VSID ||
     93         vsid == VOWLAN_VSID)
     94         return true;
     95     else
     96         return false;
     97 }
     98 
     99 static audio_usecase_t voice_extn_get_usecase_for_session_idx(const int index)
    100 {
    101     audio_usecase_t usecase_id = -1;
    102 
    103     switch(index) {
    104     case VOICE_SESS_IDX:
    105         usecase_id = USECASE_VOICE_CALL;
    106         break;
    107 
    108     case VOICE2_SESS_IDX:
    109         usecase_id = USECASE_VOICE2_CALL;
    110         break;
    111 
    112     case VOLTE_SESS_IDX:
    113         usecase_id = USECASE_VOLTE_CALL;
    114         break;
    115 
    116     case QCHAT_SESS_IDX:
    117         usecase_id = USECASE_QCHAT_CALL;
    118         break;
    119 
    120     case VOWLAN_SESS_IDX:
    121         usecase_id = USECASE_VOWLAN_CALL;
    122         break;
    123 
    124     case MMODE1_SESS_IDX:
    125         usecase_id = USECASE_VOICEMMODE1_CALL;
    126         break;
    127 
    128     case MMODE2_SESS_IDX:
    129         usecase_id = USECASE_VOICEMMODE2_CALL;
    130         break;
    131 
    132     default:
    133         ALOGE("%s: Invalid voice session index\n", __func__);
    134     }
    135 
    136     return usecase_id;
    137 }
    138 
    139 static uint32_t get_session_id_with_state(struct audio_device *adev,
    140                                           int call_state)
    141 {
    142     struct voice_session *session = NULL;
    143     int i = 0;
    144     uint32_t session_id = 0;
    145 
    146     for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
    147         session = &adev->voice.session[i];
    148         if(session->state.current == call_state){
    149             session_id = session->vsid;
    150             break;
    151         }
    152     }
    153 
    154     return session_id;
    155 }
    156 
    157 static int update_calls(struct audio_device *adev)
    158 {
    159     int i = 0;
    160     audio_usecase_t usecase_id = 0;
    161     enum voice_lch_mode lch_mode;
    162     struct voice_session *session = NULL;
    163     int fd = 0;
    164     int ret = 0;
    165 
    166     ALOGD("%s: enter:", __func__);
    167 
    168     for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
    169         usecase_id = voice_extn_get_usecase_for_session_idx(i);
    170         session = &adev->voice.session[i];
    171         ALOGD("%s: cur_state=%d new_state=%d vsid=%x",
    172               __func__, session->state.current, session->state.new, session->vsid);
    173 
    174         switch(session->state.new)
    175         {
    176         case CALL_ACTIVE:
    177             switch(session->state.current)
    178             {
    179             case CALL_INACTIVE:
    180                 ALOGD("%s: INACTIVE -> ACTIVE vsid:%x", __func__, session->vsid);
    181                 ret = voice_start_usecase(adev, usecase_id);
    182                 if(ret < 0) {
    183                     ALOGE("%s: voice_start_usecase() failed for usecase: %d\n",
    184                           __func__, usecase_id);
    185                 } else {
    186                     session->state.current = session->state.new;
    187                 }
    188                 break;
    189 
    190             case CALL_HOLD:
    191                 ALOGD("%s: HOLD -> ACTIVE vsid:%x", __func__, session->vsid);
    192                 session->state.current = session->state.new;
    193                 break;
    194 
    195             case CALL_LOCAL_HOLD:
    196                 ALOGD("%s: LOCAL_HOLD -> ACTIVE vsid:%x", __func__, session->vsid);
    197                 lch_mode = VOICE_LCH_STOP;
    198                 if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
    199                     ALOGE("LOCAL_HOLD -> ACTIVE failed");
    200                 } else {
    201                     session->state.current = session->state.new;
    202                 }
    203                 break;
    204 
    205             default:
    206                 ALOGV("%s: CALL_ACTIVE cannot be handled in state=%d vsid:%x",
    207                       __func__, session->state.current, session->vsid);
    208                 break;
    209             }
    210             break;
    211 
    212         case CALL_INACTIVE:
    213             switch(session->state.current)
    214             {
    215             case CALL_ACTIVE:
    216             case CALL_HOLD:
    217             case CALL_LOCAL_HOLD:
    218                 ALOGD("%s: ACTIVE/HOLD/LOCAL_HOLD -> INACTIVE vsid:%x", __func__, session->vsid);
    219                 ret = voice_stop_usecase(adev, usecase_id);
    220                 if(ret < 0) {
    221                     ALOGE("%s: voice_stop_usecase() failed for usecase: %d\n",
    222                           __func__, usecase_id);
    223                 } else {
    224                     session->state.current = session->state.new;
    225                 }
    226                 break;
    227 
    228             default:
    229                 ALOGV("%s: CALL_INACTIVE cannot be handled in state=%d vsid:%x",
    230                       __func__, session->state.current, session->vsid);
    231                 break;
    232             }
    233             break;
    234 
    235         case CALL_HOLD:
    236             switch(session->state.current)
    237             {
    238             case CALL_ACTIVE:
    239                 ALOGD("%s: CALL_ACTIVE -> HOLD vsid:%x", __func__, session->vsid);
    240                 session->state.current = session->state.new;
    241                 break;
    242 
    243             case CALL_LOCAL_HOLD:
    244                 ALOGD("%s: CALL_LOCAL_HOLD -> HOLD vsid:%x", __func__, session->vsid);
    245                 lch_mode = VOICE_LCH_STOP;
    246                 if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
    247                     ALOGE("LOCAL_HOLD -> HOLD failed");
    248                 } else {
    249                     session->state.current = session->state.new;
    250                 }
    251                 break;
    252 
    253             default:
    254                 ALOGV("%s: CALL_HOLD cannot be handled in state=%d vsid:%x",
    255                       __func__, session->state.current, session->vsid);
    256                 break;
    257             }
    258             break;
    259 
    260         case CALL_LOCAL_HOLD:
    261             switch(session->state.current)
    262             {
    263             case CALL_ACTIVE:
    264             case CALL_HOLD:
    265                 ALOGD("%s: ACTIVE/CALL_HOLD -> LOCAL_HOLD vsid:%x", __func__,
    266                       session->vsid);
    267                 lch_mode = VOICE_LCH_START;
    268                 if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
    269                     ALOGE("LOCAL_HOLD -> HOLD failed");
    270                 } else {
    271                     session->state.current = session->state.new;
    272                 }
    273                 break;
    274 
    275             default:
    276                 ALOGV("%s: CALL_LOCAL_HOLD cannot be handled in state=%d vsid:%x",
    277                       __func__, session->state.current, session->vsid);
    278                 break;
    279             }
    280             break;
    281 
    282         default:
    283             break;
    284         } //end out switch loop
    285     } //end for loop
    286 
    287     return ret;
    288 }
    289 
    290 static int update_call_states(struct audio_device *adev,
    291                                     const uint32_t vsid, const int call_state)
    292 {
    293     struct voice_session *session = NULL;
    294     int i = 0;
    295     bool is_call_active;
    296 
    297     for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
    298         if (vsid == adev->voice.session[i].vsid) {
    299             session = &adev->voice.session[i];
    300             break;
    301         }
    302     }
    303 
    304     if (session) {
    305         session->state.new = call_state;
    306         voice_extn_is_call_state_active(adev, &is_call_active);
    307         ALOGD("%s is_call_active:%d in_call:%d, mode:%d\n",
    308               __func__, is_call_active, adev->voice.in_call, adev->mode);
    309         /* Dont start voice call before device routing for voice usescases has
    310          * occured, otherwise voice calls will be started unintendedly on
    311          * speaker.
    312          */
    313         if (is_call_active ||
    314                 (adev->voice.in_call && adev->mode == AUDIO_MODE_IN_CALL)) {
    315             /* Device routing is not triggered for voice calls on the subsequent
    316              * subs, Hence update the call states if voice call is already
    317              * active on other sub.
    318              */
    319             update_calls(adev);
    320         }
    321     } else {
    322         return -EINVAL;
    323     }
    324 
    325     return 0;
    326 
    327 }
    328 
    329 int voice_extn_get_active_session_id(struct audio_device *adev,
    330                                      uint32_t *session_id)
    331 {
    332     *session_id = get_session_id_with_state(adev, CALL_ACTIVE);
    333     return 0;
    334 }
    335 
    336 int voice_extn_is_call_state_active(struct audio_device *adev, bool *is_call_active)
    337 {
    338     struct voice_session *session = NULL;
    339     int i = 0;
    340     *is_call_active = false;
    341 
    342     for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
    343         session = &adev->voice.session[i];
    344         if(session->state.current != CALL_INACTIVE){
    345             *is_call_active = true;
    346             break;
    347         }
    348     }
    349 
    350     return 0;
    351 }
    352 
    353 int voice_extn_is_in_call_rec_stream(struct stream_in *in, bool *in_call_rec)
    354 {
    355     *in_call_rec = false;
    356 
    357     if(in->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
    358        in->source == AUDIO_SOURCE_VOICE_UPLINK ||
    359        in->source == AUDIO_SOURCE_VOICE_CALL) {
    360        *in_call_rec = true;
    361     }
    362 
    363     return 0;
    364 }
    365 
    366 void voice_extn_init(struct audio_device *adev)
    367 {
    368     adev->voice.session[VOICE_SESS_IDX].vsid =  VOICE_VSID;
    369     adev->voice.session[VOICE2_SESS_IDX].vsid = VOICE2_VSID;
    370     adev->voice.session[VOLTE_SESS_IDX].vsid =  VOLTE_VSID;
    371     adev->voice.session[QCHAT_SESS_IDX].vsid =  QCHAT_VSID;
    372     adev->voice.session[VOWLAN_SESS_IDX].vsid = VOWLAN_VSID;
    373     adev->voice.session[MMODE1_SESS_IDX].vsid = VOICEMMODE1_VSID;
    374     adev->voice.session[MMODE2_SESS_IDX].vsid = VOICEMMODE2_VSID;
    375 }
    376 
    377 int voice_extn_get_session_from_use_case(struct audio_device *adev,
    378                                          const audio_usecase_t usecase_id,
    379                                          struct voice_session **session)
    380 {
    381 
    382     switch(usecase_id)
    383     {
    384     case USECASE_VOICE_CALL:
    385         *session = &adev->voice.session[VOICE_SESS_IDX];
    386         break;
    387 
    388     case USECASE_VOICE2_CALL:
    389         *session = &adev->voice.session[VOICE2_SESS_IDX];
    390         break;
    391 
    392     case USECASE_VOLTE_CALL:
    393         *session = &adev->voice.session[VOLTE_SESS_IDX];
    394         break;
    395 
    396     case USECASE_QCHAT_CALL:
    397         *session = &adev->voice.session[QCHAT_SESS_IDX];
    398         break;
    399 
    400     case USECASE_VOWLAN_CALL:
    401         *session = &adev->voice.session[VOWLAN_SESS_IDX];
    402         break;
    403 
    404     case USECASE_VOICEMMODE1_CALL:
    405         *session = &adev->voice.session[MMODE1_SESS_IDX];
    406         break;
    407 
    408     case USECASE_VOICEMMODE2_CALL:
    409         *session = &adev->voice.session[MMODE2_SESS_IDX];
    410         break;
    411 
    412     default:
    413         ALOGE("%s: Invalid usecase_id:%d\n", __func__, usecase_id);
    414         *session = NULL;
    415         return -EINVAL;
    416     }
    417 
    418     return 0;
    419 }
    420 
    421 int voice_extn_start_call(struct audio_device *adev)
    422 {
    423     /* Start voice calls on sessions whose call state has been
    424      * udpated.
    425      */
    426     ALOGV("%s: enter:", __func__);
    427     return update_calls(adev);
    428 }
    429 
    430 int voice_extn_stop_call(struct audio_device *adev)
    431 {
    432     int i;
    433     int ret = 0;
    434 
    435     ALOGV("%s: enter:", __func__);
    436 
    437     /* If BT device is enabled and voice calls are ended, telephony will call
    438      * set_mode(AUDIO_MODE_NORMAL) which will trigger audio policy manager to
    439      * set routing with device BT A2DP profile. Hence end all voice calls when
    440      * set_mode(AUDIO_MODE_NORMAL) before BT A2DP profile is selected.
    441      */
    442     if (adev->mode == AUDIO_MODE_NORMAL) {
    443         ALOGD("%s: end all calls", __func__);
    444         for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
    445             adev->voice.session[i].state.new = CALL_INACTIVE;
    446         }
    447 
    448         ret = update_calls(adev);
    449     }
    450 
    451     return ret;
    452 }
    453 
    454 int voice_extn_set_parameters(struct audio_device *adev,
    455                               struct str_parms *parms)
    456 {
    457     char *str;
    458     int value;
    459     int ret = 0, err;
    460     char *kv_pairs = str_parms_to_str(parms);
    461     char str_value[256] = {0};
    462 
    463     ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs);
    464 
    465     err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_VSID, &value);
    466     if (err >= 0) {
    467         str_parms_del(parms, AUDIO_PARAMETER_KEY_VSID);
    468         uint32_t vsid = value;
    469         int call_state = -1;
    470         err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_CALL_STATE, &value);
    471         if (err >= 0) {
    472             call_state = value;
    473             str_parms_del(parms, AUDIO_PARAMETER_KEY_CALL_STATE);
    474         } else {
    475             ALOGE("%s: call_state key not found", __func__);
    476             ret = -EINVAL;
    477             goto done;
    478         }
    479 
    480         if (is_valid_vsid(vsid) && is_valid_call_state(call_state)) {
    481             ret = update_call_states(adev, vsid, call_state);
    482         } else {
    483             ALOGE("%s: invalid vsid:%x or call_state:%d",
    484                   __func__, vsid, call_state);
    485             ret = -EINVAL;
    486             goto done;
    487         }
    488     }
    489 
    490     err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DEVICE_MUTE, str_value,
    491                             sizeof(str_value));
    492     if (err >= 0) {
    493         str_parms_del(parms, AUDIO_PARAMETER_KEY_DEVICE_MUTE);
    494         bool mute = false;
    495 
    496         if (!strncmp("true", str_value, sizeof("true"))) {
    497             mute = true;
    498         }
    499 
    500         err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DIRECTION, str_value,
    501                                 sizeof(str_value));
    502         if (err >= 0) {
    503             str_parms_del(parms, AUDIO_PARAMETER_KEY_DIRECTION);
    504         } else {
    505             ALOGE("%s: direction key not found", __func__);
    506             ret = -EINVAL;
    507             goto done;
    508         }
    509 
    510         ret = platform_set_device_mute(adev->platform, mute, str_value);
    511         if (ret != 0) {
    512             ALOGE("%s: Failed to set mute err:%d", __func__, ret);
    513             ret = -EINVAL;
    514             goto done;
    515         }
    516     }
    517 
    518 done:
    519     ALOGV("%s: exit with code(%d)", __func__, ret);
    520     free(kv_pairs);
    521     return ret;
    522 }
    523 
    524 static int get_all_call_states_str(const struct audio_device *adev,
    525                             char *value)
    526 {
    527     int ret = 0;
    528     char *cur_ptr = value;
    529     int i, len=0;
    530 
    531     for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
    532         snprintf(cur_ptr, VOICE_EXTN_PARAMETER_VALUE_MAX_LEN - len,
    533                  "%d:%d,",adev->voice.session[i].vsid,
    534                  adev->voice.session[i].state.current);
    535         len = strlen(cur_ptr);
    536         cur_ptr = cur_ptr + len;
    537     }
    538     ALOGV("%s:value=%s", __func__, value);
    539     return ret;
    540 }
    541 
    542 void voice_extn_get_parameters(const struct audio_device *adev,
    543                                struct str_parms *query,
    544                                struct str_parms *reply)
    545 {
    546     int ret;
    547     char value[VOICE_EXTN_PARAMETER_VALUE_MAX_LEN] = {0};
    548     char *str = str_parms_to_str(query);
    549 
    550     ALOGV_IF(str != NULL, "%s: enter %s", __func__, str);
    551     free(str);
    552 
    553     ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_AUDIO_MODE, value,
    554                             sizeof(value));
    555     if (ret >= 0) {
    556         str_parms_add_int(reply, AUDIO_PARAMETER_KEY_AUDIO_MODE, adev->mode);
    557     }
    558 
    559     ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_ALL_CALL_STATES,
    560                             value, sizeof(value));
    561     if (ret >= 0) {
    562         ret = get_all_call_states_str(adev, value);
    563         if (ret) {
    564             ALOGE("%s: Error fetching call states, err:%d", __func__, ret);
    565             return;
    566         }
    567         str_parms_add_str(reply, AUDIO_PARAMETER_KEY_ALL_CALL_STATES, value);
    568     }
    569 
    570     str = str_parms_to_str(reply);
    571     ALOGV_IF(str != NULL, "%s: exit: returns \"%s\"", __func__, str);
    572     free(str);
    573 }
    574 
    575 #ifdef INCALL_MUSIC_ENABLED
    576 int voice_extn_check_and_set_incall_music_usecase(struct audio_device *adev,
    577                                                   struct stream_out *out)
    578 {
    579     uint32_t session_id = 0;
    580 
    581     session_id = get_session_id_with_state(adev, CALL_LOCAL_HOLD);
    582     if (session_id == VOICE_VSID) {
    583         out->usecase = USECASE_INCALL_MUSIC_UPLINK;
    584     } else if (session_id == VOICE2_VSID) {
    585         out->usecase = USECASE_INCALL_MUSIC_UPLINK2;
    586     } else {
    587         ALOGE("%s: Invalid session id %x", __func__, session_id);
    588         return -EINVAL;
    589     }
    590 
    591     out->config = pcm_config_incall_music;
    592     out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
    593     out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
    594 
    595     return 0;
    596 }
    597 #endif
    598 
    599