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 <log/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 "/vendor/lib64/soundfx/libspeakerbundle.so" 27 #else 28 #define LIB_SPEAKER_BUNDLE "/vendor/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 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 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 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 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 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 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 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