1 /*
2  * Copyright (c) 2014, The Linux Foundation. All rights reserved.
3  * Not a Contribution.
4  *
5  * Copyright (C) 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #define LOG_TAG "audio_hw_utils"
21 /* #define LOG_NDEBUG 0 */
22 
23 #include <errno.h>
24 #include <cutils/properties.h>
25 #include <cutils/config_utils.h>
26 #include <stdlib.h>
27 #include <dlfcn.h>
28 #include <cutils/str_parms.h>
29 #include <cutils/log.h>
30 #include <cutils/misc.h>
31 
32 #include "audio_hw.h"
33 #include "platform.h"
34 #include "platform_api.h"
35 #include "audio_extn.h"
36 
37 #define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
38 
39 #define OUTPUTS_TAG "outputs"
40 
41 #define DYNAMIC_VALUE_TAG "dynamic"
42 #define FLAGS_TAG "flags"
43 #define FORMATS_TAG "formats"
44 #define SAMPLING_RATES_TAG "sampling_rates"
45 #define BIT_WIDTH_TAG "bit_width"
46 #define APP_TYPE_TAG "app_type"
47 
48 #define STRING_TO_ENUM(string) { #string, string }
49 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
50 
51 struct string_to_enum {
52     const char *name;
53     uint32_t value;
54 };
55 
56 const struct string_to_enum s_flag_name_to_enum_table[] = {
57     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
58     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
59     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
60     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
61     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
62     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
63 #ifdef INCALL_MUSIC_ENABLED
64     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
65 #endif
66 #ifdef COMPRESS_VOIP_ENABLED
67     STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
68 #endif
69 };
70 
71 const struct string_to_enum s_format_name_to_enum_table[] = {
72     STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
73     STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
74     STRING_TO_ENUM(AUDIO_FORMAT_MP3),
75     STRING_TO_ENUM(AUDIO_FORMAT_AAC),
76     STRING_TO_ENUM(AUDIO_FORMAT_VORBIS),
77     STRING_TO_ENUM(AUDIO_FORMAT_AMR_NB),
78     STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB),
79     STRING_TO_ENUM(AUDIO_FORMAT_AC3),
80     STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
81 #ifdef FORMATS_ENABLED
82     STRING_TO_ENUM(AUDIO_FORMAT_DTS),
83     STRING_TO_ENUM(AUDIO_FORMAT_DTS_LBR),
84     STRING_TO_ENUM(AUDIO_FORMAT_WMA),
85     STRING_TO_ENUM(AUDIO_FORMAT_WMA_PRO),
86     STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADIF),
87     STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB_PLUS),
88     STRING_TO_ENUM(AUDIO_FORMAT_EVRC),
89     STRING_TO_ENUM(AUDIO_FORMAT_EVRCB),
90     STRING_TO_ENUM(AUDIO_FORMAT_EVRCWB),
91     STRING_TO_ENUM(AUDIO_FORMAT_QCELP),
92     STRING_TO_ENUM(AUDIO_FORMAT_MP2),
93     STRING_TO_ENUM(AUDIO_FORMAT_EVRCNW),
94     STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT_OFFLOAD),
95     STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_OFFLOAD),
96     STRING_TO_ENUM(AUDIO_FORMAT_FLAC),
97     STRING_TO_ENUM(AUDIO_FORMAT_ALAC),
98     STRING_TO_ENUM(AUDIO_FORMAT_APE),
99 #endif
100 };
101 
string_to_enum(const struct string_to_enum * table,size_t size,const char * name)102 static uint32_t string_to_enum(const struct string_to_enum *table, size_t size,
103                                const char *name)
104 {
105     size_t i;
106     for (i = 0; i < size; i++) {
107         if (strcmp(table[i].name, name) == 0) {
108             ALOGV("%s found %s", __func__, table[i].name);
109             return table[i].value;
110         }
111     }
112     return 0;
113 }
114 
parse_flag_names(char * name)115 static audio_output_flags_t parse_flag_names(char *name)
116 {
117     uint32_t flag = 0;
118     char *flag_name = strtok(name, "|");
119     while (flag_name != NULL) {
120         if (strlen(flag_name) != 0) {
121             flag |= string_to_enum(s_flag_name_to_enum_table,
122                                ARRAY_SIZE(s_flag_name_to_enum_table),
123                                flag_name);
124         }
125         flag_name = strtok(NULL, "|");
126     }
127 
128     ALOGV("parse_flag_names: flag - %d", flag);
129     return (audio_output_flags_t)flag;
130 }
131 
parse_format_names(char * name,struct streams_output_cfg * so_info)132 static void parse_format_names(char *name, struct streams_output_cfg *so_info)
133 {
134     struct stream_format *sf_info = NULL;
135     char *str = strtok(name, "|");
136 
137     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0)
138         return;
139 
140     list_init(&so_info->format_list);
141     while (str != NULL) {
142         audio_format_t format = (audio_format_t)string_to_enum(s_format_name_to_enum_table,
143                                               ARRAY_SIZE(s_format_name_to_enum_table), str);
144         ALOGV("%s: format - %d", __func__, format);
145         if (format != 0) {
146             sf_info = (struct stream_format *)calloc(1, sizeof(struct stream_format));
147             if (sf_info == NULL)
148                 break; /* return whatever was parsed */
149 
150             sf_info->format = format;
151             list_add_tail(&so_info->format_list, &sf_info->list);
152         }
153         str = strtok(NULL, "|");
154     }
155 }
156 
parse_sample_rate_names(char * name,struct streams_output_cfg * so_info)157 static void parse_sample_rate_names(char *name, struct streams_output_cfg *so_info)
158 {
159     struct stream_sample_rate *ss_info = NULL;
160     uint32_t sample_rate = 48000;
161     char *str = strtok(name, "|");
162 
163     if (str != NULL && 0 == strcmp(str, DYNAMIC_VALUE_TAG))
164         return;
165 
166     list_init(&so_info->sample_rate_list);
167     while (str != NULL) {
168         sample_rate = (uint32_t)strtol(str, (char **)NULL, 10);
169         ALOGV("%s: sample_rate - %d", __func__, sample_rate);
170         if (0 != sample_rate) {
171             ss_info = (struct stream_sample_rate *)calloc(1, sizeof(struct stream_sample_rate));
172             if (ss_info == NULL)
173                 break; /* return whatever was parsed */
174 
175             ss_info->sample_rate = sample_rate;
176             list_add_tail(&so_info->sample_rate_list, &ss_info->list);
177         }
178         str = strtok(NULL, "|");
179     }
180 }
181 
parse_bit_width_names(char * name)182 static int parse_bit_width_names(char *name)
183 {
184     int bit_width = 16;
185     char *str = strtok(name, "|");
186 
187     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
188         bit_width = (int)strtol(str, (char **)NULL, 10);
189 
190     ALOGV("%s: bit_width - %d", __func__, bit_width);
191     return bit_width;
192 }
193 
parse_app_type_names(void * platform,char * name)194 static int parse_app_type_names(void *platform, char *name)
195 {
196     int app_type = platform_get_default_app_type(platform);
197     char *str = strtok(name, "|");
198 
199     if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
200         app_type = (int)strtol(str, (char **)NULL, 10);
201 
202     ALOGV("%s: app_type - %d", __func__, app_type);
203     return app_type;
204 }
205 
update_streams_output_cfg_list(cnode * root,void * platform,struct listnode * streams_output_cfg_list)206 static void update_streams_output_cfg_list(cnode *root, void *platform,
207                                            struct listnode *streams_output_cfg_list)
208 {
209     cnode *node = root->first_child;
210     struct streams_output_cfg *so_info;
211 
212     ALOGV("%s", __func__);
213     so_info = (struct streams_output_cfg *)calloc(1, sizeof(struct streams_output_cfg));
214 
215     if (!so_info) {
216         ALOGE("failed to allocate mem for so_info list element");
217         return;
218     }
219 
220     while (node) {
221         if (strcmp(node->name, FLAGS_TAG) == 0) {
222             so_info->flags = parse_flag_names((char *)node->value);
223         } else if (strcmp(node->name, FORMATS_TAG) == 0) {
224             parse_format_names((char *)node->value, so_info);
225         } else if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
226             so_info->app_type_cfg.sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
227             parse_sample_rate_names((char *)node->value, so_info);
228         } else if (strcmp(node->name, BIT_WIDTH_TAG) == 0) {
229             so_info->app_type_cfg.bit_width = parse_bit_width_names((char *)node->value);
230         } else if (strcmp(node->name, APP_TYPE_TAG) == 0) {
231             so_info->app_type_cfg.app_type = parse_app_type_names(platform, (char *)node->value);
232         }
233         node = node->next;
234     }
235     list_add_tail(streams_output_cfg_list, &so_info->list);
236 }
237 
load_output(cnode * root,void * platform,struct listnode * streams_output_cfg_list)238 static void load_output(cnode *root, void *platform,
239                         struct listnode *streams_output_cfg_list)
240 {
241     cnode *node = config_find(root, OUTPUTS_TAG);
242     if (node == NULL) {
243         ALOGE("%s: could not load output, node is NULL", __func__);
244         return;
245     }
246 
247     node = node->first_child;
248     while (node) {
249         ALOGV("%s: loading output %s", __func__, node->name);
250         update_streams_output_cfg_list(node, platform, streams_output_cfg_list);
251         node = node->next;
252     }
253 }
254 
send_app_type_cfg(void * platform,struct mixer * mixer,struct listnode * streams_output_cfg_list)255 static void send_app_type_cfg(void *platform, struct mixer *mixer,
256                               struct listnode *streams_output_cfg_list)
257 {
258     int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {-1};
259     int length = 0, i, num_app_types = 0;
260     struct listnode *node;
261     bool update;
262     struct mixer_ctl *ctl = NULL;
263     const char *mixer_ctl_name = "App Type Config";
264     struct streams_output_cfg *so_info;
265 
266     if (!mixer) {
267         ALOGE("%s: mixer is null",__func__);
268         return;
269     }
270     ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
271     if (!ctl) {
272         ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name);
273         return;
274     }
275     if (streams_output_cfg_list == NULL) {
276         app_type_cfg[length++] = 1;
277         app_type_cfg[length++] = platform_get_default_app_type(platform);
278         app_type_cfg[length++] = 48000;
279         app_type_cfg[length++] = 16;
280         mixer_ctl_set_array(ctl, app_type_cfg, length);
281         return;
282     }
283 
284     app_type_cfg[length++] = num_app_types;
285     list_for_each(node, streams_output_cfg_list) {
286         so_info = node_to_item(node, struct streams_output_cfg, list);
287         update = true;
288         for (i=0; i<length; i=i+3) {
289             if (app_type_cfg[i+1] == -1)
290                 break;
291             else if (app_type_cfg[i+1] == so_info->app_type_cfg.app_type) {
292                 update = false;
293                 break;
294             }
295         }
296         if (update && ((length + 3) <= MAX_LENGTH_MIXER_CONTROL_IN_INT)) {
297             num_app_types += 1 ;
298             app_type_cfg[length++] = so_info->app_type_cfg.app_type;
299             app_type_cfg[length++] = so_info->app_type_cfg.sample_rate;
300             app_type_cfg[length++] = so_info->app_type_cfg.bit_width;
301         }
302     }
303     ALOGV("%s: num_app_types: %d", __func__, num_app_types);
304     if (num_app_types) {
305         app_type_cfg[0] = num_app_types;
306         mixer_ctl_set_array(ctl, app_type_cfg, length);
307     }
308 }
309 
audio_extn_utils_update_streams_output_cfg_list(void * platform,struct mixer * mixer,struct listnode * streams_output_cfg_list)310 void audio_extn_utils_update_streams_output_cfg_list(void *platform,
311                                        struct mixer *mixer,
312                                        struct listnode *streams_output_cfg_list)
313 {
314     cnode *root;
315     char *data;
316 
317     ALOGV("%s", __func__);
318     list_init(streams_output_cfg_list);
319     data = (char *)load_file(AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE, NULL);
320     if (data == NULL) {
321         send_app_type_cfg(platform, mixer, NULL);
322         ALOGE("%s: could not load output policy config file", __func__);
323         return;
324     }
325 
326     root = config_node("", "");
327     if (root == NULL) {
328         ALOGE("cfg_list, NULL config root");
329         return;
330     }
331 
332     config_load(root, data);
333     load_output(root, platform, streams_output_cfg_list);
334 
335     send_app_type_cfg(platform, mixer, streams_output_cfg_list);
336 }
337 
audio_extn_utils_dump_streams_output_cfg_list(struct listnode * streams_output_cfg_list)338 void audio_extn_utils_dump_streams_output_cfg_list(
339                                        struct listnode *streams_output_cfg_list)
340 {
341     int i=0;
342     struct listnode *node_i, *node_j;
343     struct streams_output_cfg *so_info;
344     struct stream_format *sf_info;
345     struct stream_sample_rate *ss_info;
346     ALOGV("%s", __func__);
347     list_for_each(node_i, streams_output_cfg_list) {
348         so_info = node_to_item(node_i, struct streams_output_cfg, list);
349         ALOGV("%s: flags-%d, output_sample_rate-%d, output_bit_width-%d, app_type-%d",
350                __func__, so_info->flags, so_info->app_type_cfg.sample_rate,
351                so_info->app_type_cfg.bit_width, so_info->app_type_cfg.app_type);
352         list_for_each(node_j, &so_info->format_list) {
353             sf_info = node_to_item(node_j, struct stream_format, list);
354             ALOGV("format-%x", sf_info->format);
355         }
356         list_for_each(node_j, &so_info->sample_rate_list) {
357             ss_info = node_to_item(node_j, struct stream_sample_rate, list);
358             ALOGV("sample rate-%d", ss_info->sample_rate);
359         }
360     }
361 }
362 
audio_extn_utils_release_streams_output_cfg_list(struct listnode * streams_output_cfg_list)363 void audio_extn_utils_release_streams_output_cfg_list(
364                                        struct listnode *streams_output_cfg_list)
365 {
366     struct listnode *node_i, *node_j;
367     struct streams_output_cfg *so_info;
368     struct stream_format *sf_info;
369 
370     ALOGV("%s", __func__);
371     while (!list_empty(streams_output_cfg_list)) {
372         node_i = list_head(streams_output_cfg_list);
373         so_info = node_to_item(node_i, struct streams_output_cfg, list);
374         while (!list_empty(&so_info->format_list)) {
375             node_j = list_head(&so_info->format_list);
376             list_remove(node_j);
377             free(node_to_item(node_j, struct stream_format, list));
378         }
379         while (!list_empty(&so_info->sample_rate_list)) {
380             node_j = list_head(&so_info->sample_rate_list);
381             list_remove(node_j);
382             free(node_to_item(node_j, struct stream_sample_rate, list));
383         }
384         list_remove(node_i);
385         free(node_to_item(node_i, struct streams_output_cfg, list));
386     }
387 }
388 
set_output_cfg(struct streams_output_cfg * so_info,struct stream_app_type_cfg * app_type_cfg,uint32_t sample_rate,uint32_t bit_width)389 static bool set_output_cfg(struct streams_output_cfg *so_info,
390                            struct stream_app_type_cfg *app_type_cfg,
391                            uint32_t sample_rate, uint32_t bit_width)
392  {
393     struct listnode *node_i;
394     struct stream_sample_rate *ss_info;
395     list_for_each(node_i, &so_info->sample_rate_list) {
396         ss_info = node_to_item(node_i, struct stream_sample_rate, list);
397         if ((sample_rate <= ss_info->sample_rate) &&
398             (bit_width == so_info->app_type_cfg.bit_width)) {
399             app_type_cfg->app_type = so_info->app_type_cfg.app_type;
400             app_type_cfg->sample_rate = ss_info->sample_rate;
401             app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
402             ALOGV("%s app_type_cfg->app_type %d, app_type_cfg->sample_rate %d, app_type_cfg->bit_width %d",
403                    __func__, app_type_cfg->app_type, app_type_cfg->sample_rate, app_type_cfg->bit_width);
404             return true;
405         }
406     }
407     /*
408      * Reiterate through the list assuming dafault sample rate.
409      * Handles scenario where input sample rate is higher
410      * than all sample rates in list for the input bit width.
411      */
412     sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
413     list_for_each(node_i, &so_info->sample_rate_list) {
414         ss_info = node_to_item(node_i, struct stream_sample_rate, list);
415         if ((sample_rate <= ss_info->sample_rate) &&
416             (bit_width == so_info->app_type_cfg.bit_width)) {
417             app_type_cfg->app_type = so_info->app_type_cfg.app_type;
418             app_type_cfg->sample_rate = sample_rate;
419             app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
420             ALOGV("%s Assuming default sample rate. app_type_cfg->app_type %d, app_type_cfg->sample_rate %d, app_type_cfg->bit_width %d",
421                    __func__, app_type_cfg->app_type, app_type_cfg->sample_rate, app_type_cfg->bit_width);
422             return true;
423         }
424     }
425     return false;
426 }
427 
audio_extn_utils_update_stream_app_type_cfg(void * platform,struct listnode * streams_output_cfg_list,audio_devices_t devices,audio_output_flags_t flags,audio_format_t format,uint32_t sample_rate,uint32_t bit_width,struct stream_app_type_cfg * app_type_cfg)428 void audio_extn_utils_update_stream_app_type_cfg(void *platform,
429                                   struct listnode *streams_output_cfg_list,
430                                   audio_devices_t devices,
431                                   audio_output_flags_t flags,
432                                   audio_format_t format,
433                                   uint32_t sample_rate,
434                                   uint32_t bit_width,
435                                   struct stream_app_type_cfg *app_type_cfg)
436 {
437     struct listnode *node_i, *node_j, *node_k;
438     struct streams_output_cfg *so_info;
439     struct stream_format *sf_info;
440     struct stream_sample_rate *ss_info;
441 
442     if ((24 == bit_width) &&
443         (devices & AUDIO_DEVICE_OUT_SPEAKER)) {
444         int32_t bw = platform_get_snd_device_bit_width(SND_DEVICE_OUT_SPEAKER);
445         if (-ENOSYS != bw)
446             bit_width = (uint32_t)bw;
447         sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
448         ALOGI("%s Allowing 24-bit playback on speaker ONLY at default sampling rate", __func__);
449     }
450 
451     ALOGV("%s: flags: %x, format: %x sample_rate %d",
452            __func__, flags, format, sample_rate);
453     list_for_each(node_i, streams_output_cfg_list) {
454         so_info = node_to_item(node_i, struct streams_output_cfg, list);
455         if (so_info->flags == flags) {
456             list_for_each(node_j, &so_info->format_list) {
457                 sf_info = node_to_item(node_j, struct stream_format, list);
458                 if (sf_info->format == format) {
459                     if (set_output_cfg(so_info, app_type_cfg, sample_rate, bit_width))
460                         return;
461                 }
462             }
463         }
464     }
465     list_for_each(node_i, streams_output_cfg_list) {
466         so_info = node_to_item(node_i, struct streams_output_cfg, list);
467         if (so_info->flags == AUDIO_OUTPUT_FLAG_PRIMARY) {
468             ALOGV("Compatible output profile not found.");
469             app_type_cfg->app_type = so_info->app_type_cfg.app_type;
470             app_type_cfg->sample_rate = so_info->app_type_cfg.sample_rate;
471             app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
472             ALOGV("%s Default to primary output: App type: %d sample_rate %d",
473                   __func__, so_info->app_type_cfg.app_type, app_type_cfg->sample_rate);
474             return;
475         }
476     }
477     ALOGW("%s: App type could not be selected. Falling back to default", __func__);
478     app_type_cfg->app_type = platform_get_default_app_type(platform);
479     app_type_cfg->sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
480     app_type_cfg->bit_width = 16;
481 }
482 
audio_extn_utils_send_app_type_cfg(struct audio_usecase * usecase)483 int audio_extn_utils_send_app_type_cfg(struct audio_usecase *usecase)
484 {
485     char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
486     int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc;
487     struct stream_out *out;
488     struct audio_device *adev;
489     struct mixer_ctl *ctl;
490     int pcm_device_id, acdb_dev_id, snd_device = usecase->out_snd_device;
491     int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
492 
493     ALOGV("%s", __func__);
494 
495     if (usecase->type != PCM_PLAYBACK) {
496         ALOGV("%s: not a playback path, no need to cfg app type", __func__);
497         rc = 0;
498         goto exit_send_app_type_cfg;
499     }
500     if ((usecase->id != USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) &&
501         (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY) &&
502         (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
503         (usecase->id != USECASE_AUDIO_PLAYBACK_OFFLOAD)) {
504         ALOGV("%s: a playback path where app type cfg is not required", __func__);
505         rc = 0;
506         goto exit_send_app_type_cfg;
507     }
508     out = usecase->stream.out;
509     adev = out->dev;
510 
511     snd_device = usecase->out_snd_device;
512 
513     pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
514 
515     snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
516              "Audio Stream %d App Type Cfg", pcm_device_id);
517 
518     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
519     if (!ctl) {
520         ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
521               mixer_ctl_name);
522         rc = -EINVAL;
523         goto exit_send_app_type_cfg;
524     }
525     snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
526                  audio_extn_get_spkr_prot_snd_device(snd_device) : snd_device;
527     acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
528     if (acdb_dev_id < 0) {
529         ALOGE("%s: Couldn't get the acdb dev id", __func__);
530         rc = -EINVAL;
531         goto exit_send_app_type_cfg;
532     }
533 
534     if ((24 == usecase->stream.out->bit_width) &&
535         (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
536         sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
537     } else {
538         sample_rate = out->app_type_cfg.sample_rate;
539     }
540 
541     app_type_cfg[len++] = out->app_type_cfg.app_type;
542     app_type_cfg[len++] = acdb_dev_id;
543     app_type_cfg[len++] = sample_rate;
544 
545     mixer_ctl_set_array(ctl, app_type_cfg, len);
546     ALOGI("%s app_type %d, acdb_dev_id %d, sample_rate %d",
547            __func__, out->app_type_cfg.app_type, acdb_dev_id, sample_rate);
548     rc = 0;
549 exit_send_app_type_cfg:
550     return rc;
551 }
552 
read_line_from_file(const char * path,char * buf,size_t count)553 int read_line_from_file(const char *path, char *buf, size_t count)
554 {
555     char * fgets_ret;
556     FILE * fd;
557     int rv;
558 
559     fd = fopen(path, "r");
560     if (fd == NULL)
561         return -1;
562 
563     fgets_ret = fgets(buf, (int)count, fd);
564     if (NULL != fgets_ret) {
565         rv = (int)strlen(buf);
566     } else {
567         rv = ferror(fd);
568     }
569     fclose(fd);
570 
571    return rv;
572 }
573 
audio_extn_utils_send_audio_calibration(struct audio_device * adev,struct audio_usecase * usecase)574 void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
575                                              struct audio_usecase *usecase)
576 {
577     int type = usecase->type;
578 
579     if (type == PCM_PLAYBACK) {
580         struct stream_out *out = usecase->stream.out;
581         int snd_device = usecase->out_snd_device;
582         snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
583                      audio_extn_get_spkr_prot_snd_device(snd_device) : snd_device;
584         platform_send_audio_calibration(adev->platform, usecase,
585                                         out->app_type_cfg.app_type,
586                                         out->app_type_cfg.sample_rate);
587     }
588     if ((type == PCM_HFP_CALL) || (type == PCM_CAPTURE)) {
589         /* when app type is default. the sample rate is not used to send cal */
590         platform_send_audio_calibration(adev->platform, usecase,
591                                         platform_get_default_app_type(adev->platform),
592                                         48000);
593     }
594 }
595 
596