Home | History | Annotate | Download | only in audio
      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