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 <shared_mutex>
21
22 #include "com_android_bluetooth.h"
23 #include "hardware/bt_hf_client.h"
24 #include "os/logging/log_adapter.h"
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 log::error("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 log::debug("state {} peer_feat {} chld_feat {}", 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 log::error("name is not a valid UTF string.");
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 log::debug("callsetup_cb bdaddr {}", *bd_addr);
205
206 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallSetup,
207 (jint)callsetup, addr.get());
208 }
209
callheld_cb(const RawAddress * bd_addr,bthf_client_callheld_t callheld)210 static void callheld_cb(const RawAddress* bd_addr,
211 bthf_client_callheld_t callheld) {
212 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
213 CallbackEnv sCallbackEnv(__func__);
214 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
215
216 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
217 if (!addr.get()) return;
218
219 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallHeld, (jint)callheld,
220 addr.get());
221 }
222
resp_and_hold_cb(const RawAddress * bd_addr,bthf_client_resp_and_hold_t resp_and_hold)223 static void resp_and_hold_cb(const RawAddress* bd_addr,
224 bthf_client_resp_and_hold_t resp_and_hold) {
225 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
226 CallbackEnv sCallbackEnv(__func__);
227 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
228
229 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
230 if (!addr.get()) return;
231
232 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRespAndHold,
233 (jint)resp_and_hold, addr.get());
234 }
235
clip_cb(const RawAddress * bd_addr,const char * number)236 static void clip_cb(const RawAddress* bd_addr, const char* number) {
237 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
238 CallbackEnv sCallbackEnv(__func__);
239 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
240
241 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
242 if (!addr.get()) return;
243
244 const char null_str[] = "";
245 if (!sCallbackEnv.isValidUtf(number)) {
246 log::error("number is not a valid UTF string.");
247 number = null_str;
248 }
249
250 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
251 sCallbackEnv->NewStringUTF(number));
252 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClip, js_number.get(),
253 addr.get());
254 }
255
call_waiting_cb(const RawAddress * bd_addr,const char * number)256 static void call_waiting_cb(const RawAddress* bd_addr, const char* number) {
257 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
258 CallbackEnv sCallbackEnv(__func__);
259 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
260
261 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
262 if (!addr.get()) return;
263
264 const char null_str[] = "";
265 if (!sCallbackEnv.isValidUtf(number)) {
266 log::error("number is not a valid UTF string.");
267 number = null_str;
268 }
269
270 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
271 sCallbackEnv->NewStringUTF(number));
272 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallWaiting,
273 js_number.get(), addr.get());
274 }
275
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)276 static void current_calls_cb(const RawAddress* bd_addr, int index,
277 bthf_client_call_direction_t dir,
278 bthf_client_call_state_t state,
279 bthf_client_call_mpty_type_t mpty,
280 const char* number) {
281 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
282 CallbackEnv sCallbackEnv(__func__);
283 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
284
285 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
286 if (!addr.get()) return;
287
288 const char null_str[] = "";
289 if (!sCallbackEnv.isValidUtf(number)) {
290 log::error("number is not a valid UTF string.");
291 number = null_str;
292 }
293
294 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
295 sCallbackEnv->NewStringUTF(number));
296 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCurrentCalls, index, dir,
297 state, mpty, js_number.get(), addr.get());
298 }
299
volume_change_cb(const RawAddress * bd_addr,bthf_client_volume_type_t type,int volume)300 static void volume_change_cb(const RawAddress* bd_addr,
301 bthf_client_volume_type_t type, int volume) {
302 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
303 CallbackEnv sCallbackEnv(__func__);
304 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
305
306 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
307 if (!addr.get()) return;
308 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeChange, (jint)type,
309 (jint)volume, addr.get());
310 }
311
cmd_complete_cb(const RawAddress * bd_addr,bthf_client_cmd_complete_t type,int cme)312 static void cmd_complete_cb(const RawAddress* bd_addr,
313 bthf_client_cmd_complete_t type, int cme) {
314 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
315 CallbackEnv sCallbackEnv(__func__);
316 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
317
318 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
319 if (!addr.get()) return;
320 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCmdResult, (jint)type,
321 (jint)cme, addr.get());
322 }
323
subscriber_info_cb(const RawAddress * bd_addr,const char * name,bthf_client_subscriber_service_type_t type)324 static void subscriber_info_cb(const RawAddress* bd_addr, const char* name,
325 bthf_client_subscriber_service_type_t type) {
326 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
327 CallbackEnv sCallbackEnv(__func__);
328 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
329
330 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
331 if (!addr.get()) return;
332
333 const char null_str[] = "";
334 if (!sCallbackEnv.isValidUtf(name)) {
335 log::error("name is not a valid UTF string.");
336 name = null_str;
337 }
338
339 ScopedLocalRef<jstring> js_name(sCallbackEnv.get(),
340 sCallbackEnv->NewStringUTF(name));
341 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSubscriberInfo,
342 js_name.get(), (jint)type, addr.get());
343 }
344
in_band_ring_cb(const RawAddress * bd_addr,bthf_client_in_band_ring_state_t in_band)345 static void in_band_ring_cb(const RawAddress* bd_addr,
346 bthf_client_in_band_ring_state_t in_band) {
347 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
348 CallbackEnv sCallbackEnv(__func__);
349 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
350
351 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
352 if (!addr.get()) return;
353 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onInBandRing,
354 (jint)in_band, addr.get());
355 }
356
last_voice_tag_number_cb(const RawAddress * bd_addr,const char * number)357 static void last_voice_tag_number_cb(const RawAddress* bd_addr,
358 const char* number) {
359 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
360 CallbackEnv sCallbackEnv(__func__);
361 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
362
363 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
364 if (!addr.get()) return;
365
366 const char null_str[] = "";
367 if (!sCallbackEnv.isValidUtf(number)) {
368 log::error("number is not a valid UTF string.");
369 number = null_str;
370 }
371
372 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
373 sCallbackEnv->NewStringUTF(number));
374 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onLastVoiceTagNumber,
375 js_number.get(), addr.get());
376 }
377
ring_indication_cb(const RawAddress * bd_addr)378 static void ring_indication_cb(const RawAddress* bd_addr) {
379 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
380 CallbackEnv sCallbackEnv(__func__);
381 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
382
383 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
384 if (!addr.get()) return;
385 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRingIndication,
386 addr.get());
387 }
388
unknown_event_cb(const RawAddress * bd_addr,const char * eventString)389 static void unknown_event_cb(const RawAddress* bd_addr,
390 const char* eventString) {
391 std::shared_lock<std::shared_mutex> lock(callbacks_mutex);
392 CallbackEnv sCallbackEnv(__func__);
393 if (!sCallbackEnv.valid() || mCallbacksObj == NULL) return;
394
395 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
396 if (!addr.get()) return;
397
398 ScopedLocalRef<jstring> js_event(sCallbackEnv.get(),
399 sCallbackEnv->NewStringUTF(eventString));
400 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onUnknownEvent,
401 js_event.get(), addr.get());
402 }
403
404 static bthf_client_callbacks_t sBluetoothHfpClientCallbacks = {
405 sizeof(sBluetoothHfpClientCallbacks),
406 connection_state_cb,
407 audio_state_cb,
408 vr_cmd_cb,
409 network_state_cb,
410 network_roaming_cb,
411 network_signal_cb,
412 battery_level_cb,
413 current_operator_cb,
414 call_cb,
415 callsetup_cb,
416 callheld_cb,
417 resp_and_hold_cb,
418 clip_cb,
419 call_waiting_cb,
420 current_calls_cb,
421 volume_change_cb,
422 cmd_complete_cb,
423 subscriber_info_cb,
424 in_band_ring_cb,
425 last_voice_tag_number_cb,
426 ring_indication_cb,
427 unknown_event_cb,
428 };
429
initializeNative(JNIEnv * env,jobject object)430 static void initializeNative(JNIEnv* env, jobject object) {
431 log::debug("HfpClient");
432 std::unique_lock<std::shared_mutex> interface_lock(interface_mutex);
433 std::unique_lock<std::shared_mutex> callbacks_lock(callbacks_mutex);
434
435 const bt_interface_t* btInf = getBluetoothInterface();
436 if (btInf == NULL) {
437 log::error("Bluetooth module is not loaded");
438 return;
439 }
440
441 if (sBluetoothHfpClientInterface != NULL) {
442 log::warn("Cleaning up Bluetooth HFP Client Interface before initializing");
443 sBluetoothHfpClientInterface->cleanup();
444 sBluetoothHfpClientInterface = NULL;
445 }
446
447 if (mCallbacksObj != NULL) {
448 log::warn("Cleaning up Bluetooth HFP Client callback object");
449 env->DeleteGlobalRef(mCallbacksObj);
450 mCallbacksObj = NULL;
451 }
452
453 sBluetoothHfpClientInterface =
454 (bthf_client_interface_t*)btInf->get_profile_interface(
455 BT_PROFILE_HANDSFREE_CLIENT_ID);
456 if (sBluetoothHfpClientInterface == NULL) {
457 log::error("Failed to get Bluetooth HFP Client Interface");
458 return;
459 }
460
461 bt_status_t status =
462 sBluetoothHfpClientInterface->init(&sBluetoothHfpClientCallbacks);
463 if (status != BT_STATUS_SUCCESS) {
464 log::error("Failed to initialize Bluetooth HFP Client, status: {}",
465 bt_status_text(status));
466 sBluetoothHfpClientInterface = NULL;
467 return;
468 }
469
470 mCallbacksObj = env->NewGlobalRef(object);
471 }
472
cleanupNative(JNIEnv * env,jobject)473 static void cleanupNative(JNIEnv* env, jobject /* object */) {
474 std::unique_lock<std::shared_mutex> interface_lock(interface_mutex);
475 std::unique_lock<std::shared_mutex> callbacks_lock(callbacks_mutex);
476
477 const bt_interface_t* btInf = getBluetoothInterface();
478 if (btInf == NULL) {
479 log::error("Bluetooth module is not loaded");
480 return;
481 }
482
483 if (sBluetoothHfpClientInterface != NULL) {
484 log::warn("Cleaning up Bluetooth HFP Client Interface...");
485 sBluetoothHfpClientInterface->cleanup();
486 sBluetoothHfpClientInterface = NULL;
487 }
488
489 if (mCallbacksObj != NULL) {
490 log::warn("Cleaning up Bluetooth HFP Client callback object");
491 env->DeleteGlobalRef(mCallbacksObj);
492 mCallbacksObj = NULL;
493 }
494 }
495
connectNative(JNIEnv * env,jobject,jbyteArray address)496 static jboolean connectNative(JNIEnv* env, jobject /* object */,
497 jbyteArray address) {
498 std::shared_lock<std::shared_mutex> lock(interface_mutex);
499 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
500
501 jbyte* addr = env->GetByteArrayElements(address, NULL);
502 if (!addr) {
503 jniThrowIOException(env, EINVAL);
504 return JNI_FALSE;
505 }
506
507 bt_status_t status =
508 sBluetoothHfpClientInterface->connect((const RawAddress*)addr);
509 if (status != BT_STATUS_SUCCESS) {
510 log::error("Failed AG connection, status: {}", bt_status_text(status));
511 }
512 env->ReleaseByteArrayElements(address, addr, 0);
513 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
514 }
515
disconnectNative(JNIEnv * env,jobject,jbyteArray address)516 static jboolean disconnectNative(JNIEnv* env, jobject /* object */,
517 jbyteArray address) {
518 std::shared_lock<std::shared_mutex> lock(interface_mutex);
519 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
520
521 jbyte* addr = env->GetByteArrayElements(address, NULL);
522 if (!addr) {
523 jniThrowIOException(env, EINVAL);
524 return JNI_FALSE;
525 }
526
527 bt_status_t status =
528 sBluetoothHfpClientInterface->disconnect((const RawAddress*)addr);
529 if (status != BT_STATUS_SUCCESS) {
530 log::error("Failed AG disconnection, status: {}", bt_status_text(status));
531 }
532 env->ReleaseByteArrayElements(address, addr, 0);
533 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
534 }
535
connectAudioNative(JNIEnv * env,jobject,jbyteArray address)536 static jboolean connectAudioNative(JNIEnv* env, jobject /* object */,
537 jbyteArray address) {
538 std::shared_lock<std::shared_mutex> lock(interface_mutex);
539 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
540
541 jbyte* addr = env->GetByteArrayElements(address, NULL);
542 if (!addr) {
543 jniThrowIOException(env, EINVAL);
544 return JNI_FALSE;
545 }
546
547 bt_status_t status =
548 sBluetoothHfpClientInterface->connect_audio((const RawAddress*)addr);
549 if (status != BT_STATUS_SUCCESS) {
550 log::error("Failed AG audio connection, status: {}",
551 bt_status_text(status));
552 }
553 env->ReleaseByteArrayElements(address, addr, 0);
554 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
555 }
556
disconnectAudioNative(JNIEnv * env,jobject,jbyteArray address)557 static jboolean disconnectAudioNative(JNIEnv* env, jobject /* object */,
558 jbyteArray address) {
559 std::shared_lock<std::shared_mutex> lock(interface_mutex);
560 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
561
562 jbyte* addr = env->GetByteArrayElements(address, NULL);
563 if (!addr) {
564 jniThrowIOException(env, EINVAL);
565 return JNI_FALSE;
566 }
567
568 bt_status_t status =
569 sBluetoothHfpClientInterface->disconnect_audio((const RawAddress*)addr);
570 if (status != BT_STATUS_SUCCESS) {
571 log::error("Failed AG audio disconnection, status: {}",
572 bt_status_text(status));
573 }
574 env->ReleaseByteArrayElements(address, addr, 0);
575 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
576 }
577
startVoiceRecognitionNative(JNIEnv * env,jobject,jbyteArray address)578 static jboolean startVoiceRecognitionNative(JNIEnv* env, jobject /* object */,
579 jbyteArray address) {
580 std::shared_lock<std::shared_mutex> lock(interface_mutex);
581 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
582
583 jbyte* addr = env->GetByteArrayElements(address, NULL);
584 if (!addr) {
585 jniThrowIOException(env, EINVAL);
586 return JNI_FALSE;
587 }
588
589 bt_status_t status = sBluetoothHfpClientInterface->start_voice_recognition(
590 (const RawAddress*)addr);
591 if (status != BT_STATUS_SUCCESS) {
592 log::error("Failed to start voice recognition, status: {}",
593 bt_status_text(status));
594 }
595 env->ReleaseByteArrayElements(address, addr, 0);
596 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
597 }
598
stopVoiceRecognitionNative(JNIEnv * env,jobject,jbyteArray address)599 static jboolean stopVoiceRecognitionNative(JNIEnv* env, jobject /* object */,
600 jbyteArray address) {
601 std::shared_lock<std::shared_mutex> lock(interface_mutex);
602 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
603
604 jbyte* addr = env->GetByteArrayElements(address, NULL);
605 if (!addr) {
606 jniThrowIOException(env, EINVAL);
607 return JNI_FALSE;
608 }
609
610 bt_status_t status = sBluetoothHfpClientInterface->stop_voice_recognition(
611 (const RawAddress*)addr);
612 if (status != BT_STATUS_SUCCESS) {
613 log::error("Failed to stop voice recognition, status: {}",
614 bt_status_text(status));
615 }
616 env->ReleaseByteArrayElements(address, addr, 0);
617 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
618 }
619
setVolumeNative(JNIEnv * env,jobject,jbyteArray address,jint volume_type,jint volume)620 static jboolean setVolumeNative(JNIEnv* env, jobject /* object */,
621 jbyteArray address, jint volume_type,
622 jint volume) {
623 std::shared_lock<std::shared_mutex> lock(interface_mutex);
624 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
625
626 jbyte* addr = env->GetByteArrayElements(address, NULL);
627 if (!addr) {
628 jniThrowIOException(env, EINVAL);
629 return JNI_FALSE;
630 }
631
632 bt_status_t status = sBluetoothHfpClientInterface->volume_control(
633 (const RawAddress*)addr, (bthf_client_volume_type_t)volume_type, volume);
634 if (status != BT_STATUS_SUCCESS) {
635 log::error("FAILED to control volume, status: {}", bt_status_text(status));
636 }
637 env->ReleaseByteArrayElements(address, addr, 0);
638 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
639 }
640
dialNative(JNIEnv * env,jobject,jbyteArray address,jstring number_str)641 static jboolean dialNative(JNIEnv* env, jobject /* object */,
642 jbyteArray address, jstring number_str) {
643 std::shared_lock<std::shared_mutex> lock(interface_mutex);
644 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
645
646 jbyte* addr = env->GetByteArrayElements(address, NULL);
647 if (!addr) {
648 jniThrowIOException(env, EINVAL);
649 return JNI_FALSE;
650 }
651
652 const char* number = nullptr;
653 if (number_str != nullptr) {
654 number = env->GetStringUTFChars(number_str, nullptr);
655 }
656 bt_status_t status =
657 sBluetoothHfpClientInterface->dial((const RawAddress*)addr,
658 number == nullptr ? "" : number);
659
660 if (status != BT_STATUS_SUCCESS) {
661 log::error("Failed to dial, status: {}", bt_status_text(status));
662 }
663 if (number != nullptr) {
664 env->ReleaseStringUTFChars(number_str, number);
665 }
666 env->ReleaseByteArrayElements(address, addr, 0);
667 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
668 }
669
dialMemoryNative(JNIEnv * env,jobject,jbyteArray address,jint location)670 static jboolean dialMemoryNative(JNIEnv* env, jobject /* object */,
671 jbyteArray address, jint location) {
672 std::shared_lock<std::shared_mutex> lock(interface_mutex);
673 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
674
675 jbyte* addr = env->GetByteArrayElements(address, NULL);
676 if (!addr) {
677 jniThrowIOException(env, EINVAL);
678 return JNI_FALSE;
679 }
680
681 bt_status_t status = sBluetoothHfpClientInterface->dial_memory(
682 (const RawAddress*)addr, (int)location);
683 if (status != BT_STATUS_SUCCESS) {
684 log::error("Failed to dial from memory, status: {}",
685 bt_status_text(status));
686 }
687
688 env->ReleaseByteArrayElements(address, addr, 0);
689 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
690 }
691
handleCallActionNative(JNIEnv * env,jobject,jbyteArray address,jint action,jint index)692 static jboolean handleCallActionNative(JNIEnv* env, jobject /* object */,
693 jbyteArray address, jint action,
694 jint index) {
695 std::shared_lock<std::shared_mutex> lock(interface_mutex);
696 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
697
698 jbyte* addr = env->GetByteArrayElements(address, NULL);
699 if (!addr) {
700 jniThrowIOException(env, EINVAL);
701 return JNI_FALSE;
702 }
703
704 bt_status_t status = sBluetoothHfpClientInterface->handle_call_action(
705 (const RawAddress*)addr, (bthf_client_call_action_t)action, (int)index);
706
707 if (status != BT_STATUS_SUCCESS) {
708 log::error("Failed to enter private mode, status: {}",
709 bt_status_text(status));
710 }
711 env->ReleaseByteArrayElements(address, addr, 0);
712 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
713 }
714
queryCurrentCallsNative(JNIEnv * env,jobject,jbyteArray address)715 static jboolean queryCurrentCallsNative(JNIEnv* env, jobject /* object */,
716 jbyteArray address) {
717 std::shared_lock<std::shared_mutex> lock(interface_mutex);
718 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
719
720 jbyte* addr = env->GetByteArrayElements(address, NULL);
721 if (!addr) {
722 jniThrowIOException(env, EINVAL);
723 return JNI_FALSE;
724 }
725
726 bt_status_t status = sBluetoothHfpClientInterface->query_current_calls(
727 (const RawAddress*)addr);
728
729 if (status != BT_STATUS_SUCCESS) {
730 log::error("Failed to query current calls, status: {}",
731 bt_status_text(status));
732 }
733 env->ReleaseByteArrayElements(address, addr, 0);
734 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
735 }
736
queryCurrentOperatorNameNative(JNIEnv * env,jobject,jbyteArray address)737 static jboolean queryCurrentOperatorNameNative(JNIEnv* env,
738 jobject /* object */,
739 jbyteArray address) {
740 std::shared_lock<std::shared_mutex> lock(interface_mutex);
741 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
742
743 jbyte* addr = env->GetByteArrayElements(address, NULL);
744 if (!addr) {
745 jniThrowIOException(env, EINVAL);
746 return JNI_FALSE;
747 }
748
749 bt_status_t status =
750 sBluetoothHfpClientInterface->query_current_operator_name(
751 (const RawAddress*)addr);
752 if (status != BT_STATUS_SUCCESS) {
753 log::error("Failed to query current operator name, status: {}",
754 bt_status_text(status));
755 }
756
757 env->ReleaseByteArrayElements(address, addr, 0);
758 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
759 }
760
retrieveSubscriberInfoNative(JNIEnv * env,jobject,jbyteArray address)761 static jboolean retrieveSubscriberInfoNative(JNIEnv* env, jobject /* object */,
762 jbyteArray address) {
763 std::shared_lock<std::shared_mutex> lock(interface_mutex);
764 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
765
766 jbyte* addr = env->GetByteArrayElements(address, NULL);
767 if (!addr) {
768 jniThrowIOException(env, EINVAL);
769 return JNI_FALSE;
770 }
771
772 bt_status_t status = sBluetoothHfpClientInterface->retrieve_subscriber_info(
773 (const RawAddress*)addr);
774 if (status != BT_STATUS_SUCCESS) {
775 log::error("Failed to retrieve subscriber info, status: {}",
776 bt_status_text(status));
777 }
778
779 env->ReleaseByteArrayElements(address, addr, 0);
780 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
781 }
782
sendDtmfNative(JNIEnv * env,jobject,jbyteArray address,jbyte code)783 static jboolean sendDtmfNative(JNIEnv* env, jobject /* object */,
784 jbyteArray address, jbyte code) {
785 std::shared_lock<std::shared_mutex> lock(interface_mutex);
786 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
787
788 jbyte* addr = env->GetByteArrayElements(address, NULL);
789 if (!addr) {
790 jniThrowIOException(env, EINVAL);
791 return JNI_FALSE;
792 }
793
794 bt_status_t status = sBluetoothHfpClientInterface->send_dtmf(
795 (const RawAddress*)addr, (char)code);
796 if (status != BT_STATUS_SUCCESS) {
797 log::error("Failed to send DTMF, status: {}", bt_status_text(status));
798 }
799
800 env->ReleaseByteArrayElements(address, addr, 0);
801 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
802 }
803
requestLastVoiceTagNumberNative(JNIEnv * env,jobject,jbyteArray address)804 static jboolean requestLastVoiceTagNumberNative(JNIEnv* env,
805 jobject /* object */,
806 jbyteArray address) {
807 std::shared_lock<std::shared_mutex> lock(interface_mutex);
808 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
809
810 jbyte* addr = env->GetByteArrayElements(address, NULL);
811 if (!addr) {
812 jniThrowIOException(env, EINVAL);
813 return JNI_FALSE;
814 }
815
816 bt_status_t status =
817 sBluetoothHfpClientInterface->request_last_voice_tag_number(
818 (const RawAddress*)addr);
819
820 if (status != BT_STATUS_SUCCESS) {
821 log::error("Failed to request last Voice Tag number, status: {}",
822 bt_status_text(status));
823 }
824
825 env->ReleaseByteArrayElements(address, addr, 0);
826 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
827 }
828
sendATCmdNative(JNIEnv * env,jobject,jbyteArray address,jint cmd,jint val1,jint val2,jstring arg_str)829 static jboolean sendATCmdNative(JNIEnv* env, jobject /* object */,
830 jbyteArray address, jint cmd, jint val1,
831 jint val2, jstring arg_str) {
832 std::shared_lock<std::shared_mutex> lock(interface_mutex);
833 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
834
835 jbyte* addr = env->GetByteArrayElements(address, NULL);
836 if (!addr) {
837 jniThrowIOException(env, EINVAL);
838 return JNI_FALSE;
839 }
840 const char* arg = NULL;
841 if (arg_str != NULL) {
842 arg = env->GetStringUTFChars(arg_str, NULL);
843 }
844
845 bt_status_t status = sBluetoothHfpClientInterface->send_at_cmd(
846 (const RawAddress*)addr, cmd, val1, val2, arg);
847
848 if (status != BT_STATUS_SUCCESS) {
849 log::error("Failed to send cmd, status: {}", bt_status_text(status));
850 }
851
852 if (arg != NULL) {
853 env->ReleaseStringUTFChars(arg_str, arg);
854 }
855
856 env->ReleaseByteArrayElements(address, addr, 0);
857 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
858 }
859
sendAndroidAtNative(JNIEnv * env,jobject,jbyteArray address,jstring arg_str)860 static jboolean sendAndroidAtNative(JNIEnv* env, jobject /* object */,
861 jbyteArray address, jstring arg_str) {
862 std::shared_lock<std::shared_mutex> lock(interface_mutex);
863 if (!sBluetoothHfpClientInterface) return JNI_FALSE;
864
865 jbyte* addr = env->GetByteArrayElements(address, NULL);
866 if (!addr) {
867 jniThrowIOException(env, EINVAL);
868 return JNI_FALSE;
869 }
870
871 const char* arg = NULL;
872 if (arg_str != NULL) {
873 arg = env->GetStringUTFChars(arg_str, NULL);
874 }
875
876 bt_status_t status = sBluetoothHfpClientInterface->send_android_at(
877 (const RawAddress*)addr, arg);
878
879 if (status != BT_STATUS_SUCCESS) {
880 log::error("FAILED to control volume, status: {}", bt_status_text(status));
881 }
882
883 if (arg != NULL) {
884 env->ReleaseStringUTFChars(arg_str, arg);
885 }
886
887 env->ReleaseByteArrayElements(address, addr, 0);
888 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
889 }
890
register_com_android_bluetooth_hfpclient(JNIEnv * env)891 int register_com_android_bluetooth_hfpclient(JNIEnv* env) {
892 const JNINativeMethod methods[] = {
893 {"initializeNative", "()V", (void*)initializeNative},
894 {"cleanupNative", "()V", (void*)cleanupNative},
895 {"connectNative", "([B)Z", (void*)connectNative},
896 {"disconnectNative", "([B)Z", (void*)disconnectNative},
897 {"connectAudioNative", "([B)Z", (void*)connectAudioNative},
898 {"disconnectAudioNative", "([B)Z", (void*)disconnectAudioNative},
899 {"startVoiceRecognitionNative", "([B)Z",
900 (void*)startVoiceRecognitionNative},
901 {"stopVoiceRecognitionNative", "([B)Z",
902 (void*)stopVoiceRecognitionNative},
903 {"setVolumeNative", "([BII)Z", (void*)setVolumeNative},
904 {"dialNative", "([BLjava/lang/String;)Z", (void*)dialNative},
905 {"dialMemoryNative", "([BI)Z", (void*)dialMemoryNative},
906 {"handleCallActionNative", "([BII)Z", (void*)handleCallActionNative},
907 {"queryCurrentCallsNative", "([B)Z", (void*)queryCurrentCallsNative},
908 {"queryCurrentOperatorNameNative", "([B)Z",
909 (void*)queryCurrentOperatorNameNative},
910 {"retrieveSubscriberInfoNative", "([B)Z",
911 (void*)retrieveSubscriberInfoNative},
912 {"sendDtmfNative", "([BB)Z", (void*)sendDtmfNative},
913 {"requestLastVoiceTagNumberNative", "([B)Z",
914 (void*)requestLastVoiceTagNumberNative},
915 {"sendATCmdNative", "([BIIILjava/lang/String;)Z", (void*)sendATCmdNative},
916 {"sendAndroidAtNative", "([BLjava/lang/String;)Z",
917 (void*)sendAndroidAtNative},
918 };
919 const int result = REGISTER_NATIVE_METHODS(
920 env, "com/android/bluetooth/hfpclient/NativeInterface", methods);
921 if (result != 0) {
922 return result;
923 }
924
925 const JNIJavaMethod javaMethods[] = {
926 {"onConnectionStateChanged", "(III[B)V",
927 &method_onConnectionStateChanged},
928 {"onAudioStateChanged", "(I[B)V", &method_onAudioStateChanged},
929 {"onVrStateChanged", "(I[B)V", &method_onVrStateChanged},
930 {"onNetworkState", "(I[B)V", &method_onNetworkState},
931 {"onNetworkRoaming", "(I[B)V", &method_onNetworkRoaming},
932 {"onNetworkSignal", "(I[B)V", &method_onNetworkSignal},
933 {"onBatteryLevel", "(I[B)V", &method_onBatteryLevel},
934 {"onCurrentOperator", "(Ljava/lang/String;[B)V",
935 &method_onCurrentOperator},
936 {"onCall", "(I[B)V", &method_onCall},
937 {"onCallSetup", "(I[B)V", &method_onCallSetup},
938 {"onCallHeld", "(I[B)V", &method_onCallHeld},
939 {"onRespAndHold", "(I[B)V", &method_onRespAndHold},
940 {"onClip", "(Ljava/lang/String;[B)V", &method_onClip},
941 {"onCallWaiting", "(Ljava/lang/String;[B)V", &method_onCallWaiting},
942 {"onCurrentCalls", "(IIIILjava/lang/String;[B)V", &method_onCurrentCalls},
943 {"onVolumeChange", "(II[B)V", &method_onVolumeChange},
944 {"onCmdResult", "(II[B)V", &method_onCmdResult},
945 {"onSubscriberInfo", "(Ljava/lang/String;I[B)V",
946 &method_onSubscriberInfo},
947 {"onInBandRing", "(I[B)V", &method_onInBandRing},
948 {"onLastVoiceTagNumber", "(Ljava/lang/String;[B)V",
949 &method_onLastVoiceTagNumber},
950 {"onRingIndication", "([B)V", &method_onRingIndication},
951 {"onUnknownEvent", "(Ljava/lang/String;[B)V", &method_onUnknownEvent},
952 };
953 GET_JAVA_METHODS(env, "com/android/bluetooth/hfpclient/NativeInterface",
954 javaMethods);
955
956 return 0;
957 }
958
959 } /* namespace android */
960