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