• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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