• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "ext_speaker"
18 /*#define LOG_NDEBUG 0*/
19 #include <cutils/log.h>
20 
21 #include <audio_hw.h>
22 #include <dlfcn.h>
23 
24 #ifdef __LP64__
25         #define LIB_SPEAKER_BUNDLE "/system/lib64/soundfx/libspeakerbundle.so"
26 #else
27         #define LIB_SPEAKER_BUNDLE "/system/lib/soundfx/libspeakerbundle.so"
28 #endif
29 
30 typedef void (*set_mode_t)(int);
31 typedef void (*set_speaker_on_t)(bool);
32 typedef void (*set_earpiece_on_t)(bool);
33 typedef void (*set_voice_vol_t)(float);
34 
35 struct speaker_data {
36     struct audio_device *adev;
37     void *speaker_bundle;
38     set_mode_t set_mode;
39     set_speaker_on_t set_speaker_on;
40     set_earpiece_on_t set_earpiece_on;
41     set_voice_vol_t set_voice_vol;
42 };
43 
open_speaker_bundle()44 static struct speaker_data* open_speaker_bundle()
45 {
46     struct speaker_data *sd = calloc(1, sizeof(struct speaker_data));
47 
48     sd->speaker_bundle = dlopen(LIB_SPEAKER_BUNDLE, RTLD_NOW);
49     if (sd->speaker_bundle == NULL) {
50         ALOGE("%s: DLOPEN failed for %s", __func__, LIB_SPEAKER_BUNDLE);
51         goto error;
52     } else {
53         ALOGV("%s: DLOPEN successful for %s", __func__, LIB_SPEAKER_BUNDLE);
54 
55         sd->set_mode = (set_mode_t)dlsym(sd->speaker_bundle,
56                                              "set_mode");
57         if (sd->set_mode == NULL) {
58             ALOGE("%s: dlsym error %s for set_mode", __func__,
59                   dlerror());
60             goto error;
61         }
62         sd->set_speaker_on = (set_speaker_on_t)dlsym(sd->speaker_bundle,
63                                              "set_speaker_on");
64         if (sd->set_speaker_on == NULL) {
65             ALOGE("%s: dlsym error %s for set_speaker_on", __func__,
66                   dlerror());
67             goto error;
68         }
69         sd->set_earpiece_on = (set_earpiece_on_t)dlsym(sd->speaker_bundle,
70                                              "set_earpiece_on");
71         if (sd->set_earpiece_on == NULL) {
72             ALOGE("%s: dlsym error %s for set_earpiece_on", __func__,
73                   dlerror());
74             goto error;
75         }
76         sd->set_voice_vol = (set_voice_vol_t)dlsym(sd->speaker_bundle,
77                                              "set_voice_volume");
78         if (sd->set_voice_vol == NULL) {
79             ALOGE("%s: dlsym error %s for set_voice_volume",
80                   __func__, dlerror());
81             goto error;
82         }
83     }
84     return sd;
85 
86 error:
87     free(sd);
88     return 0;
89 }
90 
close_speaker_bundle(struct speaker_data * sd)91 static void close_speaker_bundle(struct speaker_data *sd)
92 {
93     if (sd != NULL) {
94         dlclose(sd->speaker_bundle);
95         free(sd);
96         sd = NULL;
97     }
98 }
99 
audio_extn_extspk_init(struct audio_device * adev)100 void *audio_extn_extspk_init(struct audio_device *adev)
101 {
102     struct speaker_data *data = open_speaker_bundle();
103 
104     if (data)
105         data->adev = adev;
106 
107     return data;
108 }
109 
audio_extn_extspk_deinit(void * extn)110 void audio_extn_extspk_deinit(void *extn)
111 {
112     struct speaker_data *data = (struct speaker_data*)extn;
113     close_speaker_bundle(data);
114 }
115 
audio_extn_extspk_update(void * extn)116 void audio_extn_extspk_update(void* extn)
117 {
118     struct speaker_data *data = (struct speaker_data*)extn;
119 
120     if (data) {
121         bool speaker_on = false;
122         bool earpiece_on = false;
123         struct listnode *node;
124         struct audio_usecase *usecase;
125         list_for_each(node, &data->adev->usecase_list) {
126             usecase = node_to_item(node, struct audio_usecase, list);
127             if (usecase->devices & AUDIO_DEVICE_OUT_EARPIECE) {
128                 if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
129                     earpiece_on = true;
130                 }
131             }
132             if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) {
133                 if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
134                     speaker_on = true;
135                 }
136             }
137         }
138         data->set_earpiece_on(earpiece_on);
139         data->set_speaker_on(speaker_on);
140     }
141 }
142 
audio_extn_extspk_set_mode(void * extn,audio_mode_t mode)143 void audio_extn_extspk_set_mode(void* extn, audio_mode_t mode)
144 {
145     struct speaker_data *data = (struct speaker_data*)extn;
146 
147     if (data)
148         data->set_mode(mode);
149 }
150 
audio_extn_extspk_set_voice_vol(void * extn,float vol)151 void audio_extn_extspk_set_voice_vol(void* extn, float vol)
152 {
153     struct speaker_data *data = (struct speaker_data*)extn;
154 
155     if (data)
156         data->set_voice_vol(vol);
157 }
158