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 <stdlib.h>
22 #include <audio_hw.h>
23 #include <dlfcn.h>
24
25 #ifdef __LP64__
26 #define LIB_SPEAKER_BUNDLE "/system/lib64/soundfx/libspeakerbundle.so"
27 #else
28 #define LIB_SPEAKER_BUNDLE "/system/lib/soundfx/libspeakerbundle.so"
29 #endif
30
31 typedef void (*set_mode_t)(int);
32 typedef void (*set_speaker_on_t)(bool);
33 typedef void (*set_earpiece_on_t)(bool);
34 typedef void (*set_voice_vol_t)(float);
35
36 struct speaker_data {
37 struct audio_device *adev;
38 void *speaker_bundle;
39 set_mode_t set_mode;
40 set_speaker_on_t set_speaker_on;
41 set_earpiece_on_t set_earpiece_on;
42 set_voice_vol_t set_voice_vol;
43 };
44
open_speaker_bundle()45 static struct speaker_data* open_speaker_bundle()
46 {
47 struct speaker_data *sd = calloc(1, sizeof(struct speaker_data));
48
49 sd->speaker_bundle = dlopen(LIB_SPEAKER_BUNDLE, RTLD_NOW);
50 if (sd->speaker_bundle == NULL) {
51 ALOGE("%s: DLOPEN failed for %s", __func__, LIB_SPEAKER_BUNDLE);
52 goto error;
53 } else {
54 ALOGV("%s: DLOPEN successful for %s", __func__, LIB_SPEAKER_BUNDLE);
55
56 sd->set_mode = (set_mode_t)dlsym(sd->speaker_bundle,
57 "set_mode");
58 if (sd->set_mode == NULL) {
59 ALOGE("%s: dlsym error %s for set_mode", __func__,
60 dlerror());
61 goto error;
62 }
63 sd->set_speaker_on = (set_speaker_on_t)dlsym(sd->speaker_bundle,
64 "set_speaker_on");
65 if (sd->set_speaker_on == NULL) {
66 ALOGE("%s: dlsym error %s for set_speaker_on", __func__,
67 dlerror());
68 goto error;
69 }
70 sd->set_earpiece_on = (set_earpiece_on_t)dlsym(sd->speaker_bundle,
71 "set_earpiece_on");
72 if (sd->set_earpiece_on == NULL) {
73 ALOGE("%s: dlsym error %s for set_earpiece_on", __func__,
74 dlerror());
75 goto error;
76 }
77 sd->set_voice_vol = (set_voice_vol_t)dlsym(sd->speaker_bundle,
78 "set_voice_volume");
79 if (sd->set_voice_vol == NULL) {
80 ALOGE("%s: dlsym error %s for set_voice_volume",
81 __func__, dlerror());
82 goto error;
83 }
84 }
85 return sd;
86
87 error:
88 free(sd);
89 return 0;
90 }
91
close_speaker_bundle(struct speaker_data * sd)92 static void close_speaker_bundle(struct speaker_data *sd)
93 {
94 if (sd != NULL) {
95 dlclose(sd->speaker_bundle);
96 free(sd);
97 sd = NULL;
98 }
99 }
100
audio_extn_extspk_init(struct audio_device * adev)101 void *audio_extn_extspk_init(struct audio_device *adev)
102 {
103 struct speaker_data *data = open_speaker_bundle();
104
105 if (data)
106 data->adev = adev;
107
108 return data;
109 }
110
audio_extn_extspk_deinit(void * extn)111 void audio_extn_extspk_deinit(void *extn)
112 {
113 struct speaker_data *data = (struct speaker_data*)extn;
114 close_speaker_bundle(data);
115 }
116
audio_extn_extspk_update(void * extn)117 void audio_extn_extspk_update(void* extn)
118 {
119 struct speaker_data *data = (struct speaker_data*)extn;
120
121 if (data) {
122 bool speaker_on = false;
123 bool earpiece_on = false;
124 struct listnode *node;
125 struct audio_usecase *usecase;
126 list_for_each(node, &data->adev->usecase_list) {
127 usecase = node_to_item(node, struct audio_usecase, list);
128 if (usecase->devices & AUDIO_DEVICE_OUT_EARPIECE) {
129 if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
130 earpiece_on = true;
131 }
132 }
133 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER) {
134 if(data->adev->snd_dev_ref_cnt[usecase->out_snd_device] != 0) {
135 speaker_on = true;
136 }
137 }
138 }
139 data->set_earpiece_on(earpiece_on);
140 data->set_speaker_on(speaker_on);
141 }
142 }
143
audio_extn_extspk_set_mode(void * extn,audio_mode_t mode)144 void audio_extn_extspk_set_mode(void* extn, audio_mode_t mode)
145 {
146 struct speaker_data *data = (struct speaker_data*)extn;
147
148 if (data)
149 data->set_mode(mode);
150 }
151
audio_extn_extspk_set_voice_vol(void * extn,float vol)152 void audio_extn_extspk_set_voice_vol(void* extn, float vol)
153 {
154 struct speaker_data *data = (struct speaker_data*)extn;
155
156 if (data)
157 data->set_voice_vol(vol);
158 }
159