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