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
ril_register_set_wb_amr_callback(void * function,void * data)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 */
ril_set_wb_amr_callback(void * ril_client,const void * data,size_t datalen)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
ril_connect_if_required(struct ril_handle * ril)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
ril_open(struct ril_handle * ril)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
ril_close(struct ril_handle * ril)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
ril_set_call_volume(struct ril_handle * ril,enum ril_sound_type sound_type,float volume)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
ril_set_call_audio_path(struct ril_handle * ril,enum ril_audio_path path)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