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