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