1 /* 2 * Copyright (C) 2011 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 "audio_hw_primary" 18 /*#define LOG_NDEBUG 0*/ 19 20 #include <dlfcn.h> 21 #include <stdlib.h> 22 23 #include <utils/Log.h> 24 #include <cutils/properties.h> 25 26 #include "ril_interface.h" 27 28 #define VOLUME_STEPS_DEFAULT "5" 29 #define VOLUME_STEPS_PROPERTY "ro.config.vc_call_vol_steps" 30 31 /* Function pointers */ 32 void *(*_ril_open_client)(void); 33 int (*_ril_close_client)(void *); 34 int (*_ril_connect)(void *); 35 int (*_ril_is_connected)(void *); 36 int (*_ril_disconnect)(void *); 37 int (*_ril_set_call_volume)(void *, enum ril_sound_type, int); 38 int (*_ril_set_call_audio_path)(void *, enum ril_audio_path); 39 int (*_ril_set_call_clock_sync)(void *, enum ril_clock_state); 40 int (*_ril_register_unsolicited_handler)(void *, int, void *); 41 int (*_ril_get_wb_amr)(void *, void *); 42 43 /* Audio WB AMR callback */ 44 void (*_audio_set_wb_amr_callback)(void *, int); 45 void *callback_data = NULL; 46 47 void ril_register_set_wb_amr_callback(void *function, void *data) 48 { 49 _audio_set_wb_amr_callback = function; 50 callback_data = data; 51 } 52 53 /* This is the callback function that the RIL uses to 54 set the wideband AMR state */ 55 static int ril_set_wb_amr_callback(void *ril_client, 56 const void *data, 57 size_t datalen) 58 { 59 int enable = ((int *)data)[0]; 60 61 if (!callback_data || !_audio_set_wb_amr_callback) 62 return -1; 63 64 _audio_set_wb_amr_callback(callback_data, enable); 65 66 return 0; 67 } 68 69 static int ril_connect_if_required(struct ril_handle *ril) 70 { 71 if (_ril_is_connected(ril->client)) 72 return 0; 73 74 if (_ril_connect(ril->client) != RIL_CLIENT_ERR_SUCCESS) { 75 LOGE("ril_connect() failed"); 76 return -1; 77 } 78 79 /* get wb amr status to set pcm samplerate depending on 80 wb amr status when ril is connected. */ 81 if(_ril_get_wb_amr) 82 _ril_get_wb_amr(ril->client, ril_set_wb_amr_callback); 83 84 return 0; 85 } 86 87 int ril_open(struct ril_handle *ril) 88 { 89 char property[PROPERTY_VALUE_MAX]; 90 91 if (!ril) 92 return -1; 93 94 ril->handle = dlopen(RIL_CLIENT_LIBPATH, RTLD_NOW); 95 96 if (!ril->handle) { 97 LOGE("Cannot open '%s'", RIL_CLIENT_LIBPATH); 98 return -1; 99 } 100 101 _ril_open_client = dlsym(ril->handle, "OpenClient_RILD"); 102 _ril_close_client = dlsym(ril->handle, "CloseClient_RILD"); 103 _ril_connect = dlsym(ril->handle, "Connect_RILD"); 104 _ril_is_connected = dlsym(ril->handle, "isConnected_RILD"); 105 _ril_disconnect = dlsym(ril->handle, "Disconnect_RILD"); 106 _ril_set_call_volume = dlsym(ril->handle, "SetCallVolume"); 107 _ril_set_call_audio_path = dlsym(ril->handle, "SetCallAudioPath"); 108 _ril_set_call_clock_sync = dlsym(ril->handle, "SetCallClockSync"); 109 _ril_register_unsolicited_handler = dlsym(ril->handle, 110 "RegisterUnsolicitedHandler"); 111 /* since this function is not supported in all RILs, don't require it */ 112 _ril_get_wb_amr = dlsym(ril->handle, "GetWB_AMR"); 113 114 if (!_ril_open_client || !_ril_close_client || !_ril_connect || 115 !_ril_is_connected || !_ril_disconnect || !_ril_set_call_volume || 116 !_ril_set_call_audio_path || !_ril_set_call_clock_sync || 117 !_ril_register_unsolicited_handler) { 118 LOGE("Cannot get symbols from '%s'", RIL_CLIENT_LIBPATH); 119 dlclose(ril->handle); 120 return -1; 121 } 122 123 ril->client = _ril_open_client(); 124 if (!ril->client) { 125 LOGE("ril_open_client() failed"); 126 dlclose(ril->handle); 127 return -1; 128 } 129 130 /* register the wideband AMR callback */ 131 _ril_register_unsolicited_handler(ril->client, RIL_UNSOL_WB_AMR_STATE, 132 ril_set_wb_amr_callback); 133 134 property_get(VOLUME_STEPS_PROPERTY, property, VOLUME_STEPS_DEFAULT); 135 ril->volume_steps_max = atoi(property); 136 /* this catches the case where VOLUME_STEPS_PROPERTY does not contain 137 an integer */ 138 if (ril->volume_steps_max == 0) 139 ril->volume_steps_max = atoi(VOLUME_STEPS_DEFAULT); 140 141 return 0; 142 } 143 144 int ril_close(struct ril_handle *ril) 145 { 146 if (!ril || !ril->handle || !ril->client) 147 return -1; 148 149 if ((_ril_disconnect(ril->client) != RIL_CLIENT_ERR_SUCCESS) || 150 (_ril_close_client(ril->client) != RIL_CLIENT_ERR_SUCCESS)) { 151 LOGE("ril_disconnect() or ril_close_client() failed"); 152 return -1; 153 } 154 155 dlclose(ril->handle); 156 return 0; 157 } 158 159 int ril_set_call_volume(struct ril_handle *ril, enum ril_sound_type sound_type, 160 float volume) 161 { 162 if (ril_connect_if_required(ril)) 163 return 0; 164 165 return _ril_set_call_volume(ril->client, sound_type, 166 (int)(volume * ril->volume_steps_max)); 167 } 168 169 int ril_set_call_audio_path(struct ril_handle *ril, enum ril_audio_path path) 170 { 171 if (ril_connect_if_required(ril)) 172 return 0; 173 174 return _ril_set_call_audio_path(ril->client, path); 175 } 176 177 int ril_set_call_clock_sync(struct ril_handle *ril, enum ril_clock_state state) 178 { 179 if (ril_connect_if_required(ril)) 180 return 0; 181 182 return _ril_set_call_clock_sync(ril->client, state); 183 } 184