1 /*
2  * Copyright (c) 2015, The Linux Foundation. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *   * Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *   * Redistributions in binary form must reproduce the above
10  *     copyright notice, this list of conditions and the following
11  *     disclaimer in the documentation and/or other materials provided
12  *     with the distribution.
13  *   * Neither the name of The Linux Foundation nor the names of its
14  *     contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 #define LOG_TAG "source_track"
30 /*#define LOG_NDEBUG 0*/
31 #define LOG_NDDEBUG 0
32 
33 #include <errno.h>
34 #include <math.h>
35 #include <cutils/log.h>
36 
37 #include "audio_hw.h"
38 #include "platform.h"
39 #include "platform_api.h"
40 #include "voice_extn.h"
41 #include <stdlib.h>
42 #include <cutils/str_parms.h>
43 
44 #ifdef SOURCE_TRACKING_ENABLED
45 /* Audio Paramater Key to identify the list of start angles.
46  * Starting angle (in degrees) defines the boundary starting angle for each sector.
47  */
48 #define AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES        "SoundFocus.start_angles"
49 /* Audio Paramater Key to identify the list of enable flags corresponding to each sector.
50  */
51 #define AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS      "SoundFocus.enable_sectors"
52 /* Audio Paramater Key to identify the gain step value to be applied to all enabled sectors.
53  */
54 #define AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP           "SoundFocus.gain_step"
55 /* Audio Paramater Key to identify the list of voice activity detector outputs corresponding
56  * to each sector.
57  */
58 #define AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD                "SourceTrack.vad"
59 /* Audio Paramater Key to identify the direction (in degrees) of arrival for desired talker
60  * (dominant source of speech).
61  */
62 #define AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH         "SourceTrack.doa_speech"
63 /* Audio Paramater Key to identify the list of directions (in degrees) of arrival for
64  * interferers (interfering noise sources).
65  */
66 #define AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE          "SourceTrack.doa_noise"
67 /* Audio Paramater Key to identify the list of sound strength indicators at each degree
68  * of the horizontal plane referred to by a full circle (360 degrees).
69  */
70 #define AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY     "SourceTrack.polar_activity"
71 
72 #define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES        0x1
73 #define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS      0x2
74 #define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP           0x4
75 #define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD                0x8
76 #define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH         0x10
77 #define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE          0x20
78 #define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY     0x40
79 
80 #define BITMASK_AUDIO_PARAMETER_KEYS_SOUND_FOCUS \
81      (BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES |\
82       BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS |\
83       BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP)
84 
85 #define BITMASK_AUDIO_PARAMETER_KEYS_SOURCE_TRACKING \
86      (BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD |\
87       BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH |\
88       BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE |\
89       BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY)
90 
91 #define MAX_SECTORS                                         8
92 #define MAX_STR_SIZE                                       2048
93 
94 struct audio_device_to_audio_interface audio_device_to_interface_table[];
95 int audio_device_to_interface_table_len;
96 
97 struct sound_focus_param {
98     uint16_t start_angle[MAX_SECTORS];
99     uint8_t enable[MAX_SECTORS];
100     uint16_t gain_step;
101 };
102 
103 struct source_tracking_param {
104     uint8_t vad[MAX_SECTORS];
105     uint16_t doa_speech;
106     uint16_t doa_noise[3];
107     uint8_t polar_activity[360];
108 };
109 
add_audio_intf_name_to_mixer_ctl(audio_devices_t device,char * mixer_ctl_name,struct audio_device_to_audio_interface * table,int len)110 static int add_audio_intf_name_to_mixer_ctl(audio_devices_t device, char *mixer_ctl_name,
111                                 struct audio_device_to_audio_interface *table, int len)
112 {
113     int ret = 0;
114     int i;
115 
116     if (table == NULL) {
117         ALOGE("%s: table is NULL", __func__);
118 
119         ret = -EINVAL;
120         goto done;
121     }
122 
123     if (mixer_ctl_name == NULL) {
124         ret = -EINVAL;
125         goto done;
126     }
127 
128     for (i=0; i < len; i++) {
129         if (device == table[i].device) {
130              strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
131              strlcat(mixer_ctl_name, table[i].interface_name, MIXER_PATH_MAX_LENGTH);
132              break;
133         }
134     }
135 
136     if (i == len) {
137         ALOGE("%s: Audio Device not found in the table", __func__);
138 
139         ret = -EINVAL;
140     }
141 done:
142     return ret;
143 }
144 
is_stt_supported_snd_device(snd_device_t snd_device)145 static bool is_stt_supported_snd_device(snd_device_t snd_device)
146 {
147     bool ret = false;
148 
149     switch (snd_device) {
150     case SND_DEVICE_IN_HANDSET_DMIC:
151     case SND_DEVICE_IN_HANDSET_DMIC_AEC:
152     case SND_DEVICE_IN_HANDSET_DMIC_NS:
153     case SND_DEVICE_IN_HANDSET_DMIC_AEC_NS:
154     case SND_DEVICE_IN_HANDSET_STEREO_DMIC:
155     case SND_DEVICE_IN_HANDSET_QMIC:
156     case SND_DEVICE_IN_VOICE_DMIC:
157     case SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE:
158     case SND_DEVICE_IN_HEADSET_MIC_FLUENCE:
159     case SND_DEVICE_IN_SPEAKER_DMIC:
160     case SND_DEVICE_IN_SPEAKER_DMIC_AEC:
161     case SND_DEVICE_IN_SPEAKER_DMIC_NS:
162     case SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS:
163     case SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE:
164     case SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE:
165     case SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE:
166     case SND_DEVICE_IN_SPEAKER_QMIC_AEC:
167     case SND_DEVICE_IN_SPEAKER_QMIC_NS:
168     case SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS:
169     case SND_DEVICE_IN_VOICE_SPEAKER_DMIC:
170     case SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE:
171     case SND_DEVICE_IN_VOICE_SPEAKER_QMIC:
172         ret = true;
173         break;
174     default:
175         break;
176     }
177 
178     return ret;
179 }
180 
get_input_audio_device(audio_devices_t device)181 audio_devices_t get_input_audio_device(audio_devices_t device)
182 {
183     audio_devices_t in_device = device;
184 
185     switch (device) {
186     case AUDIO_DEVICE_OUT_EARPIECE:
187     case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
188         in_device = AUDIO_DEVICE_IN_BUILTIN_MIC;
189         break;
190     case AUDIO_DEVICE_OUT_SPEAKER:
191         in_device = AUDIO_DEVICE_IN_BACK_MIC;
192         break;
193     case AUDIO_DEVICE_OUT_WIRED_HEADSET:
194         in_device = AUDIO_DEVICE_IN_WIRED_HEADSET;
195         break;
196     case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET:
197         in_device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET;
198         break;
199     default:
200         break;
201     }
202 
203     return in_device;
204 }
205 
derive_mixer_ctl_from_usecase_intf(struct audio_device * adev,char * mixer_ctl_name)206 static int derive_mixer_ctl_from_usecase_intf(struct audio_device *adev,
207                                               char *mixer_ctl_name) {
208     struct audio_usecase *usecase = NULL;
209     audio_devices_t in_device;
210     int ret = 0;
211 
212     if (mixer_ctl_name == NULL) {
213         ALOGE("%s: mixer_ctl_name is NULL", __func__);
214 
215         ret = -EINVAL;
216         goto done;
217     }
218 
219     if (voice_is_in_call(adev)) {
220         strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
221         strlcat(mixer_ctl_name, "Voice Tx", MIXER_PATH_MAX_LENGTH);
222         usecase = get_usecase_from_list(adev,
223                                         get_usecase_id_from_usecase_type(adev, VOICE_CALL));
224     } else if (voice_extn_compress_voip_is_active(adev)) {
225         strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
226         strlcat(mixer_ctl_name, "Voice Tx", MIXER_PATH_MAX_LENGTH);
227         usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
228     } else {
229         strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH);
230         strlcat(mixer_ctl_name, "Audio Tx", MIXER_PATH_MAX_LENGTH);
231         usecase = get_usecase_from_list(adev, get_usecase_id_from_usecase_type(adev, PCM_CAPTURE));
232     }
233 
234     if (usecase && (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
235         if (is_stt_supported_snd_device(usecase->in_snd_device)) {
236              in_device = get_input_audio_device(usecase->devices);
237              ret = add_audio_intf_name_to_mixer_ctl(in_device, mixer_ctl_name,
238                 audio_device_to_interface_table, audio_device_to_interface_table_len);
239         } else {
240             ALOGE("%s: Sound Focus/Source Tracking not supported on the input sound device (%s)",
241                     __func__, platform_get_snd_device_name(usecase->in_snd_device));
242 
243             ret = -EINVAL;
244         }
245     } else {
246         ALOGE("%s: No use case is active which supports Sound Focus/Source Tracking",
247                __func__);
248 
249         ret = -EINVAL;
250     }
251 
252 done:
253     return ret;
254 }
255 
parse_soundfocus_sourcetracking_keys(struct str_parms * parms)256 static int parse_soundfocus_sourcetracking_keys(struct str_parms *parms)
257 {
258     char *str;
259     char *value = NULL;
260     int val, len;
261     int ret = 0, err;
262     char *kv_pairs = str_parms_to_str(parms);
263 
264     ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs);
265 
266     len = strlen(kv_pairs);
267     value = (char*)calloc(len, sizeof(char));
268     if(value == NULL) {
269         ret = -ENOMEM;
270         ALOGE("%s: failed to allocate memory", __func__);
271 
272         goto done;
273     }
274 
275     err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES,
276                             value, len);
277     if (err >= 0) {
278         str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES);
279         ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES;
280     }
281 
282     err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS,
283                             value, len);
284     if (err >= 0) {
285         str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS);
286         ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS;
287     }
288 
289     err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP,
290                             value, len);
291     if (err >= 0) {
292         str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP);
293         ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP;
294     }
295 
296     err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD,
297                             value, len);
298     if (err >= 0) {
299         str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD);
300         ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD;
301     }
302 
303     err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH,
304                             value, len);
305     if (err >= 0) {
306         str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH);
307         ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH;
308     }
309 
310     err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE,
311                             value, len);
312     if (err >= 0) {
313         str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE);
314         ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE;
315     }
316 
317     err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY,
318                             value, len);
319     if (err >= 0) {
320         str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY);
321         ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY;
322     }
323 
324 done:
325     free(kv_pairs);
326     if(value != NULL)
327         free(value);
328     ALOGV("%s: returning bitmask = %d", __func__, ret);
329 
330     return ret;
331 }
332 
get_soundfocus_sourcetracking_data(struct audio_device * adev,const int bitmask,struct sound_focus_param * sound_focus_data,struct source_tracking_param * source_tracking_data)333 static int get_soundfocus_sourcetracking_data(struct audio_device *adev,
334                                         const int bitmask,
335                                         struct sound_focus_param *sound_focus_data,
336                                         struct source_tracking_param *source_tracking_data)
337 {
338     struct mixer_ctl *ctl;
339     char sound_focus_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Sound Focus";
340     char source_tracking_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Source Tracking";
341     int ret = -EINVAL;
342     int i, count;
343 
344     if (bitmask & BITMASK_AUDIO_PARAMETER_KEYS_SOUND_FOCUS) {
345         /* Derive the mixer control name based on the use case and the audio interface
346          * for the corresponding audio device
347          */
348         ret = derive_mixer_ctl_from_usecase_intf(adev, sound_focus_mixer_ctl_name);
349         if (ret != 0) {
350             ALOGE("%s: Could not get Sound Focus Params", __func__);
351 
352             goto done;
353         } else {
354             ALOGV("%s: Mixer Ctl name: %s", __func__, sound_focus_mixer_ctl_name);
355         }
356 
357         ctl = mixer_get_ctl_by_name(adev->mixer, sound_focus_mixer_ctl_name);
358         if (!ctl) {
359             ALOGE("%s: Could not get ctl for mixer cmd - %s",
360                   __func__, sound_focus_mixer_ctl_name);
361 
362             ret = -EINVAL;
363             goto done;
364         } else {
365             ALOGV("%s: Getting Sound Focus Params", __func__);
366 
367             mixer_ctl_update(ctl);
368             count = mixer_ctl_get_num_values(ctl);
369             if (count != sizeof(struct sound_focus_param)) {
370                 ALOGE("%s: mixer_ctl_get_num_values() invalid sound focus data size", __func__);
371 
372                 ret = -EINVAL;
373                 goto done;
374             }
375 
376             ret = mixer_ctl_get_array(ctl, (void *)sound_focus_data, count);
377             if (ret != 0) {
378                 ALOGE("%s: mixer_ctl_get_array() failed to get Sound Focus Params", __func__);
379 
380                 ret = -EINVAL;
381                 goto done;
382             }
383         }
384     }
385 
386     if (bitmask & BITMASK_AUDIO_PARAMETER_KEYS_SOURCE_TRACKING) {
387         /* Derive the mixer control name based on the use case and the audio interface
388          * for the corresponding audio device
389          */
390         ret = derive_mixer_ctl_from_usecase_intf(adev, source_tracking_mixer_ctl_name);
391         if (ret != 0) {
392             ALOGE("%s: Could not get Source Tracking Params", __func__);
393 
394             goto done;
395         } else {
396             ALOGV("%s: Mixer Ctl name: %s", __func__, source_tracking_mixer_ctl_name);
397         }
398 
399         ctl = mixer_get_ctl_by_name(adev->mixer, source_tracking_mixer_ctl_name);
400         if (!ctl) {
401             ALOGE("%s: Could not get ctl for mixer cmd - %s",
402                   __func__, source_tracking_mixer_ctl_name);
403 
404             ret = -EINVAL;
405             goto done;
406         } else {
407             ALOGV("%s: Getting Source Tracking Params", __func__);
408 
409             mixer_ctl_update(ctl);
410             count = mixer_ctl_get_num_values(ctl);
411             if (count != sizeof(struct source_tracking_param)) {
412                 ALOGE("%s: mixer_ctl_get_num_values() invalid source tracking data size", __func__);
413 
414                 ret = -EINVAL;
415                 goto done;
416             }
417 
418             ret = mixer_ctl_get_array(ctl, (void *)source_tracking_data, count);
419             if (ret != 0) {
420                 ALOGE("%s: mixer_ctl_get_array() failed to get Source Tracking Params", __func__);
421 
422                 ret = -EINVAL;
423                 goto done;
424             }
425         }
426     }
427 
428 done:
429     return ret;
430 }
431 
send_soundfocus_sourcetracking_params(struct str_parms * reply,const int bitmask,const struct sound_focus_param sound_focus_data,const struct source_tracking_param source_tracking_data)432 static void send_soundfocus_sourcetracking_params(struct str_parms *reply,
433                                                 const int bitmask,
434                                                 const struct sound_focus_param sound_focus_data,
435                                                 const struct source_tracking_param source_tracking_data)
436 {
437     int i = 0, len = 0;
438     char value[MAX_STR_SIZE] = "";
439 
440     if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES) {
441         for (i = 0; i < MAX_SECTORS; i++) {
442             if ((i >=4) && (sound_focus_data.start_angle[i] == 0xFFFF))
443                 continue;
444             if (i)
445                 snprintf(value + strlen(value), MAX_STR_SIZE, ",");
446             snprintf(value + strlen(value), MAX_STR_SIZE, "%d", sound_focus_data.start_angle[i]);
447         }
448         str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES, value);
449     }
450 
451     strlcpy(value, "", sizeof(""));
452     if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS) {
453         for (i = 0; i < MAX_SECTORS; i++) {
454             if ((i >=4) && (sound_focus_data.enable[i] == 0xFF))
455                 continue;
456             if (i)
457                 snprintf(value + strlen(value), MAX_STR_SIZE, ",");
458             snprintf(value + strlen(value), MAX_STR_SIZE, "%d", sound_focus_data.enable[i]);
459         }
460         str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS, value);
461     }
462 
463     if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP)
464         str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP, sound_focus_data.gain_step);
465 
466     strlcpy(value, "", sizeof(""));
467     if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD) {
468         for (i = 0; i < MAX_SECTORS; i++) {
469             if ((i >=4) && (source_tracking_data.vad[i] == 0xFF))
470                 continue;
471             if (i)
472                 snprintf(value + strlen(value), MAX_STR_SIZE, ",");
473             snprintf(value + strlen(value), MAX_STR_SIZE, "%d", source_tracking_data.vad[i]);
474         }
475         str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD, value);
476     }
477 
478     if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH)
479         str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH, source_tracking_data.doa_speech);
480 
481     strlcpy(value, "", sizeof(""));
482     if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE) {
483         snprintf(value, MAX_STR_SIZE,
484                      "%d,%d,%d", source_tracking_data.doa_noise[0], source_tracking_data.doa_noise[1], source_tracking_data.doa_noise[2]);
485         str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE, value);
486     }
487 
488     strlcpy(value, "", sizeof(""));
489     if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY) {
490         for (i = 0; i < 360; i++) {
491             if (i)
492                 snprintf(value + strlen(value), MAX_STR_SIZE, ",");
493             snprintf(value + strlen(value), MAX_STR_SIZE, "%d", source_tracking_data.polar_activity[i]);
494         }
495         str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY, value);
496     }
497 }
498 
audio_extn_source_track_get_parameters(struct audio_device * adev,struct str_parms * query,struct str_parms * reply)499 void audio_extn_source_track_get_parameters(struct audio_device *adev,
500                                             struct str_parms *query,
501                                             struct str_parms *reply)
502 {
503     int bitmask = 0, ret = 0;
504     struct sound_focus_param sound_focus_data;
505     struct source_tracking_param source_tracking_data;
506 
507     memset(&sound_focus_data, 0xFF, sizeof(struct sound_focus_param));
508     memset(&source_tracking_data, 0xFF, sizeof(struct source_tracking_param));
509 
510     // Parse the input parameters string for Source Tracking keys
511     bitmask = parse_soundfocus_sourcetracking_keys(query);
512     if (bitmask) {
513         // Get the parameter values from the backend
514         ret = get_soundfocus_sourcetracking_data(adev, bitmask, &sound_focus_data, &source_tracking_data);
515         if (ret == 0) {
516             // Construct the return string with key, value pairs
517             send_soundfocus_sourcetracking_params(reply, bitmask, sound_focus_data, source_tracking_data);
518         }
519     }
520 }
521 
audio_extn_source_track_set_parameters(struct audio_device * adev,struct str_parms * parms)522 void audio_extn_source_track_set_parameters(struct audio_device *adev,
523                                             struct str_parms *parms)
524 {
525     int len, ret, count;;
526     struct mixer_ctl *ctl;
527     char sound_focus_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Sound Focus";
528     char *value = NULL;
529     char *kv_pairs = str_parms_to_str(parms);
530 
531     len = strlen(kv_pairs);
532     value = (char*)calloc(len, sizeof(char));
533     if(value == NULL) {
534         ret = -ENOMEM;
535         ALOGE("%s: failed to allocate memory", __func__);
536 
537         goto done;
538     }
539 
540     // Parse the input parameter string for Source Tracking key, value pairs
541     ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES,
542                             value, len);
543     if (ret >= 0) {
544         char *saveptr, *tok;
545         int i = 0, val;
546         struct sound_focus_param sound_focus_param;
547 
548         memset(&sound_focus_param, 0xFF, sizeof(struct sound_focus_param));
549 
550         str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES);
551         tok = strtok_r(value, ",", &saveptr);
552         while ((i < MAX_SECTORS) && (tok != NULL)) {
553             if (sscanf(tok, "%d", &val) == 1) {
554                 sound_focus_param.start_angle[i++] = (uint16_t)val;
555             }
556             tok = strtok_r(NULL, ",", &saveptr);
557         }
558 
559         ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS,
560                                 value, len);
561         if (ret >= 0) {
562             str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS);
563             tok = strtok_r(value, ",", &saveptr);
564             i = 0;
565             while ((i < MAX_SECTORS) && (tok != NULL)) {
566                 if (sscanf(tok, "%d", &val) == 1) {
567                     sound_focus_param.enable[i++] = (uint8_t)val;
568                 }
569                 tok = strtok_r(NULL, ",", &saveptr);
570             }
571         } else {
572             ALOGE("%s: SoundFocus.enable_sectors key not found", __func__);
573 
574             goto done;
575         }
576 
577         ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP, &val);
578         if (ret >= 0) {
579             str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP);
580             sound_focus_param.gain_step = (uint16_t)val;
581         } else {
582             ALOGE("%s: SoundFocus.gain_step key not found", __func__);
583 
584             goto done;
585         }
586 
587         /* Derive the mixer control name based on the use case and the audio h/w
588          * interface name for the corresponding audio device
589          */
590         ret = derive_mixer_ctl_from_usecase_intf(adev, sound_focus_mixer_ctl_name);
591         if (ret != 0) {
592             ALOGE("%s: Could not set Sound Focus Params", __func__);
593 
594             goto done;
595         } else {
596             ALOGV("%s: Mixer Ctl name: %s", __func__, sound_focus_mixer_ctl_name);
597         }
598 
599         ctl = mixer_get_ctl_by_name(adev->mixer, sound_focus_mixer_ctl_name);
600         if (!ctl) {
601             ALOGE("%s: Could not get ctl for mixer cmd - %s",
602                   __func__, sound_focus_mixer_ctl_name);
603 
604             goto done;
605         } else {
606             ALOGV("%s: Setting Sound Focus Params", __func__);
607 
608             for (i = 0; i < MAX_SECTORS;i++) {
609                 ALOGV("%s: start_angles[%d] = %d", __func__, i, sound_focus_param.start_angle[i]);
610             }
611             for (i = 0; i < MAX_SECTORS;i++) {
612                 ALOGV("%s: enable_sectors[%d] = %d", __func__, i, sound_focus_param.enable[i]);
613             }
614             ALOGV("%s: gain_step = %d", __func__, sound_focus_param.gain_step);
615 
616             mixer_ctl_update(ctl);
617             count = mixer_ctl_get_num_values(ctl);
618             if (count != sizeof(struct sound_focus_param)) {
619                 ALOGE("%s: mixer_ctl_get_num_values() invalid data size", __func__);
620 
621                 goto done;
622             }
623 
624             // Set the parameters on the mixer control derived above
625             ret = mixer_ctl_set_array(ctl, (void *)&sound_focus_param, count);
626             if (ret != 0) {
627                 ALOGE("%s: mixer_ctl_set_array() failed to set Sound Focus Params", __func__);
628 
629                 goto done;
630             }
631        }
632     }
633 
634 done:
635     free(kv_pairs);
636     if(value != NULL)
637         free(value);
638     return;
639 }
640 #endif /* SOURCE_TRACKING_ENABLED end */
641