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