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 <log/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
is_valid_call_state(int call_state)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
is_valid_vsid(uint32_t vsid)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
voice_extn_get_usecase_for_session_idx(const int index)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
get_session_id_with_state(struct audio_device * adev,int call_state)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
update_calls(struct audio_device * adev)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
update_call_states(struct audio_device * adev,const uint32_t vsid,const int call_state)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
voice_extn_get_active_session_id(struct audio_device * adev,uint32_t * session_id)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
voice_extn_is_call_state_active(struct audio_device * adev,bool * is_call_active)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
voice_extn_is_in_call_rec_stream(struct stream_in * in,bool * in_call_rec)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
voice_extn_init(struct audio_device * adev)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
voice_extn_get_session_from_use_case(struct audio_device * adev,const audio_usecase_t usecase_id,struct voice_session ** session)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
voice_extn_start_call(struct audio_device * adev)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
voice_extn_stop_call(struct audio_device * adev)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
voice_extn_set_parameters(struct audio_device * adev,struct str_parms * parms)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
get_all_call_states_str(const struct audio_device * adev,char * value)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
voice_extn_get_parameters(const struct audio_device * adev,struct str_parms * query,struct str_parms * reply)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
voice_extn_check_and_set_incall_music_usecase(struct audio_device * adev,struct stream_out * out)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 = get_session_id_with_state(adev, CALL_ACTIVE);
580 if (session_id == VOICEMMODE1_VSID)
581 out->usecase = USECASE_INCALL_MUSIC_UPLINK;
582 else if (session_id == VOICEMMODE2_VSID)
583 out->usecase = USECASE_INCALL_MUSIC_UPLINK2;
584 else {
585 ALOGE("%s: Invalid session id %x", __func__, session_id);
586 out->usecase = USECASE_INCALL_MUSIC_UPLINK;
587 }
588
589 out->config = pcm_config_incall_music;
590 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
591 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
592 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
593 out->config.rate = out->sample_rate;
594
595 ALOGV("%s: mode=%d, usecase id=%d", __func__, adev->mode, out->usecase);
596 return 0;
597 }
598 #endif
599
600