1 /*
2  * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
3  * Not a Contribution.
4  *
5  * Copyright (C) 2013 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_extn"
21 /*#define LOG_NDEBUG 0*/
22 #define LOG_NDDEBUG 0
23 
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <dlfcn.h>
27 #include <cutils/properties.h>
28 #include <cutils/log.h>
29 
30 #include "audio_hw.h"
31 #include "audio_extn.h"
32 #include "platform.h"
33 #include "platform_api.h"
34 
35 #include "sound/compress_params.h"
36 
37 #define MAX_SLEEP_RETRY 100
38 #define WIFI_INIT_WAIT_SLEEP 50
39 
40 struct audio_extn_module {
41     bool anc_enabled;
42     bool aanc_enabled;
43     bool custom_stereo_enabled;
44     uint32_t proxy_channel_num;
45 };
46 
47 static struct audio_extn_module aextnmod = {
48     .anc_enabled = 0,
49     .aanc_enabled = 0,
50     .custom_stereo_enabled = 0,
51     .proxy_channel_num = 2,
52 };
53 
54 #define AUDIO_PARAMETER_KEY_ANC        "anc_enabled"
55 #define AUDIO_PARAMETER_KEY_WFD        "wfd_channel_cap"
56 #define AUDIO_PARAMETER_CAN_OPEN_PROXY "can_open_proxy"
57 #define AUDIO_PARAMETER_CUSTOM_STEREO  "stereo_as_dual_mono"
58 /* Query offload playback instances count */
59 #define AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE "offload_num_active"
60 #define AUDIO_PARAMETER_KEY_ASPHERE_ENABLE   "asphere_enable"
61 #define AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH "asphere_strength"
62 
63 #ifndef FM_POWER_OPT
64 #define audio_extn_fm_set_parameters(adev, parms) (0)
65 #else
66 void audio_extn_fm_set_parameters(struct audio_device *adev,
67                                    struct str_parms *parms);
68 #endif
69 #ifndef HFP_ENABLED
70 #define audio_extn_hfp_set_parameters(adev, parms) (0)
71 #else
72 void audio_extn_hfp_set_parameters(struct audio_device *adev,
73                                            struct str_parms *parms);
74 #endif
75 
76 #ifndef SOURCE_TRACKING_ENABLED
77 #define audio_extn_source_track_set_parameters(adev, parms) (0)
78 #define audio_extn_source_track_get_parameters(adev, query, reply) (0)
79 #else
80 void audio_extn_source_track_set_parameters(struct audio_device *adev,
81                                             struct str_parms *parms);
82 void audio_extn_source_track_get_parameters(struct audio_device *adev,
83                                             struct str_parms *query,
84                                             struct str_parms *reply);
85 #endif
86 
87 #ifndef CUSTOM_STEREO_ENABLED
88 #define audio_extn_customstereo_set_parameters(adev, parms)         (0)
89 #else
audio_extn_customstereo_set_parameters(struct audio_device * adev,struct str_parms * parms)90 void audio_extn_customstereo_set_parameters(struct audio_device *adev,
91                                            struct str_parms *parms)
92 {
93     int ret = 0;
94     char value[32]={0};
95     bool custom_stereo_state = false;
96     const char *mixer_ctl_name = "Set Custom Stereo OnOff";
97     struct mixer_ctl *ctl;
98 
99     ALOGV("%s", __func__);
100     ret = str_parms_get_str(parms, AUDIO_PARAMETER_CUSTOM_STEREO, value,
101                             sizeof(value));
102     if (ret >= 0) {
103         if (!strncmp("true", value, sizeof("true")) || atoi(value))
104             custom_stereo_state = true;
105 
106         if (custom_stereo_state == aextnmod.custom_stereo_enabled)
107             return;
108 
109         ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
110         if (!ctl) {
111             ALOGE("%s: Could not get ctl for mixer cmd - %s",
112                   __func__, mixer_ctl_name);
113             return;
114         }
115         if (mixer_ctl_set_value(ctl, 0, custom_stereo_state) < 0) {
116             ALOGE("%s: Could not set custom stereo state %d",
117                   __func__, custom_stereo_state);
118             return;
119         }
120         aextnmod.custom_stereo_enabled = custom_stereo_state;
121         ALOGV("%s: Setting custom stereo state success", __func__);
122     }
123 }
124 #endif /* CUSTOM_STEREO_ENABLED */
125 
126 #ifndef ANC_HEADSET_ENABLED
127 #define audio_extn_set_anc_parameters(adev, parms)       (0)
128 #else
audio_extn_get_anc_enabled(void)129 bool audio_extn_get_anc_enabled(void)
130 {
131     ALOGD("%s: anc_enabled:%d", __func__, aextnmod.anc_enabled);
132     return (aextnmod.anc_enabled ? true: false);
133 }
134 
audio_extn_should_use_handset_anc(int in_channels)135 bool audio_extn_should_use_handset_anc(int in_channels)
136 {
137     char prop_aanc[PROPERTY_VALUE_MAX] = "false";
138 
139     property_get("persist.aanc.enable", prop_aanc, "0");
140     if (!strncmp("true", prop_aanc, 4)) {
141         ALOGD("%s: AANC enabled in the property", __func__);
142         aextnmod.aanc_enabled = 1;
143     }
144 
145     return (aextnmod.aanc_enabled && aextnmod.anc_enabled
146             && (in_channels == 1));
147 }
148 
audio_extn_should_use_fb_anc(void)149 bool audio_extn_should_use_fb_anc(void)
150 {
151   char prop_anc[PROPERTY_VALUE_MAX] = "feedforward";
152 
153   property_get("persist.headset.anc.type", prop_anc, "0");
154   if (!strncmp("feedback", prop_anc, sizeof("feedback"))) {
155     ALOGD("%s: FB ANC headset type enabled\n", __func__);
156     return true;
157   }
158   return false;
159 }
160 
audio_extn_set_anc_parameters(struct audio_device * adev,struct str_parms * parms)161 void audio_extn_set_anc_parameters(struct audio_device *adev,
162                                    struct str_parms *parms)
163 {
164     int ret;
165     char value[32] ={0};
166     struct listnode *node;
167     struct audio_usecase *usecase;
168 
169     ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_ANC, value,
170                             sizeof(value));
171     if (ret >= 0) {
172         if (strcmp(value, "true") == 0)
173             aextnmod.anc_enabled = true;
174         else
175             aextnmod.anc_enabled = false;
176 
177         list_for_each(node, &adev->usecase_list) {
178             usecase = node_to_item(node, struct audio_usecase, list);
179             if (usecase->type == PCM_PLAYBACK) {
180                 if (usecase->stream.out->devices == \
181                     AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
182                     usecase->stream.out->devices ==  \
183                     AUDIO_DEVICE_OUT_WIRED_HEADSET) {
184                         select_devices(adev, usecase->id);
185                         ALOGV("%s: switching device", __func__);
186                         break;
187                 }
188             }
189         }
190     }
191 
192     ALOGD("%s: anc_enabled:%d", __func__, aextnmod.anc_enabled);
193 }
194 #endif /* ANC_HEADSET_ENABLED */
195 
196 #ifndef FLUENCE_ENABLED
197 #define audio_extn_set_fluence_parameters(adev, parms) (0)
198 #define audio_extn_get_fluence_parameters(adev, query, reply) (0)
199 #else
audio_extn_set_fluence_parameters(struct audio_device * adev,struct str_parms * parms)200 void audio_extn_set_fluence_parameters(struct audio_device *adev,
201                                             struct str_parms *parms)
202 {
203     int ret = 0, err;
204     char value[32];
205     struct listnode *node;
206     struct audio_usecase *usecase;
207 
208     err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_FLUENCE,
209                                  value, sizeof(value));
210     ALOGV_IF(err >= 0, "%s: Set Fluence Type to %s", __func__, value);
211     if (err >= 0) {
212         ret = platform_set_fluence_type(adev->platform, value);
213         if (ret != 0) {
214             ALOGE("platform_set_fluence_type returned error: %d", ret);
215         } else {
216             /*
217              *If the fluence is manually set/reset, devices
218              *need to get updated for all the usecases
219              *i.e. audio and voice.
220              */
221              list_for_each(node, &adev->usecase_list) {
222                  usecase = node_to_item(node, struct audio_usecase, list);
223                  select_devices(adev, usecase->id);
224              }
225         }
226     }
227 }
228 
audio_extn_get_fluence_parameters(const struct audio_device * adev,struct str_parms * query,struct str_parms * reply)229 int audio_extn_get_fluence_parameters(const struct audio_device *adev,
230                        struct str_parms *query, struct str_parms *reply)
231 {
232     int ret = 0, err;
233     char value[256] = {0};
234 
235     err = str_parms_get_str(query, AUDIO_PARAMETER_KEY_FLUENCE, value,
236                                                           sizeof(value));
237     if (err >= 0) {
238         ret = platform_get_fluence_type(adev->platform, value, sizeof(value));
239         if (ret >= 0) {
240             ALOGV("%s: Fluence Type is %s", __func__, value);
241             str_parms_add_str(reply, AUDIO_PARAMETER_KEY_FLUENCE, value);
242         } else
243             goto done;
244     }
245 done:
246     return ret;
247 }
248 #endif /* FLUENCE_ENABLED */
249 
250 #ifndef AFE_PROXY_ENABLED
251 #define audio_extn_set_afe_proxy_parameters(adev, parms)  (0)
252 #define audio_extn_get_afe_proxy_parameters(query, reply) (0)
253 #else
254 /* Front left channel. */
255 #define PCM_CHANNEL_FL    1
256 
257 /* Front right channel. */
258 #define PCM_CHANNEL_FR    2
259 
260 /* Front center channel. */
261 #define PCM_CHANNEL_FC    3
262 
263 /* Left surround channel.*/
264 #define PCM_CHANNEL_LS   4
265 
266 /* Right surround channel.*/
267 #define PCM_CHANNEL_RS   5
268 
269 /* Low frequency effect channel. */
270 #define PCM_CHANNEL_LFE  6
271 
272 /* Left back channel; Rear left channel. */
273 #define PCM_CHANNEL_LB   8
274 
275 /* Right back channel; Rear right channel. */
276 #define PCM_CHANNEL_RB   9
277 
afe_proxy_set_channel_mapping(struct audio_device * adev,int channel_count)278 static int32_t afe_proxy_set_channel_mapping(struct audio_device *adev,
279                                                      int channel_count)
280 {
281     struct mixer_ctl *ctl;
282     const char *mixer_ctl_name = "Playback Channel Map";
283     int set_values[8] = {0};
284     int ret;
285     ALOGV("%s channel_count:%d",__func__, channel_count);
286 
287     switch (channel_count) {
288     case 2:
289         set_values[0] = PCM_CHANNEL_FL;
290         set_values[1] = PCM_CHANNEL_FR;
291         break;
292     case 6:
293         set_values[0] = PCM_CHANNEL_FL;
294         set_values[1] = PCM_CHANNEL_FR;
295         set_values[2] = PCM_CHANNEL_FC;
296         set_values[3] = PCM_CHANNEL_LFE;
297         set_values[4] = PCM_CHANNEL_LS;
298         set_values[5] = PCM_CHANNEL_RS;
299         break;
300     case 8:
301         set_values[0] = PCM_CHANNEL_FL;
302         set_values[1] = PCM_CHANNEL_FR;
303         set_values[2] = PCM_CHANNEL_FC;
304         set_values[3] = PCM_CHANNEL_LFE;
305         set_values[4] = PCM_CHANNEL_LS;
306         set_values[5] = PCM_CHANNEL_RS;
307         set_values[6] = PCM_CHANNEL_LB;
308         set_values[7] = PCM_CHANNEL_RB;
309         break;
310     default:
311         ALOGE("unsupported channels(%d) for setting channel map",
312                                                     channel_count);
313         return -EINVAL;
314     }
315 
316     ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
317     if (!ctl) {
318         ALOGE("%s: Could not get ctl for mixer cmd - %s",
319               __func__, mixer_ctl_name);
320         return -EINVAL;
321     }
322     ALOGV("AFE: set mapping(%d %d %d %d %d %d %d %d) for channel:%d",
323         set_values[0], set_values[1], set_values[2], set_values[3], set_values[4],
324         set_values[5], set_values[6], set_values[7], channel_count);
325     ret = mixer_ctl_set_array(ctl, set_values, channel_count);
326     return ret;
327 }
328 
audio_extn_set_afe_proxy_channel_mixer(struct audio_device * adev,int channel_count)329 int32_t audio_extn_set_afe_proxy_channel_mixer(struct audio_device *adev,
330                                     int channel_count)
331 {
332     int32_t ret = 0;
333     const char *channel_cnt_str = NULL;
334     struct mixer_ctl *ctl = NULL;
335     const char *mixer_ctl_name = "PROXY_RX Channels";
336 
337     ALOGD("%s: entry", __func__);
338     /* use the existing channel count set by hardware params to
339     configure the back end for stereo as usb/a2dp would be
340     stereo by default */
341     ALOGD("%s: channels = %d", __func__, channel_count);
342     switch (channel_count) {
343     case 8: channel_cnt_str = "Eight"; break;
344     case 7: channel_cnt_str = "Seven"; break;
345     case 6: channel_cnt_str = "Six"; break;
346     case 5: channel_cnt_str = "Five"; break;
347     case 4: channel_cnt_str = "Four"; break;
348     case 3: channel_cnt_str = "Three"; break;
349     default: channel_cnt_str = "Two"; break;
350     }
351 
352     if(channel_count >= 2 && channel_count <= 8) {
353        ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
354        if (!ctl) {
355             ALOGE("%s: could not get ctl for mixer cmd - %s",
356                   __func__, mixer_ctl_name);
357         return -EINVAL;
358        }
359     }
360     mixer_ctl_set_enum_by_string(ctl, channel_cnt_str);
361 
362     if (channel_count == 6 || channel_count == 8 || channel_count == 2) {
363         ret = afe_proxy_set_channel_mapping(adev, channel_count);
364     } else {
365         ALOGE("%s: set unsupported channel count(%d)",  __func__, channel_count);
366         ret = -EINVAL;
367     }
368 
369     ALOGD("%s: exit", __func__);
370     return ret;
371 }
372 
audio_extn_set_afe_proxy_parameters(struct audio_device * adev,struct str_parms * parms)373 void audio_extn_set_afe_proxy_parameters(struct audio_device *adev,
374                                          struct str_parms *parms)
375 {
376     int ret, val;
377     char value[32]={0};
378 
379     ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_WFD, value,
380                             sizeof(value));
381     if (ret >= 0) {
382         val = atoi(value);
383         aextnmod.proxy_channel_num = val;
384         adev->cur_wfd_channels = val;
385         ALOGD("%s: channel capability set to: %d", __func__,
386                aextnmod.proxy_channel_num);
387     }
388 }
389 
audio_extn_get_afe_proxy_parameters(struct str_parms * query,struct str_parms * reply)390 int audio_extn_get_afe_proxy_parameters(struct str_parms *query,
391                                         struct str_parms *reply)
392 {
393     int ret, val;
394     char value[32]={0};
395     char *str = NULL;
396 
397     ret = str_parms_get_str(query, AUDIO_PARAMETER_CAN_OPEN_PROXY, value,
398                             sizeof(value));
399     if (ret >= 0) {
400         if (audio_extn_usb_is_proxy_inuse())
401             val = 0;
402         else
403             val = 1;
404         str_parms_add_int(reply, AUDIO_PARAMETER_CAN_OPEN_PROXY, val);
405     }
406 
407     return 0;
408 }
409 
410 /* must be called with hw device mutex locked */
audio_extn_read_afe_proxy_channel_masks(struct stream_out * out)411 int32_t audio_extn_read_afe_proxy_channel_masks(struct stream_out *out)
412 {
413     int ret = 0;
414     int channels = aextnmod.proxy_channel_num;
415 
416     switch (channels) {
417         /*
418          * Do not handle stereo output in Multi-channel cases
419          * Stereo case is handled in normal playback path
420          */
421     case 6:
422         ALOGV("%s: AFE PROXY supports 5.1", __func__);
423         out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
424         break;
425     case 8:
426         ALOGV("%s: AFE PROXY supports 5.1 and 7.1 channels", __func__);
427         out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
428         out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
429         break;
430     default:
431         ALOGE("AFE PROXY does not support multi channel playback");
432         ret = -ENOSYS;
433         break;
434     }
435     return ret;
436 }
437 
audio_extn_get_afe_proxy_channel_count()438 int32_t audio_extn_get_afe_proxy_channel_count()
439 {
440     return aextnmod.proxy_channel_num;
441 }
442 
443 #endif /* AFE_PROXY_ENABLED */
444 
get_active_offload_usecases(const struct audio_device * adev,struct str_parms * query,struct str_parms * reply)445 static int get_active_offload_usecases(const struct audio_device *adev,
446                                        struct str_parms *query,
447                                        struct str_parms *reply)
448 {
449     int ret, count = 0;
450     char value[32]={0};
451     struct listnode *node;
452     struct audio_usecase *usecase;
453 
454     ALOGV("%s", __func__);
455     ret = str_parms_get_str(query, AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE, value,
456                             sizeof(value));
457     if (ret >= 0) {
458         list_for_each(node, &adev->usecase_list) {
459             usecase = node_to_item(node, struct audio_usecase, list);
460             if (is_offload_usecase(usecase->id))
461                 count++;
462         }
463         ALOGV("%s, number of active offload usecases: %d", __func__, count);
464         str_parms_add_int(reply, AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE, count);
465     }
466     return ret;
467 }
468 
469 #ifndef AUDIOSPHERE_ENABLED
470 #define audio_extn_asphere_set_parameters(adev, parms)  (0)
471 #define audio_extn_asphere_get_parameters(adev, query, reply) (0)
472 #else
audio_extn_asphere_set_parameters(const struct audio_device * adev,struct str_parms * parms)473 int32_t audio_extn_asphere_set_parameters(const struct audio_device *adev,
474                                      struct str_parms *parms)
475 {
476     int ret = 0, val[2];
477     char value[32] = {0};
478     int set_enable, set_strength;
479     int enable = -1, strength = -1;
480     struct mixer_ctl *ctl = NULL;
481     const char *mixer_ctl_name = "MSM ASphere Set Param";
482     char propValue[PROPERTY_VALUE_MAX] = {0};
483     bool asphere_prop_enabled = false;
484 
485     if (property_get("audio.pp.asphere.enabled", propValue, "false")) {
486         if (!strncmp("true", propValue, 4))
487             asphere_prop_enabled = true;
488     }
489 
490     if (!asphere_prop_enabled) {
491         ALOGV("%s: property not set!!! not doing anything", __func__);
492         return ret;
493     }
494 
495     set_enable = str_parms_get_str(parms,
496                             AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
497                             value, sizeof(value));
498     if (set_enable > 0)
499         enable = atoi(value);
500 
501     set_strength = str_parms_get_str(parms,
502                             AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
503                             value, sizeof(value));
504     if (set_strength > 0)
505         strength = atoi(value);
506 
507     if (set_enable >= 0 || set_strength >= 0) {
508         ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
509         if (!ctl) {
510             ALOGE("%s: could not get ctl for mixer cmd - %s",
511                   __func__, mixer_ctl_name);
512             return -EINVAL;
513         }
514         ALOGD("%s: set ctl \"%s:%d,%d\"",
515               __func__, mixer_ctl_name, enable, strength);
516         val[0] = enable;
517         val[1] = strength;
518         ret = mixer_ctl_set_array(ctl, val, sizeof(val)/sizeof(val[0]));
519         if (ret)
520             ALOGE("%s: set ctl failed!!!\"%s:%d,%d\"",
521                   __func__, mixer_ctl_name, enable, strength);
522     }
523     ALOGV("%s: exit ret %d", __func__, ret);
524     return ret;
525 }
526 
audio_extn_asphere_get_parameters(const struct audio_device * adev,struct str_parms * query,struct str_parms * reply)527 int32_t audio_extn_asphere_get_parameters(const struct audio_device *adev,
528                                           struct str_parms *query,
529                                           struct str_parms *reply)
530 {
531     int ret = 0, val[2] = {-1, -1};
532     char value[32] = {0};
533     int get_enable, get_strength;
534     struct mixer_ctl *ctl = NULL;
535     const char *mixer_ctl_name = "MSM ASphere Set Param";
536 
537     get_enable = str_parms_get_str(query,
538                                    AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
539                                    value, sizeof(value));
540     get_strength = str_parms_get_str(query,
541                                      AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
542                                      value, sizeof(value));
543     if (get_enable > 0 || get_strength > 0) {
544         ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
545         if (!ctl) {
546             ALOGE("%s: could not get ctl for mixer cmd - %s",
547                   __func__, mixer_ctl_name);
548             return -EINVAL;
549         }
550         ret = mixer_ctl_get_array(ctl, val, sizeof(val)/sizeof(val[0]));
551         if (ret)
552             ALOGE("%s: got ctl failed!!! \"%s:%d,%d\"",
553                    __func__, mixer_ctl_name, val[0], val[1]);
554         if (get_enable > 0)
555             str_parms_add_int(reply,
556                               AUDIO_PARAMETER_KEY_ASPHERE_ENABLE, val[0]);
557         if (get_strength > 0)
558             str_parms_add_int(reply,
559                               AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH, val[1]);
560     }
561     ALOGV("%s: exit ret %d", __func__, ret);
562     return ret;
563 }
564 #endif
565 
audio_extn_set_parameters(struct audio_device * adev,struct str_parms * parms)566 void audio_extn_set_parameters(struct audio_device *adev,
567                                struct str_parms *parms)
568 {
569    audio_extn_set_anc_parameters(adev, parms);
570    audio_extn_set_fluence_parameters(adev, parms);
571    audio_extn_set_afe_proxy_parameters(adev, parms);
572    audio_extn_fm_set_parameters(adev, parms);
573    audio_extn_sound_trigger_set_parameters(adev, parms);
574    audio_extn_listen_set_parameters(adev, parms);
575    audio_extn_hfp_set_parameters(adev, parms);
576    audio_extn_a2dp_set_parameters(parms);
577    audio_extn_ddp_set_parameters(adev, parms);
578    audio_extn_ds2_set_parameters(adev, parms);
579    audio_extn_customstereo_set_parameters(adev, parms);
580    audio_extn_pm_set_parameters(parms);
581    audio_extn_source_track_set_parameters(adev, parms);
582    audio_extn_asphere_set_parameters(adev, parms);
583 }
584 
audio_extn_get_parameters(const struct audio_device * adev,struct str_parms * query,struct str_parms * reply)585 void audio_extn_get_parameters(const struct audio_device *adev,
586                               struct str_parms *query,
587                               struct str_parms *reply)
588 {
589     char *kv_pairs = NULL;
590     audio_extn_get_afe_proxy_parameters(query, reply);
591     audio_extn_get_fluence_parameters(adev, query, reply);
592     get_active_offload_usecases(adev, query, reply);
593     audio_extn_source_track_get_parameters(adev, query, reply);
594     audio_extn_asphere_get_parameters(adev, query, reply);
595     kv_pairs = str_parms_to_str(reply);
596     ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs);
597     free(kv_pairs);
598 }
599 
600 #ifndef COMPRESS_METADATA_NEEDED
601 #define audio_extn_parse_compress_metadata(out, parms) (0)
602 #else
audio_extn_parse_compress_metadata(struct stream_out * out,struct str_parms * parms)603 int audio_extn_parse_compress_metadata(struct stream_out *out,
604                                        struct str_parms *parms)
605 {
606     int ret = 0;
607     char value[32];
608 
609     if (out->format == AUDIO_FORMAT_FLAC) {
610         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
611         if (ret >= 0) {
612             out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
613             out->send_new_metadata = 1;
614         }
615         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
616         if (ret >= 0) {
617             out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
618             out->send_new_metadata = 1;
619         }
620         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
621         if (ret >= 0) {
622             out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
623             out->send_new_metadata = 1;
624         }
625         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
626         if (ret >= 0) {
627             out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
628             out->send_new_metadata = 1;
629         }
630         ALOGV("FLAC metadata: min_blk_size %d, max_blk_size %d min_frame_size %d max_frame_size %d",
631               out->compr_config.codec->options.flac_dec.min_blk_size,
632               out->compr_config.codec->options.flac_dec.max_blk_size,
633               out->compr_config.codec->options.flac_dec.min_frame_size,
634               out->compr_config.codec->options.flac_dec.max_frame_size);
635     }
636 
637     else if (out->format == AUDIO_FORMAT_ALAC) {
638         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_FRAME_LENGTH, value, sizeof(value));
639         if (ret >= 0) {
640             out->compr_config.codec->options.alac.frame_length = atoi(value);
641             out->send_new_metadata = 1;
642         }
643         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_COMPATIBLE_VERSION, value, sizeof(value));
644         if (ret >= 0) {
645             out->compr_config.codec->options.alac.compatible_version = atoi(value);
646             out->send_new_metadata = 1;
647         }
648         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_BIT_DEPTH, value, sizeof(value));
649         if (ret >= 0) {
650             out->compr_config.codec->options.alac.bit_depth = atoi(value);
651             out->send_new_metadata = 1;
652         }
653         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_PB, value, sizeof(value));
654         if (ret >= 0) {
655             out->compr_config.codec->options.alac.pb = atoi(value);
656             out->send_new_metadata = 1;
657         }
658         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MB, value, sizeof(value));
659         if (ret >= 0) {
660             out->compr_config.codec->options.alac.mb = atoi(value);
661             out->send_new_metadata = 1;
662         }
663 
664         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_KB, value, sizeof(value));
665         if (ret >= 0) {
666             out->compr_config.codec->options.alac.kb = atoi(value);
667             out->send_new_metadata = 1;
668         }
669         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_NUM_CHANNELS, value, sizeof(value));
670         if (ret >= 0) {
671             out->compr_config.codec->options.alac.num_channels = atoi(value);
672             out->send_new_metadata = 1;
673         }
674         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MAX_RUN, value, sizeof(value));
675         if (ret >= 0) {
676             out->compr_config.codec->options.alac.max_run = atoi(value);
677             out->send_new_metadata = 1;
678         }
679         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MAX_FRAME_BYTES, value, sizeof(value));
680         if (ret >= 0) {
681             out->compr_config.codec->options.alac.max_frame_bytes = atoi(value);
682             out->send_new_metadata = 1;
683         }
684         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_AVG_BIT_RATE, value, sizeof(value));
685         if (ret >= 0) {
686             out->compr_config.codec->options.alac.avg_bit_rate = atoi(value);
687             out->send_new_metadata = 1;
688         }
689         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_SAMPLING_RATE, value, sizeof(value));
690         if (ret >= 0) {
691             out->compr_config.codec->options.alac.sample_rate = atoi(value);
692             out->send_new_metadata = 1;
693         }
694         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_CHANNEL_LAYOUT_TAG, value, sizeof(value));
695         if (ret >= 0) {
696             out->compr_config.codec->options.alac.channel_layout_tag = atoi(value);
697             out->send_new_metadata = 1;
698         }
699         ALOGV("ALAC CSD values: frameLength %d bitDepth %d numChannels %d"
700                 " maxFrameBytes %d, avgBitRate %d, sampleRate %d",
701                 out->compr_config.codec->options.alac.frame_length,
702                 out->compr_config.codec->options.alac.bit_depth,
703                 out->compr_config.codec->options.alac.num_channels,
704                 out->compr_config.codec->options.alac.max_frame_bytes,
705                 out->compr_config.codec->options.alac.avg_bit_rate,
706                 out->compr_config.codec->options.alac.sample_rate);
707     }
708 
709     else if (out->format == AUDIO_FORMAT_APE) {
710         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_COMPATIBLE_VERSION, value, sizeof(value));
711         if (ret >= 0) {
712             out->compr_config.codec->options.ape.compatible_version = atoi(value);
713             out->send_new_metadata = 1;
714         }
715         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_COMPRESSION_LEVEL, value, sizeof(value));
716         if (ret >= 0) {
717             out->compr_config.codec->options.ape.compression_level = atoi(value);
718             out->send_new_metadata = 1;
719         }
720         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_FORMAT_FLAGS, value, sizeof(value));
721         if (ret >= 0) {
722             out->compr_config.codec->options.ape.format_flags = atoi(value);
723             out->send_new_metadata = 1;
724         }
725         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_BLOCKS_PER_FRAME, value, sizeof(value));
726         if (ret >= 0) {
727             out->compr_config.codec->options.ape.blocks_per_frame = atoi(value);
728             out->send_new_metadata = 1;
729         }
730         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_FINAL_FRAME_BLOCKS, value, sizeof(value));
731         if (ret >= 0) {
732             out->compr_config.codec->options.ape.final_frame_blocks = atoi(value);
733             out->send_new_metadata = 1;
734         }
735         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_TOTAL_FRAMES, value, sizeof(value));
736         if (ret >= 0) {
737             out->compr_config.codec->options.ape.total_frames = atoi(value);
738             out->send_new_metadata = 1;
739         }
740         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_BITS_PER_SAMPLE, value, sizeof(value));
741         if (ret >= 0) {
742             out->compr_config.codec->options.ape.bits_per_sample = atoi(value);
743             out->send_new_metadata = 1;
744         }
745         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_NUM_CHANNELS, value, sizeof(value));
746         if (ret >= 0) {
747             out->compr_config.codec->options.ape.num_channels = atoi(value);
748             out->send_new_metadata = 1;
749         }
750         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_SAMPLE_RATE, value, sizeof(value));
751         if (ret >= 0) {
752             out->compr_config.codec->options.ape.sample_rate = atoi(value);
753             out->send_new_metadata = 1;
754         }
755         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_SEEK_TABLE_PRESENT, value, sizeof(value));
756         if (ret >= 0) {
757             out->compr_config.codec->options.ape.seek_table_present = atoi(value);
758             out->send_new_metadata = 1;
759         }
760         ALOGV("APE CSD values: compatibleVersion %d compressionLevel %d"
761                 " formatFlags %d blocksPerFrame %d finalFrameBlocks %d"
762                 " totalFrames %d bitsPerSample %d numChannels %d"
763                 " sampleRate %d seekTablePresent %d",
764                 out->compr_config.codec->options.ape.compatible_version,
765                 out->compr_config.codec->options.ape.compression_level,
766                 out->compr_config.codec->options.ape.format_flags,
767                 out->compr_config.codec->options.ape.blocks_per_frame,
768                 out->compr_config.codec->options.ape.final_frame_blocks,
769                 out->compr_config.codec->options.ape.total_frames,
770                 out->compr_config.codec->options.ape.bits_per_sample,
771                 out->compr_config.codec->options.ape.num_channels,
772                 out->compr_config.codec->options.ape.sample_rate,
773                 out->compr_config.codec->options.ape.seek_table_present);
774     }
775 
776     else if (out->format == AUDIO_FORMAT_VORBIS) {
777         // transcoded bitstream mode
778         out->compr_config.codec->options.vorbis_dec.bit_stream_fmt = 1;
779         out->send_new_metadata = 1;
780     }
781 
782     else if (out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
783         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
784         if (ret >= 0) {
785             out->compr_config.codec->format = atoi(value);
786             out->send_new_metadata = 1;
787         }
788         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
789         if (ret >= 0) {
790             out->compr_config.codec->options.wma.super_block_align = atoi(value);
791             out->send_new_metadata = 1;
792         }
793         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
794         if (ret >= 0) {
795             out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
796             out->send_new_metadata = 1;
797         }
798         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
799         if (ret >= 0) {
800             out->compr_config.codec->options.wma.channelmask = atoi(value);
801             out->send_new_metadata = 1;
802         }
803         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
804         if (ret >= 0) {
805             out->compr_config.codec->options.wma.encodeopt = atoi(value);
806             out->send_new_metadata = 1;
807         }
808         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
809         if (ret >= 0) {
810             out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
811             out->send_new_metadata = 1;
812         }
813         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
814         if (ret >= 0) {
815             out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
816             out->send_new_metadata = 1;
817         }
818         ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
819                 out->compr_config.codec->format,
820                 out->compr_config.codec->options.wma.super_block_align,
821                 out->compr_config.codec->options.wma.bits_per_sample,
822                 out->compr_config.codec->options.wma.channelmask,
823                 out->compr_config.codec->options.wma.encodeopt,
824                 out->compr_config.codec->options.wma.encodeopt1,
825                 out->compr_config.codec->options.wma.encodeopt2);
826     }
827 
828     return ret;
829 }
830 #endif
831 
832 #ifdef AUXPCM_BT_ENABLED
audio_extn_read_xml(struct audio_device * adev,uint32_t mixer_card,const char * mixer_xml_path,const char * mixer_xml_path_auxpcm)833 int32_t audio_extn_read_xml(struct audio_device *adev, uint32_t mixer_card,
834                             const char* mixer_xml_path,
835                             const char* mixer_xml_path_auxpcm)
836 {
837     char bt_soc[128];
838     bool wifi_init_complete = false;
839     int sleep_retry = 0;
840 
841     while (!wifi_init_complete && sleep_retry < MAX_SLEEP_RETRY) {
842         property_get("qcom.bluetooth.soc", bt_soc, NULL);
843         if (strncmp(bt_soc, "unknown", sizeof("unknown"))) {
844             wifi_init_complete = true;
845         } else {
846             usleep(WIFI_INIT_WAIT_SLEEP*1000);
847             sleep_retry++;
848         }
849     }
850 
851     if (!strncmp(bt_soc, "ath3k", sizeof("ath3k")))
852         adev->audio_route = audio_route_init(mixer_card, mixer_xml_path_auxpcm);
853     else
854         adev->audio_route = audio_route_init(mixer_card, mixer_xml_path);
855 
856     return 0;
857 }
858 #endif /* AUXPCM_BT_ENABLED */
859 
860 #ifdef KPI_OPTIMIZE_ENABLED
861 typedef int (*perf_lock_acquire_t)(int, int, int*, int);
862 typedef int (*perf_lock_release_t)(int);
863 
864 static void *qcopt_handle;
865 static perf_lock_acquire_t perf_lock_acq;
866 static perf_lock_release_t perf_lock_rel;
867 
868 static int perf_lock_handle;
869 char opt_lib_path[512] = {0};
870 int perf_lock_opts[1] = {0x20E};
871 
audio_extn_perf_lock_init(void)872 int audio_extn_perf_lock_init(void)
873 {
874     int ret = 0;
875     if (qcopt_handle == NULL) {
876         if (property_get("ro.vendor.extension_library",
877                          opt_lib_path, NULL) <= 0) {
878             ALOGE("%s: Failed getting perf property \n", __func__);
879             ret = -EINVAL;
880             goto err;
881         }
882         if ((qcopt_handle = dlopen(opt_lib_path, RTLD_NOW)) == NULL) {
883             ALOGE("%s: Failed to open perf handle \n", __func__);
884             ret = -EINVAL;
885             goto err;
886         } else {
887             perf_lock_acq = (perf_lock_acquire_t)dlsym(qcopt_handle,
888                                                        "perf_lock_acq");
889             if (perf_lock_acq == NULL) {
890                 ALOGE("%s: Perf lock Acquire NULL \n", __func__);
891                 ret = -EINVAL;
892                 goto err;
893             }
894             perf_lock_rel = (perf_lock_release_t)dlsym(qcopt_handle,
895                                                        "perf_lock_rel");
896             if (perf_lock_rel == NULL) {
897                 ALOGE("%s: Perf lock Release NULL \n", __func__);
898                 ret = -EINVAL;
899                 goto err;
900             }
901             ALOGE("%s: Perf lock handles Success \n", __func__);
902         }
903     }
904 err:
905     return ret;
906 }
907 
audio_extn_perf_lock_acquire(void)908 void audio_extn_perf_lock_acquire(void)
909 {
910     if (perf_lock_acq)
911         perf_lock_handle = perf_lock_acq(perf_lock_handle, 0, perf_lock_opts, 1);
912     else
913         ALOGE("%s: Perf lock acquire error \n", __func__);
914 }
915 
audio_extn_perf_lock_release(void)916 void audio_extn_perf_lock_release(void)
917 {
918     if (perf_lock_rel && perf_lock_handle)
919         perf_lock_rel(perf_lock_handle);
920     else
921         ALOGE("%s: Perf lock release error \n", __func__);
922 }
923 #endif /* KPI_OPTIMIZE_ENABLED */
924