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 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 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 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 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 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 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 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