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