| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "audio_hw_primary" |
| /*#define LOG_NDEBUG 0*/ |
| |
| #include <dlfcn.h> |
| #include <stdlib.h> |
| |
| #include <utils/Log.h> |
| #include <cutils/properties.h> |
| |
| #include "ril_interface.h" |
| |
| #define VOLUME_STEPS_DEFAULT "5" |
| #define VOLUME_STEPS_PROPERTY "ro.config.vc_call_vol_steps" |
| |
| /* Function pointers */ |
| void *(*_ril_open_client)(void); |
| int (*_ril_close_client)(void *); |
| int (*_ril_connect)(void *); |
| int (*_ril_is_connected)(void *); |
| int (*_ril_disconnect)(void *); |
| int (*_ril_set_call_volume)(void *, enum ril_sound_type, int); |
| int (*_ril_set_call_audio_path)(void *, enum ril_audio_path); |
| int (*_ril_register_unsolicited_handler)(void *, int, void *); |
| int (*_ril_get_wb_amr)(void *, void *); |
| |
| /* Audio WB AMR callback */ |
| void (*_audio_set_wb_amr_callback)(void *, int); |
| void *callback_data = NULL; |
| |
| void ril_register_set_wb_amr_callback(void *function, void *data) |
| { |
| _audio_set_wb_amr_callback = function; |
| callback_data = data; |
| } |
| |
| /* This is the callback function that the RIL uses to |
| set the wideband AMR state */ |
| static int ril_set_wb_amr_callback(void *ril_client, |
| const void *data, |
| size_t datalen) |
| { |
| int enable = ((int *)data)[0]; |
| |
| if (!callback_data || !_audio_set_wb_amr_callback) |
| return -1; |
| |
| _audio_set_wb_amr_callback(callback_data, enable); |
| |
| return 0; |
| } |
| |
| static int ril_connect_if_required(struct ril_handle *ril) |
| { |
| if (_ril_is_connected(ril->client)) |
| return 0; |
| |
| if (_ril_connect(ril->client) != RIL_CLIENT_ERR_SUCCESS) { |
| ALOGE("ril_connect() failed"); |
| return -1; |
| } |
| |
| /* get wb amr status to set pcm samplerate depending on |
| wb amr status when ril is connected. */ |
| if(_ril_get_wb_amr) |
| _ril_get_wb_amr(ril->client, ril_set_wb_amr_callback); |
| |
| return 0; |
| } |
| |
| int ril_open(struct ril_handle *ril) |
| { |
| char property[PROPERTY_VALUE_MAX]; |
| |
| if (!ril) |
| return -1; |
| |
| ril->handle = dlopen(RIL_CLIENT_LIBPATH, RTLD_NOW); |
| |
| if (!ril->handle) { |
| ALOGE("Cannot open '%s'", RIL_CLIENT_LIBPATH); |
| return -1; |
| } |
| |
| _ril_open_client = dlsym(ril->handle, "OpenClient_RILD"); |
| _ril_close_client = dlsym(ril->handle, "CloseClient_RILD"); |
| _ril_connect = dlsym(ril->handle, "Connect_RILD"); |
| _ril_is_connected = dlsym(ril->handle, "isConnected_RILD"); |
| _ril_disconnect = dlsym(ril->handle, "Disconnect_RILD"); |
| _ril_set_call_volume = dlsym(ril->handle, "SetCallVolume"); |
| _ril_set_call_audio_path = dlsym(ril->handle, "SetCallAudioPath"); |
| _ril_register_unsolicited_handler = dlsym(ril->handle, |
| "RegisterUnsolicitedHandler"); |
| /* since this function is not supported in all RILs, don't require it */ |
| _ril_get_wb_amr = dlsym(ril->handle, "GetWB_AMR"); |
| |
| if (!_ril_open_client || !_ril_close_client || !_ril_connect || |
| !_ril_is_connected || !_ril_disconnect || !_ril_set_call_volume || |
| !_ril_set_call_audio_path || !_ril_register_unsolicited_handler) { |
| ALOGE("Cannot get symbols from '%s'", RIL_CLIENT_LIBPATH); |
| dlclose(ril->handle); |
| return -1; |
| } |
| |
| ril->client = _ril_open_client(); |
| if (!ril->client) { |
| ALOGE("ril_open_client() failed"); |
| dlclose(ril->handle); |
| return -1; |
| } |
| |
| /* register the wideband AMR callback */ |
| _ril_register_unsolicited_handler(ril->client, RIL_UNSOL_WB_AMR_STATE, |
| ril_set_wb_amr_callback); |
| |
| property_get(VOLUME_STEPS_PROPERTY, property, VOLUME_STEPS_DEFAULT); |
| ril->volume_steps_max = atoi(property); |
| /* this catches the case where VOLUME_STEPS_PROPERTY does not contain |
| an integer */ |
| if (ril->volume_steps_max == 0) |
| ril->volume_steps_max = atoi(VOLUME_STEPS_DEFAULT); |
| |
| return 0; |
| } |
| |
| int ril_close(struct ril_handle *ril) |
| { |
| if (!ril || !ril->handle || !ril->client) |
| return -1; |
| |
| if ((_ril_disconnect(ril->client) != RIL_CLIENT_ERR_SUCCESS) || |
| (_ril_close_client(ril->client) != RIL_CLIENT_ERR_SUCCESS)) { |
| ALOGE("ril_disconnect() or ril_close_client() failed"); |
| return -1; |
| } |
| |
| dlclose(ril->handle); |
| return 0; |
| } |
| |
| int ril_set_call_volume(struct ril_handle *ril, enum ril_sound_type sound_type, |
| float volume) |
| { |
| if (ril_connect_if_required(ril)) |
| return 0; |
| |
| return _ril_set_call_volume(ril->client, sound_type, |
| (int)(volume * ril->volume_steps_max)); |
| } |
| |
| int ril_set_call_audio_path(struct ril_handle *ril, enum ril_audio_path path) |
| { |
| if (ril_connect_if_required(ril)) |
| return 0; |
| |
| return _ril_set_call_audio_path(ril->client, path); |
| } |