blob: 3d7ce06de0465f3b09eae8e8b25ed4bc436e5130 [file] [log] [blame]
/*
* 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);
}