1 /*
2 * Copyright (c) 2014 The Android Open Source Project
3 * Copyright (C) 2012 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #define LOG_TAG "BluetoothHeadsetClientServiceJni"
19
20 #include "com_android_bluetooth.h"
21 #include "hardware/bt_hf_client.h"
22 #include "utils/Log.h"
23
24 #include <shared_mutex>
25
26 namespace android {
27
28 static bthf_client_interface_t* sBluetoothHfpClientInterface = NULL;
29 static std::shared_mutex interface_mutex;
30
31 static jobject mCallbacksObj = NULL;
32 static std::shared_mutex callbacks_mutex;
33
34 static jmethodID method_onConnectionStateChanged;
35 static jmethodID method_onAudioStateChanged;
36 static jmethodID method_onVrStateChanged;
37 static jmethodID method_onNetworkState;
38 static jmethodID method_onNetworkRoaming;
39 static jmethodID method_onNetworkSignal;
40 static jmethodID method_onBatteryLevel;
41 static jmethodID method_onCurrentOperator;
42 static jmethodID method_onCall;
43 static jmethodID method_onCallSetup;
44 static jmethodID method_onCallHeld;
45 static jmethodID method_onRespAndHold;
46 static jmethodID method_onClip;
47 static jmethodID method_onCallWaiting;
48 static jmethodID method_onCurrentCalls;
49 static jmethodID method_onVolumeChange;
50 static jmethodID method_onCmdResult;
51 static jmethodID method_onSubscriberInfo;
52 static jmethodID method_onInBandRing;
53 static jmethodID method_onLastVoiceTagNumber;
54 static jmethodID method_onRingIndication;
55 static jmethodID method_onUnknownEvent;
56
marshall_bda(const RawAddress * bd_addr)57 static jbyteArray marshall_bda(const RawAddress* bd_addr) {
58 CallbackEnv sCallbackEnv(__func__);
59 if (!sCallbackEnv.valid()) return NULL;
60
61 jbyteArray addr = sCallbackEnv->NewByteArray(sizeof(RawAddress));
62 if (!addr) {
63 ALOGE("Fail to new jbyteArray bd addr");
64 return NULL;
65 }
66 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(RawAddress),
67 (jbyte*)bd_addr);
68 return addr;
69 }
70
connection_state_cb(const RawAddress * bd_addr,bthf_client_connection_state_t state,unsigned int peer_feat,unsigned int chld_feat)71 static void connection_state_cb(const RawAddress* bd_addr,
72 bthf_client_connection_state_t state,
73 unsigned int peer_feat,
74 unsigned int chld_feat) {
75 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
76 CallbackEnv sCallbackEnv(__func__);
77 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
78
79 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
80 if (!addr.get()) return;
81
82 ALOGD("%s: state %d peer_feat %d chld_feat %d", __func__, state, peer_feat, chld_feat);
83 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged,
84 (jint)state, (jint)peer_feat, (jint)chld_feat,
85 addr.get());
86 }
87
audio_state_cb(const RawAddress * bd_addr,bthf_client_audio_state_t state)88 static void audio_state_cb(const RawAddress* bd_addr,
89 bthf_client_audio_state_t state) {
90 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
91 CallbackEnv sCallbackEnv(__func__);
92 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
93
94 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
95 if (!addr.get()) return;
96
97 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged,
98 (jint)state, addr.get());
99 }
100
vr_cmd_cb(const RawAddress * bd_addr,bthf_client_vr_state_t state)101 static void vr_cmd_cb(const RawAddress* bd_addr, bthf_client_vr_state_t state) {
102 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
103 CallbackEnv sCallbackEnv(__func__);
104 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
105
106 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
107 if (!addr.get()) return;
108
109 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVrStateChanged,
110 (jint)state, addr.get());
111 }
112
network_state_cb(const RawAddress * bd_addr,bthf_client_network_state_t state)113 static void network_state_cb(const RawAddress* bd_addr,
114 bthf_client_network_state_t state) {
115 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
116 CallbackEnv sCallbackEnv(__func__);
117 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
118
119 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
120 if (!addr.get()) return;
121
122 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNetworkState,
123 (jint)state, addr.get());
124 }
125
network_roaming_cb(const RawAddress * bd_addr,bthf_client_service_type_t type)126 static void network_roaming_cb(const RawAddress* bd_addr,
127 bthf_client_service_type_t type) {
128 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
129 CallbackEnv sCallbackEnv(__func__);
130 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
131
132 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
133 if (!addr.get()) return;
134
135 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNetworkRoaming,
136 (jint)type, addr.get());
137 }
138
network_signal_cb(const RawAddress * bd_addr,int signal)139 static void network_signal_cb(const RawAddress* bd_addr, int signal) {
140 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
141 CallbackEnv sCallbackEnv(__func__);
142 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
143
144 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
145 if (!addr.get()) return;
146
147 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNetworkSignal,
148 (jint)signal, addr.get());
149 }
150
battery_level_cb(const RawAddress * bd_addr,int level)151 static void battery_level_cb(const RawAddress* bd_addr, int level) {
152 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
153 CallbackEnv sCallbackEnv(__func__);
154 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
155
156 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
157 if (!addr.get()) return;
158
159 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onBatteryLevel,
160 (jint)level, addr.get());
161 }
162
current_operator_cb(const RawAddress * bd_addr,const char * name)163 static void current_operator_cb(const RawAddress* bd_addr, const char* name) {
164 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
165 CallbackEnv sCallbackEnv(__func__);
166 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
167
168 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
169 if (!addr.get()) return;
170
171 const char null_str[] = "";
172 if (!sCallbackEnv.isValidUtf(name)) {
173 ALOGE("%s: name is not a valid UTF string.", __func__);
174 name = null_str;
175 }
176
177 ScopedLocalRef<jstring> js_name(sCallbackEnv.get(),
178 sCallbackEnv->NewStringUTF(name));
179 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCurrentOperator,
180 js_name.get(), addr.get());
181 }
182
call_cb(const RawAddress * bd_addr,bthf_client_call_t call)183 static void call_cb(const RawAddress* bd_addr, bthf_client_call_t call) {
184 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
185 CallbackEnv sCallbackEnv(__func__);
186 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
187
188 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
189 if (!addr.get()) return;
190
191 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCall, (jint)call,
192 addr.get());
193 }
194
callsetup_cb(const RawAddress * bd_addr,bthf_client_callsetup_t callsetup)195 static void callsetup_cb(const RawAddress* bd_addr,
196 bthf_client_callsetup_t callsetup) {
197 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
198 CallbackEnv sCallbackEnv(__func__);
199 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
200
201 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
202 if (!addr.get()) return;
203
204 ALOGD("callsetup_cb bdaddr %02x:%02x:%02x:%02x:%02x:%02x",
205 bd_addr->address[0], bd_addr->address[1], bd_addr->address[2],
206 bd_addr->address[3], bd_addr->address[4], bd_addr->address[5]);
207
208 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallSetup,
209 (jint)callsetup, addr.get());
210 }
211
callheld_cb(const RawAddress * bd_addr,bthf_client_callheld_t callheld)212 static void callheld_cb(const RawAddress* bd_addr,
213 bthf_client_callheld_t callheld) {
214 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
215 CallbackEnv sCallbackEnv(__func__);
216 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
217
218 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
219 if (!addr.get()) return;
220
221 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallHeld, (jint)callheld,
222 addr.get());
223 }
224
resp_and_hold_cb(const RawAddress * bd_addr,bthf_client_resp_and_hold_t resp_and_hold)225 static void resp_and_hold_cb(const RawAddress* bd_addr,
226 bthf_client_resp_and_hold_t resp_and_hold) {
227 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
228 CallbackEnv sCallbackEnv(__func__);
229 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
230
231 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
232 if (!addr.get()) return;
233
234 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRespAndHold,
235 (jint)resp_and_hold, addr.get());
236 }
237
clip_cb(const RawAddress * bd_addr,const char * number)238 static void clip_cb(const RawAddress* bd_addr, const char* number) {
239 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
240 CallbackEnv sCallbackEnv(__func__);
241 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
242
243 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
244 if (!addr.get()) return;
245
246 const char null_str[] = "";
247 if (!sCallbackEnv.isValidUtf(number)) {
248 ALOGE("%s: number is not a valid UTF string.", __func__);
249 number = null_str;
250 }
251
252 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
253 sCallbackEnv->NewStringUTF(number));
254 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClip, js_number.get(),
255 addr.get());
256 }
257
call_waiting_cb(const RawAddress * bd_addr,const char * number)258 static void call_waiting_cb(const RawAddress* bd_addr, const char* number) {
259 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
260 CallbackEnv sCallbackEnv(__func__);
261 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
262
263 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
264 if (!addr.get()) return;
265
266 const char null_str[] = "";
267 if (!sCallbackEnv.isValidUtf(number)) {
268 ALOGE("%s: number is not a valid UTF string.", __func__);
269 number = null_str;
270 }
271
272 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
273 sCallbackEnv->NewStringUTF(number));
274 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallWaiting,
275 js_number.get(), addr.get());
276 }
277
current_calls_cb(const RawAddress * bd_addr,int index,bthf_client_call_direction_t dir,bthf_client_call_state_t state,bthf_client_call_mpty_type_t mpty,const char * number)278 static void current_calls_cb(const RawAddress* bd_addr, int index,
279 bthf_client_call_direction_t dir,
280 bthf_client_call_state_t state,
281 bthf_client_call_mpty_type_t mpty,
282 const char* number) {
283 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
284 CallbackEnv sCallbackEnv(__func__);
285 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
286
287 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
288 if (!addr.get()) return;
289
290 const char null_str[] = "";
291 if (!sCallbackEnv.isValidUtf(number)) {
292 ALOGE("%s: number is not a valid UTF string.", __func__);
293 number = null_str;
294 }
295
296 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
297 sCallbackEnv->NewStringUTF(number));
298 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCurrentCalls, index, dir,
299 state, mpty, js_number.get(), addr.get());
300 }
301
volume_change_cb(const RawAddress * bd_addr,bthf_client_volume_type_t type,int volume)302 static void volume_change_cb(const RawAddress* bd_addr,
303 bthf_client_volume_type_t type, int volume) {
304 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
305 CallbackEnv sCallbackEnv(__func__);
306 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
307
308 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
309 if (!addr.get()) return;
310 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeChange, (jint)type,
311 (jint)volume, addr.get());
312 }
313
cmd_complete_cb(const RawAddress * bd_addr,bthf_client_cmd_complete_t type,int cme)314 static void cmd_complete_cb(const RawAddress* bd_addr,
315 bthf_client_cmd_complete_t type, int cme) {
316 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
317 CallbackEnv sCallbackEnv(__func__);
318 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
319
320 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
321 if (!addr.get()) return;
322 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCmdResult, (jint)type,
323 (jint)cme, addr.get());
324 }
325
subscriber_info_cb(const RawAddress * bd_addr,const char * name,bthf_client_subscriber_service_type_t type)326 static void subscriber_info_cb(const RawAddress* bd_addr, const char* name,
327 bthf_client_subscriber_service_type_t type) {
328 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
329 CallbackEnv sCallbackEnv(__func__);
330 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
331
332 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
333 if (!addr.get()) return;
334
335 const char null_str[] = "";
336 if (!sCallbackEnv.isValidUtf(name)) {
337 ALOGE("%s: name is not a valid UTF string.", __func__);
338 name = null_str;
339 }
340
341 ScopedLocalRef<jstring> js_name(sCallbackEnv.get(),
342 sCallbackEnv->NewStringUTF(name));
343 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSubscriberInfo,
344 js_name.get(), (jint)type, addr.get());
345 }
346
in_band_ring_cb(const RawAddress * bd_addr,bthf_client_in_band_ring_state_t in_band)347 static void in_band_ring_cb(const RawAddress* bd_addr,
348 bthf_client_in_band_ring_state_t in_band) {
349 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
350 CallbackEnv sCallbackEnv(__func__);
351 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
352
353 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
354 if (!addr.get()) return;
355 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onInBandRing,
356 (jint)in_band, addr.get());
357 }
358
last_voice_tag_number_cb(const RawAddress * bd_addr,const char * number)359 static void last_voice_tag_number_cb(const RawAddress* bd_addr,
360 const char* number) {
361 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
362 CallbackEnv sCallbackEnv(__func__);
363 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
364
365 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
366 if (!addr.get()) return;
367
368 const char null_str[] = "";
369 if (!sCallbackEnv.isValidUtf(number)) {
370 ALOGE("%s: number is not a valid UTF string.", __func__);
371 number = null_str;
372 }
373
374 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
375 sCallbackEnv->NewStringUTF(number));
376 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onLastVoiceTagNumber,
377 js_number.get(), addr.get());
378 }
379
ring_indication_cb(const RawAddress * bd_addr)380 static void ring_indication_cb(const RawAddress* bd_addr) {
381 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
382 CallbackEnv sCallbackEnv(__func__);
383 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
384
385 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
386 if (!addr.get()) return;
387 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRingIndication,
388 addr.get());
389 }
390
unknown_event_cb(const RawAddress * bd_addr,const char * eventString)391 static void unknown_event_cb(const RawAddress* bd_addr,
392 const char* eventString) {
393 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
394 CallbackEnv sCallbackEnv(__func__);
395 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
396
397 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
398 if (!addr.get()) return;
399
400 ScopedLocalRef<jstring> js_event(sCallbackEnv.get(),
401 sCallbackEnv->NewStringUTF(eventString));
402 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onUnknownEvent,
403 js_event.get(), addr.get());
404 }
405
406 static bthf_client_callbacks_t sBluetoothHfpClientCallbacks = {
407 sizeof(sBluetoothHfpClientCallbacks),
408 connection_state_cb,
409 audio_state_cb,
410 vr_cmd_cb,
411 network_state_cb,
412 network_roaming_cb,
413 network_signal_cb,
414 battery_level_cb,
415 current_operator_cb,
416 call_cb,
417 callsetup_cb,
418 callheld_cb,
419 resp_and_hold_cb,
420 clip_cb,
421 call_waiting_cb,
422 current_calls_cb,
423 volume_change_cb,
424 cmd_complete_cb,
425 subscriber_info_cb,
426 in_band_ring_cb,
427 last_voice_tag_number_cb,
428 ring_indication_cb,
429 unknown_event_cb,
430 };
431
classInitNative(JNIEnv * env,jclass clazz)432 static void classInitNative(JNIEnv* env, jclass clazz) {
433 method_onConnectionStateChanged =
434 env->GetMethodID(clazz, "onConnectionStateChanged", "(III[B)V");
435 method_onAudioStateChanged =
436 env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V");
437 method_onVrStateChanged =
438 env->GetMethodID(clazz, "onVrStateChanged", "(I[B)V");
439 method_onNetworkState = env->GetMethodID(clazz, "onNetworkState", "(I[B)V");
440 method_onNetworkRoaming = env->GetMethodID(clazz, "onNetworkRoaming", "(I[B)V");
441 method_onNetworkSignal = env->GetMethodID(clazz, "onNetworkSignal", "(I[B)V");
442 method_onBatteryLevel = env->GetMethodID(clazz, "onBatteryLevel", "(I[B)V");
443 method_onCurrentOperator =
444 env->GetMethodID(clazz, "onCurrentOperator", "(Ljava/lang/String;[B)V");
445 method_onCall = env->GetMethodID(clazz, "onCall", "(I[B)V");
446 method_onCallSetup = env->GetMethodID(clazz, "onCallSetup", "(I[B)V");
447 method_onCallHeld = env->GetMethodID(clazz, "onCallHeld", "(I[B)V");
448 method_onRespAndHold = env->GetMethodID(clazz, "onRespAndHold", "(I[B)V");
449 method_onClip = env->GetMethodID(clazz, "onClip", "(Ljava/lang/String;[B)V");
450 method_onCallWaiting =
451 env->GetMethodID(clazz, "onCallWaiting", "(Ljava/lang/String;[B)V");
452 method_onCurrentCalls =
453 env->GetMethodID(clazz, "onCurrentCalls", "(IIIILjava/lang/String;[B)V");
454 method_onVolumeChange = env->GetMethodID(clazz, "onVolumeChange", "(II[B)V");
455 method_onCmdResult = env->GetMethodID(clazz, "onCmdResult", "(II[B)V");
456 method_onSubscriberInfo =
457 env->GetMethodID(clazz, "onSubscriberInfo", "(Ljava/lang/String;I[B)V");
458 method_onInBandRing = env->GetMethodID(clazz, "onInBandRing", "(I[B)V");
459 method_onLastVoiceTagNumber =
460 env->GetMethodID(clazz, "onLastVoiceTagNumber", "(Ljava/lang/String;[B)V");
461 method_onRingIndication = env->GetMethodID(clazz, "onRingIndication", "([B)V");
462 method_onUnknownEvent =
463 env->GetMethodID(clazz, "onUnknownEvent", "(Ljava/lang/String;[B)V");
464
465 ALOGI("%s succeeds", __func__);
466 }
467
initializeNative(JNIEnv * env,jobject object)468 static void initializeNative(JNIEnv* env, jobject object) {
469 ALOGD("%s: HfpClient", __func__);
470 std::unique_lock<std::shared_mutex> interface_lock(interface_mutex);
471 std::unique_lock<std::shared_mutex> callbacks_lock(callbacks_mutex);
472
473 const bt_interface_t* btInf = getBluetoothInterface();
474 if (btInf == NULL) {
475 ALOGE("Bluetooth module is not loaded");
476 return;
477 }
478
479 if (sBluetoothHfpClientInterface != NULL) {
480 ALOGW("Cleaning up Bluetooth HFP Client Interface before initializing");
481 sBluetoothHfpClientInterface->cleanup();
482 sBluetoothHfpClientInterface = NULL;
483 }
484
485 if (mCallbacksObj != NULL) {
486 ALOGW("Cleaning up Bluetooth HFP Client callback object");
487 env->DeleteGlobalRef(mCallbacksObj);
488 mCallbacksObj = NULL;
489 }
490
491 sBluetoothHfpClientInterface =
492 (bthf_client_interface_t*)btInf->get_profile_interface(
493 BT_PROFILE_HANDSFREE_CLIENT_ID);
494 if (sBluetoothHfpClientInterface == NULL) {
495 ALOGE("Failed to get Bluetooth HFP Client Interface");
496 return;
497 }
498
499 bt_status_t status =
500 sBluetoothHfpClientInterface->init(&sBluetoothHfpClientCallbacks);
501 if (status != BT_STATUS_SUCCESS) {
502 ALOGE("Failed to initialize Bluetooth HFP Client, status: %d", status);
503 sBluetoothHfpClientInterface = NULL;
504 return;
505 }
506
507 mCallbacksObj = env->NewGlobalRef(object);
508 }
509
cleanupNative(JNIEnv * env,jobject object)510 static void cleanupNative(JNIEnv* env, jobject object) {
511 std::unique_lock<std::shared_mutex> interface_lock(interface_mutex);
512 std::unique_lock<std::shared_mutex> callbacks_lock(callbacks_mutex);
513
514 const bt_interface_t* btInf = getBluetoothInterface();
515 if (btInf == NULL) {
516 ALOGE("Bluetooth module is not loaded");
517 return;
518 }
519
520 if (sBluetoothHfpClientInterface != NULL) {
521 ALOGW("Cleaning up Bluetooth HFP Client Interface...");
522 sBluetoothHfpClientInterface->cleanup();
523 sBluetoothHfpClientInterface = NULL;
524 }
525
526 if (mCallbacksObj != NULL) {
527 ALOGW("Cleaning up Bluetooth HFP Client callback object");
528 env->DeleteGlobalRef(mCallbacksObj);
529 mCallbacksObj = NULL;
530 }
531 }
532
connectNative(JNIEnv * env,jobject object,jbyteArray address)533 static jboolean connectNative(JNIEnv* env, jobject object, jbyteArray address) {
534 std::shared_lock<std::shared_mutex> lock(interface_mutex);
535 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
536
537 jbyte* addr = env->GetByteArrayElements(address, NULL);
538 if (!addr) {
539 jniThrowIOException(env, EINVAL);
540 return JNI_FALSE;
541 }
542
543 bt_status_t status =
544 sBluetoothHfpClientInterface->connect((const RawAddress*)addr);
545 if (status != BT_STATUS_SUCCESS) {
546 ALOGE("Failed AG connection, status: %d", status);
547 }
548 env->ReleaseByteArrayElements(address, addr, 0);
549 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
550 }
551
disconnectNative(JNIEnv * env,jobject object,jbyteArray address)552 static jboolean disconnectNative(JNIEnv* env, jobject object,
553 jbyteArray address) {
554 std::shared_lock<std::shared_mutex> lock(interface_mutex);
555 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
556
557 jbyte* addr = env->GetByteArrayElements(address, NULL);
558 if (!addr) {
559 jniThrowIOException(env, EINVAL);
560 return JNI_FALSE;
561 }
562
563 bt_status_t status =
564 sBluetoothHfpClientInterface->disconnect((const RawAddress*)addr);
565 if (status != BT_STATUS_SUCCESS) {
566 ALOGE("Failed AG disconnection, status: %d", status);
567 }
568 env->ReleaseByteArrayElements(address, addr, 0);
569 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
570 }
571
connectAudioNative(JNIEnv * env,jobject object,jbyteArray address)572 static jboolean connectAudioNative(JNIEnv* env, jobject object,
573 jbyteArray address) {
574 std::shared_lock<std::shared_mutex> lock(interface_mutex);
575 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
576
577 jbyte* addr = env->GetByteArrayElements(address, NULL);
578 if (!addr) {
579 jniThrowIOException(env, EINVAL);
580 return JNI_FALSE;
581 }
582
583 bt_status_t status =
584 sBluetoothHfpClientInterface->connect_audio((const RawAddress*)addr);
585 if (status != BT_STATUS_SUCCESS) {
586 ALOGE("Failed AG audio connection, status: %d", status);
587 }
588 env->ReleaseByteArrayElements(address, addr, 0);
589 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
590 }
591
disconnectAudioNative(JNIEnv * env,jobject object,jbyteArray address)592 static jboolean disconnectAudioNative(JNIEnv* env, jobject object,
593 jbyteArray address) {
594 std::shared_lock<std::shared_mutex> lock(interface_mutex);
595 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
596
597 jbyte* addr = env->GetByteArrayElements(address, NULL);
598 if (!addr) {
599 jniThrowIOException(env, EINVAL);
600 return JNI_FALSE;
601 }
602
603 bt_status_t status =
604 sBluetoothHfpClientInterface->disconnect_audio((const RawAddress*)addr);
605 if (status != BT_STATUS_SUCCESS) {
606 ALOGE("Failed AG audio disconnection, status: %d", status);
607 }
608 env->ReleaseByteArrayElements(address, addr, 0);
609 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
610 }
611
startVoiceRecognitionNative(JNIEnv * env,jobject object,jbyteArray address)612 static jboolean startVoiceRecognitionNative(JNIEnv* env, jobject object,
613 jbyteArray address) {
614 std::shared_lock<std::shared_mutex> lock(interface_mutex);
615 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
616
617 jbyte* addr = env->GetByteArrayElements(address, NULL);
618 if (!addr) {
619 jniThrowIOException(env, EINVAL);
620 return JNI_FALSE;
621 }
622
623 bt_status_t status = sBluetoothHfpClientInterface->start_voice_recognition(
624 (const RawAddress*)addr);
625 if (status != BT_STATUS_SUCCESS) {
626 ALOGE("Failed to start voice recognition, status: %d", status);
627 }
628 env->ReleaseByteArrayElements(address, addr, 0);
629 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
630 }
631
stopVoiceRecognitionNative(JNIEnv * env,jobject object,jbyteArray address)632 static jboolean stopVoiceRecognitionNative(JNIEnv* env, jobject object,
633 jbyteArray address) {
634 std::shared_lock<std::shared_mutex> lock(interface_mutex);
635 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
636
637 jbyte* addr = env->GetByteArrayElements(address, NULL);
638 if (!addr) {
639 jniThrowIOException(env, EINVAL);
640 return JNI_FALSE;
641 }
642
643 bt_status_t status = sBluetoothHfpClientInterface->stop_voice_recognition(
644 (const RawAddress*)addr);
645 if (status != BT_STATUS_SUCCESS) {
646 ALOGE("Failed to stop voice recognition, status: %d", status);
647 }
648 env->ReleaseByteArrayElements(address, addr, 0);
649 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
650 }
651
setVolumeNative(JNIEnv * env,jobject object,jbyteArray address,jint volume_type,jint volume)652 static jboolean setVolumeNative(JNIEnv* env, jobject object, jbyteArray address,
653 jint volume_type, jint volume) {
654 std::shared_lock<std::shared_mutex> lock(interface_mutex);
655 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
656
657 jbyte* addr = env->GetByteArrayElements(address, NULL);
658 if (!addr) {
659 jniThrowIOException(env, EINVAL);
660 return JNI_FALSE;
661 }
662
663 bt_status_t status = sBluetoothHfpClientInterface->volume_control(
664 (const RawAddress*)addr, (bthf_client_volume_type_t)volume_type, volume);
665 if (status != BT_STATUS_SUCCESS) {
666 ALOGE("FAILED to control volume, status: %d", status);
667 }
668 env->ReleaseByteArrayElements(address, addr, 0);
669 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
670 }
671
dialNative(JNIEnv * env,jobject object,jbyteArray address,jstring number_str)672 static jboolean dialNative(JNIEnv* env, jobject object, jbyteArray address,
673 jstring number_str) {
674 std::shared_lock<std::shared_mutex> lock(interface_mutex);
675 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
676
677 jbyte* addr = env->GetByteArrayElements(address, NULL);
678 if (!addr) {
679 jniThrowIOException(env, EINVAL);
680 return JNI_FALSE;
681 }
682
683 const char* number = nullptr;
684 if (number_str != nullptr) {
685 number = env->GetStringUTFChars(number_str, nullptr);
686 }
687 bt_status_t status =
688 sBluetoothHfpClientInterface->dial((const RawAddress*)addr,
689 number == nullptr ? "" : number);
690
691 if (status != BT_STATUS_SUCCESS) {
692 ALOGE("Failed to dial, status: %d", status);
693 }
694 if (number != nullptr) {
695 env->ReleaseStringUTFChars(number_str, number);
696 }
697 env->ReleaseByteArrayElements(address, addr, 0);
698 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
699 }
700
dialMemoryNative(JNIEnv * env,jobject object,jbyteArray address,jint location)701 static jboolean dialMemoryNative(JNIEnv* env, jobject object,
702 jbyteArray address, jint location) {
703 std::shared_lock<std::shared_mutex> lock(interface_mutex);
704 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
705
706 jbyte* addr = env->GetByteArrayElements(address, NULL);
707 if (!addr) {
708 jniThrowIOException(env, EINVAL);
709 return JNI_FALSE;
710 }
711
712 bt_status_t status = sBluetoothHfpClientInterface->dial_memory(
713 (const RawAddress*)addr, (int)location);
714 if (status != BT_STATUS_SUCCESS) {
715 ALOGE("Failed to dial from memory, status: %d", status);
716 }
717
718 env->ReleaseByteArrayElements(address, addr, 0);
719 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
720 }
721
handleCallActionNative(JNIEnv * env,jobject object,jbyteArray address,jint action,jint index)722 static jboolean handleCallActionNative(JNIEnv* env, jobject object,
723 jbyteArray address, jint action,
724 jint index) {
725 std::shared_lock<std::shared_mutex> lock(interface_mutex);
726 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
727
728 jbyte* addr = env->GetByteArrayElements(address, NULL);
729 if (!addr) {
730 jniThrowIOException(env, EINVAL);
731 return JNI_FALSE;
732 }
733
734 bt_status_t status = sBluetoothHfpClientInterface->handle_call_action(
735 (const RawAddress*)addr, (bthf_client_call_action_t)action, (int)index);
736
737 if (status != BT_STATUS_SUCCESS) {
738 ALOGE("Failed to enter private mode, status: %d", status);
739 }
740 env->ReleaseByteArrayElements(address, addr, 0);
741 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
742 }
743
queryCurrentCallsNative(JNIEnv * env,jobject object,jbyteArray address)744 static jboolean queryCurrentCallsNative(JNIEnv* env, jobject object,
745 jbyteArray address) {
746 std::shared_lock<std::shared_mutex> lock(interface_mutex);
747 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
748
749 jbyte* addr = env->GetByteArrayElements(address, NULL);
750 if (!addr) {
751 jniThrowIOException(env, EINVAL);
752 return JNI_FALSE;
753 }
754
755 bt_status_t status = sBluetoothHfpClientInterface->query_current_calls(
756 (const RawAddress*)addr);
757
758 if (status != BT_STATUS_SUCCESS) {
759 ALOGE("Failed to query current calls, status: %d", status);
760 }
761 env->ReleaseByteArrayElements(address, addr, 0);
762 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
763 }
764
queryCurrentOperatorNameNative(JNIEnv * env,jobject object,jbyteArray address)765 static jboolean queryCurrentOperatorNameNative(JNIEnv* env, jobject object,
766 jbyteArray address) {
767 std::shared_lock<std::shared_mutex> lock(interface_mutex);
768 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
769
770 jbyte* addr = env->GetByteArrayElements(address, NULL);
771 if (!addr) {
772 jniThrowIOException(env, EINVAL);
773 return JNI_FALSE;
774 }
775
776 bt_status_t status =
777 sBluetoothHfpClientInterface->query_current_operator_name(
778 (const RawAddress*)addr);
779 if (status != BT_STATUS_SUCCESS) {
780 ALOGE("Failed to query current operator name, status: %d", status);
781 }
782
783 env->ReleaseByteArrayElements(address, addr, 0);
784 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
785 }
786
retrieveSubscriberInfoNative(JNIEnv * env,jobject object,jbyteArray address)787 static jboolean retrieveSubscriberInfoNative(JNIEnv* env, jobject object,
788 jbyteArray address) {
789 std::shared_lock<std::shared_mutex> lock(interface_mutex);
790 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
791
792 jbyte* addr = env->GetByteArrayElements(address, NULL);
793 if (!addr) {
794 jniThrowIOException(env, EINVAL);
795 return JNI_FALSE;
796 }
797
798 bt_status_t status = sBluetoothHfpClientInterface->retrieve_subscriber_info(
799 (const RawAddress*)addr);
800 if (status != BT_STATUS_SUCCESS) {
801 ALOGE("Failed to retrieve subscriber info, status: %d", status);
802 }
803
804 env->ReleaseByteArrayElements(address, addr, 0);
805 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
806 }
807
sendDtmfNative(JNIEnv * env,jobject object,jbyteArray address,jbyte code)808 static jboolean sendDtmfNative(JNIEnv* env, jobject object, jbyteArray address,
809 jbyte code) {
810 std::shared_lock<std::shared_mutex> lock(interface_mutex);
811 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
812
813 jbyte* addr = env->GetByteArrayElements(address, NULL);
814 if (!addr) {
815 jniThrowIOException(env, EINVAL);
816 return JNI_FALSE;
817 }
818
819 bt_status_t status = sBluetoothHfpClientInterface->send_dtmf(
820 (const RawAddress*)addr, (char)code);
821 if (status != BT_STATUS_SUCCESS) {
822 ALOGE("Failed to send DTMF, status: %d", status);
823 }
824
825 env->ReleaseByteArrayElements(address, addr, 0);
826 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
827 }
828
requestLastVoiceTagNumberNative(JNIEnv * env,jobject object,jbyteArray address)829 static jboolean requestLastVoiceTagNumberNative(JNIEnv* env, jobject object,
830 jbyteArray address) {
831 std::shared_lock<std::shared_mutex> lock(interface_mutex);
832 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
833
834 jbyte* addr = env->GetByteArrayElements(address, NULL);
835 if (!addr) {
836 jniThrowIOException(env, EINVAL);
837 return JNI_FALSE;
838 }
839
840 bt_status_t status =
841 sBluetoothHfpClientInterface->request_last_voice_tag_number(
842 (const RawAddress*)addr);
843
844 if (status != BT_STATUS_SUCCESS) {
845 ALOGE("Failed to request last Voice Tag number, status: %d", status);
846 }
847
848 env->ReleaseByteArrayElements(address, addr, 0);
849 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
850 }
851
sendATCmdNative(JNIEnv * env,jobject object,jbyteArray address,jint cmd,jint val1,jint val2,jstring arg_str)852 static jboolean sendATCmdNative(JNIEnv* env, jobject object, jbyteArray address,
853 jint cmd, jint val1, jint val2,
854 jstring arg_str) {
855 std::shared_lock<std::shared_mutex> lock(interface_mutex);
856 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
857
858 jbyte* addr = env->GetByteArrayElements(address, NULL);
859 if (!addr) {
860 jniThrowIOException(env, EINVAL);
861 return JNI_FALSE;
862 }
863 const char* arg = NULL;
864 if (arg_str != NULL) {
865 arg = env->GetStringUTFChars(arg_str, NULL);
866 }
867
868 bt_status_t status = sBluetoothHfpClientInterface->send_at_cmd(
869 (const RawAddress*)addr, cmd, val1, val2, arg);
870
871 if (status != BT_STATUS_SUCCESS) {
872 ALOGE("Failed to send cmd, status: %d", status);
873 }
874
875 if (arg != NULL) {
876 env->ReleaseStringUTFChars(arg_str, arg);
877 }
878
879 env->ReleaseByteArrayElements(address, addr, 0);
880 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
881 }
882
sendAndroidAtNative(JNIEnv * env,jobject object,jbyteArray address,jstring arg_str)883 static jboolean sendAndroidAtNative(JNIEnv* env, jobject object,
884 jbyteArray address, jstring arg_str) {
885 std::shared_lock<std::shared_mutex> lock(interface_mutex);
886 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
887
888 jbyte* addr = env->GetByteArrayElements(address, NULL);
889 if (!addr) {
890 jniThrowIOException(env, EINVAL);
891 return JNI_FALSE;
892 }
893
894 const char* arg = NULL;
895 if (arg_str != NULL) {
896 arg = env->GetStringUTFChars(arg_str, NULL);
897 }
898
899 bt_status_t status = sBluetoothHfpClientInterface->send_android_at(
900 (const RawAddress*)addr, arg);
901
902 if (status != BT_STATUS_SUCCESS) {
903 ALOGE("FAILED to control volume, status: %d", status);
904 }
905
906 if (arg != NULL) {
907 env->ReleaseStringUTFChars(arg_str, arg);
908 }
909
910 env->ReleaseByteArrayElements(address, addr, 0);
911 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
912 }
913
914 static JNINativeMethod sMethods[] = {
915 {"classInitNative", "()V", (void*)classInitNative},
916 {"initializeNative", "()V", (void*)initializeNative},
917 {"cleanupNative", "()V", (void*)cleanupNative},
918 {"connectNative", "([B)Z", (void*)connectNative},
919 {"disconnectNative", "([B)Z", (void*)disconnectNative},
920 {"connectAudioNative", "([B)Z", (void*)connectAudioNative},
921 {"disconnectAudioNative", "([B)Z", (void*)disconnectAudioNative},
922 {"startVoiceRecognitionNative", "([B)Z",
923 (void*)startVoiceRecognitionNative},
924 {"stopVoiceRecognitionNative", "([B)Z", (void*)stopVoiceRecognitionNative},
925 {"setVolumeNative", "([BII)Z", (void*)setVolumeNative},
926 {"dialNative", "([BLjava/lang/String;)Z", (void*)dialNative},
927 {"dialMemoryNative", "([BI)Z", (void*)dialMemoryNative},
928 {"handleCallActionNative", "([BII)Z", (void*)handleCallActionNative},
929 {"queryCurrentCallsNative", "([B)Z", (void*)queryCurrentCallsNative},
930 {"queryCurrentOperatorNameNative", "([B)Z",
931 (void*)queryCurrentOperatorNameNative},
932 {"retrieveSubscriberInfoNative", "([B)Z",
933 (void*)retrieveSubscriberInfoNative},
934 {"sendDtmfNative", "([BB)Z", (void*)sendDtmfNative},
935 {"requestLastVoiceTagNumberNative", "([B)Z",
936 (void*)requestLastVoiceTagNumberNative},
937 {"sendATCmdNative", "([BIIILjava/lang/String;)Z", (void*)sendATCmdNative},
938 {"sendAndroidAtNative", "([BLjava/lang/String;)Z",
939 (void*)sendAndroidAtNative},
940 };
941
register_com_android_bluetooth_hfpclient(JNIEnv * env)942 int register_com_android_bluetooth_hfpclient(JNIEnv* env) {
943 return jniRegisterNativeMethods(
944 env, "com/android/bluetooth/hfpclient/NativeInterface",
945 sMethods, NELEM(sMethods));
946 }
947
948 } /* namespace android */
949