1 /* 2 ** Copyright 2006, 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 "BluetoothAudioGateway.cpp" 18 19 #include "android_bluetooth_common.h" 20 #include "android_bluetooth_c.h" 21 #include "android_runtime/AndroidRuntime.h" 22 #include "JNIHelp.h" 23 #include "jni.h" 24 #include "utils/Log.h" 25 #include "utils/misc.h" 26 27 #define USE_ACCEPT_DIRECTLY (0) 28 #define USE_SELECT (0) /* 1 for select(), 0 for poll(); used only when 29 USE_ACCEPT_DIRECTLY == 0 */ 30 31 #include <stdio.h> 32 #include <string.h> 33 #include <stdlib.h> 34 #include <errno.h> 35 #include <unistd.h> 36 #include <fcntl.h> 37 #include <sys/socket.h> 38 #include <sys/time.h> 39 #include <sys/types.h> 40 #include <unistd.h> 41 #include <fcntl.h> 42 #include <sys/uio.h> 43 #include <ctype.h> 44 45 #if USE_SELECT 46 #include <sys/select.h> 47 #else 48 #include <sys/poll.h> 49 #endif 50 51 #ifdef HAVE_BLUETOOTH 52 #include <bluetooth/bluetooth.h> 53 #include <bluetooth/rfcomm.h> 54 #include <bluetooth/sco.h> 55 #endif 56 57 namespace android { 58 59 #ifdef HAVE_BLUETOOTH 60 static jfieldID field_mNativeData; 61 /* in */ 62 static jfieldID field_mHandsfreeAgRfcommChannel; 63 static jfieldID field_mHeadsetAgRfcommChannel; 64 /* out */ 65 static jfieldID field_mTimeoutRemainingMs; /* out */ 66 67 static jfieldID field_mConnectingHeadsetAddress; 68 static jfieldID field_mConnectingHeadsetRfcommChannel; /* -1 when not connected */ 69 static jfieldID field_mConnectingHeadsetSocketFd; 70 71 static jfieldID field_mConnectingHandsfreeAddress; 72 static jfieldID field_mConnectingHandsfreeRfcommChannel; /* -1 when not connected */ 73 static jfieldID field_mConnectingHandsfreeSocketFd; 74 75 76 typedef struct { 77 int hcidev; 78 int hf_ag_rfcomm_channel; 79 int hs_ag_rfcomm_channel; 80 int hf_ag_rfcomm_sock; 81 int hs_ag_rfcomm_sock; 82 } native_data_t; 83 84 static inline native_data_t * get_native_data(JNIEnv *env, jobject object) { 85 return (native_data_t *)(env->GetIntField(object, 86 field_mNativeData)); 87 } 88 89 static int setup_listening_socket(int dev, int channel); 90 #endif 91 92 static void classInitNative(JNIEnv* env, jclass clazz) { 93 ALOGV("%s", __FUNCTION__); 94 #ifdef HAVE_BLUETOOTH 95 96 /* in */ 97 field_mNativeData = get_field(env, clazz, "mNativeData", "I"); 98 field_mHandsfreeAgRfcommChannel = 99 get_field(env, clazz, "mHandsfreeAgRfcommChannel", "I"); 100 field_mHeadsetAgRfcommChannel = 101 get_field(env, clazz, "mHeadsetAgRfcommChannel", "I"); 102 103 /* out */ 104 field_mConnectingHeadsetAddress = 105 get_field(env, clazz, 106 "mConnectingHeadsetAddress", "Ljava/lang/String;"); 107 field_mConnectingHeadsetRfcommChannel = 108 get_field(env, clazz, "mConnectingHeadsetRfcommChannel", "I"); 109 field_mConnectingHeadsetSocketFd = 110 get_field(env, clazz, "mConnectingHeadsetSocketFd", "I"); 111 112 field_mConnectingHandsfreeAddress = 113 get_field(env, clazz, 114 "mConnectingHandsfreeAddress", "Ljava/lang/String;"); 115 field_mConnectingHandsfreeRfcommChannel = 116 get_field(env, clazz, "mConnectingHandsfreeRfcommChannel", "I"); 117 field_mConnectingHandsfreeSocketFd = 118 get_field(env, clazz, "mConnectingHandsfreeSocketFd", "I"); 119 120 field_mTimeoutRemainingMs = 121 get_field(env, clazz, "mTimeoutRemainingMs", "I"); 122 #endif 123 } 124 125 static void initializeNativeDataNative(JNIEnv* env, jobject object) { 126 ALOGV("%s", __FUNCTION__); 127 #ifdef HAVE_BLUETOOTH 128 native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t)); 129 if (NULL == nat) { 130 ALOGE("%s: out of memory!", __FUNCTION__); 131 return; 132 } 133 134 nat->hcidev = BLUETOOTH_ADAPTER_HCI_NUM; 135 136 env->SetIntField(object, field_mNativeData, (jint)nat); 137 nat->hf_ag_rfcomm_channel = 138 env->GetIntField(object, field_mHandsfreeAgRfcommChannel); 139 nat->hs_ag_rfcomm_channel = 140 env->GetIntField(object, field_mHeadsetAgRfcommChannel); 141 ALOGV("HF RFCOMM channel = %d.", nat->hf_ag_rfcomm_channel); 142 ALOGV("HS RFCOMM channel = %d.", nat->hs_ag_rfcomm_channel); 143 144 /* Set the default values of these to -1. */ 145 env->SetIntField(object, field_mConnectingHeadsetRfcommChannel, -1); 146 env->SetIntField(object, field_mConnectingHandsfreeRfcommChannel, -1); 147 148 nat->hf_ag_rfcomm_sock = -1; 149 nat->hs_ag_rfcomm_sock = -1; 150 #endif 151 } 152 153 static void cleanupNativeDataNative(JNIEnv* env, jobject object) { 154 ALOGV("%s", __FUNCTION__); 155 #ifdef HAVE_BLUETOOTH 156 native_data_t *nat = get_native_data(env, object); 157 if (nat) { 158 free(nat); 159 } 160 #endif 161 } 162 163 #ifdef HAVE_BLUETOOTH 164 165 #if USE_ACCEPT_DIRECTLY==0 166 static int set_nb(int sk, bool nb) { 167 int flags = fcntl(sk, F_GETFL); 168 if (flags < 0) { 169 ALOGE("Can't get socket flags with fcntl(): %s (%d)", 170 strerror(errno), errno); 171 close(sk); 172 return -1; 173 } 174 flags &= ~O_NONBLOCK; 175 if (nb) flags |= O_NONBLOCK; 176 int status = fcntl(sk, F_SETFL, flags); 177 if (status < 0) { 178 ALOGE("Can't set socket to nonblocking mode with fcntl(): %s (%d)", 179 strerror(errno), errno); 180 close(sk); 181 return -1; 182 } 183 return 0; 184 } 185 #endif /*USE_ACCEPT_DIRECTLY==0*/ 186 187 static int do_accept(JNIEnv* env, jobject object, int ag_fd, 188 jfieldID out_fd, 189 jfieldID out_address, 190 jfieldID out_channel) { 191 192 #if USE_ACCEPT_DIRECTLY==0 193 if (set_nb(ag_fd, true) < 0) 194 return -1; 195 #endif 196 197 struct sockaddr_rc raddr; 198 int alen = sizeof(raddr); 199 int nsk = TEMP_FAILURE_RETRY(accept(ag_fd, (struct sockaddr *) &raddr, &alen)); 200 if (nsk < 0) { 201 ALOGE("Error on accept from socket fd %d: %s (%d).", 202 ag_fd, 203 strerror(errno), 204 errno); 205 #if USE_ACCEPT_DIRECTLY==0 206 set_nb(ag_fd, false); 207 #endif 208 return -1; 209 } 210 211 env->SetIntField(object, out_fd, nsk); 212 env->SetIntField(object, out_channel, raddr.rc_channel); 213 214 char addr[BTADDR_SIZE]; 215 get_bdaddr_as_string(&raddr.rc_bdaddr, addr); 216 env->SetObjectField(object, out_address, env->NewStringUTF(addr)); 217 218 ALOGI("Successful accept() on AG socket %d: new socket %d, address %s, RFCOMM channel %d", 219 ag_fd, 220 nsk, 221 addr, 222 raddr.rc_channel); 223 #if USE_ACCEPT_DIRECTLY==0 224 set_nb(ag_fd, false); 225 #endif 226 return 0; 227 } 228 229 #if USE_SELECT 230 static inline int on_accept_set_fields(JNIEnv* env, jobject object, 231 fd_set *rset, int ag_fd, 232 jfieldID out_fd, 233 jfieldID out_address, 234 jfieldID out_channel) { 235 236 env->SetIntField(object, out_channel, -1); 237 238 if (ag_fd >= 0 && FD_ISSET(ag_fd, &rset)) { 239 return do_accept(env, object, ag_fd, 240 out_fd, out_address, out_channel); 241 } 242 else { 243 ALOGI("fd = %d, FD_ISSET() = %d", 244 ag_fd, 245 FD_ISSET(ag_fd, &rset)); 246 if (ag_fd >= 0 && !FD_ISSET(ag_fd, &rset)) { 247 ALOGE("WTF???"); 248 return -1; 249 } 250 } 251 252 return 0; 253 } 254 #endif 255 #endif /* HAVE_BLUETOOTH */ 256 257 static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, 258 jint timeout_ms) { 259 // ALOGV("%s", __FUNCTION__); 260 #ifdef HAVE_BLUETOOTH 261 262 env->SetIntField(object, field_mTimeoutRemainingMs, timeout_ms); 263 264 int n = 0; 265 native_data_t *nat = get_native_data(env, object); 266 #if USE_ACCEPT_DIRECTLY 267 if (nat->hf_ag_rfcomm_channel > 0) { 268 ALOGI("Setting HF AG server socket to RFCOMM port %d!", 269 nat->hf_ag_rfcomm_channel); 270 struct timeval tv; 271 int len = sizeof(tv); 272 if (getsockopt(nat->hf_ag_rfcomm_channel, 273 SOL_SOCKET, SO_RCVTIMEO, &tv, &len) < 0) { 274 ALOGE("getsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)", 275 nat->hf_ag_rfcomm_channel, 276 strerror(errno), 277 errno); 278 return JNI_FALSE; 279 } 280 ALOGI("Current HF AG server socket RCVTIMEO is (%d(s), %d(us))!", 281 (int)tv.tv_sec, (int)tv.tv_usec); 282 if (timeout_ms >= 0) { 283 tv.tv_sec = timeout_ms / 1000; 284 tv.tv_usec = 1000 * (timeout_ms % 1000); 285 if (setsockopt(nat->hf_ag_rfcomm_channel, 286 SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { 287 ALOGE("setsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)", 288 nat->hf_ag_rfcomm_channel, 289 strerror(errno), 290 errno); 291 return JNI_FALSE; 292 } 293 ALOGI("Changed HF AG server socket RCVTIMEO to (%d(s), %d(us))!", 294 (int)tv.tv_sec, (int)tv.tv_usec); 295 } 296 297 if (!do_accept(env, object, nat->hf_ag_rfcomm_sock, 298 field_mConnectingHandsfreeSocketFd, 299 field_mConnectingHandsfreeAddress, 300 field_mConnectingHandsfreeRfcommChannel)) 301 { 302 env->SetIntField(object, field_mTimeoutRemainingMs, 0); 303 return JNI_TRUE; 304 } 305 return JNI_FALSE; 306 } 307 #else 308 #if USE_SELECT 309 fd_set rset; 310 FD_ZERO(&rset); 311 int cnt = 0; 312 if (nat->hf_ag_rfcomm_channel > 0) { 313 ALOGI("Setting HF AG server socket to RFCOMM port %d!", 314 nat->hf_ag_rfcomm_channel); 315 cnt++; 316 FD_SET(nat->hf_ag_rfcomm_sock, &rset); 317 } 318 if (nat->hs_ag_rfcomm_channel > 0) { 319 ALOGI("Setting HS AG server socket to RFCOMM port %d!", 320 nat->hs_ag_rfcomm_channel); 321 cnt++; 322 FD_SET(nat->hs_ag_rfcomm_sock, &rset); 323 } 324 if (cnt == 0) { 325 ALOGE("Neither HF nor HS listening sockets are open!"); 326 return JNI_FALSE; 327 } 328 329 struct timeval to; 330 if (timeout_ms >= 0) { 331 to.tv_sec = timeout_ms / 1000; 332 to.tv_usec = 1000 * (timeout_ms % 1000); 333 } 334 n = TEMP_FAILURE_RETRY(select( 335 MAX(nat->hf_ag_rfcomm_sock, nat->hs_ag_rfcomm_sock) + 1, 336 &rset, 337 NULL, 338 NULL, 339 (timeout_ms < 0 ? NULL : &to))); 340 if (timeout_ms > 0) { 341 jint remaining = to.tv_sec*1000 + to.tv_usec/1000; 342 ALOGI("Remaining time %ldms", (long)remaining); 343 env->SetIntField(object, field_mTimeoutRemainingMs, 344 remaining); 345 } 346 347 ALOGI("listening select() returned %d", n); 348 349 if (n <= 0) { 350 if (n < 0) { 351 ALOGE("listening select() on RFCOMM sockets: %s (%d)", 352 strerror(errno), 353 errno); 354 } 355 return JNI_FALSE; 356 } 357 358 n = on_accept_set_fields(env, object, 359 &rset, nat->hf_ag_rfcomm_sock, 360 field_mConnectingHandsfreeSocketFd, 361 field_mConnectingHandsfreeAddress, 362 field_mConnectingHandsfreeRfcommChannel); 363 364 n += on_accept_set_fields(env, object, 365 &rset, nat->hs_ag_rfcomm_sock, 366 field_mConnectingHeadsetSocketFd, 367 field_mConnectingHeadsetAddress, 368 field_mConnectingHeadsetRfcommChannel); 369 370 return !n ? JNI_TRUE : JNI_FALSE; 371 #else 372 struct pollfd fds[2]; 373 int cnt = 0; 374 if (nat->hf_ag_rfcomm_channel > 0) { 375 // ALOGI("Setting HF AG server socket %d to RFCOMM port %d!", 376 // nat->hf_ag_rfcomm_sock, 377 // nat->hf_ag_rfcomm_channel); 378 fds[cnt].fd = nat->hf_ag_rfcomm_sock; 379 fds[cnt].events = POLLIN | POLLPRI | POLLOUT | POLLERR; 380 cnt++; 381 } 382 if (nat->hs_ag_rfcomm_channel > 0) { 383 // ALOGI("Setting HS AG server socket %d to RFCOMM port %d!", 384 // nat->hs_ag_rfcomm_sock, 385 // nat->hs_ag_rfcomm_channel); 386 fds[cnt].fd = nat->hs_ag_rfcomm_sock; 387 fds[cnt].events = POLLIN | POLLPRI | POLLOUT | POLLERR; 388 cnt++; 389 } 390 if (cnt == 0) { 391 ALOGE("Neither HF nor HS listening sockets are open!"); 392 return JNI_FALSE; 393 } 394 n = TEMP_FAILURE_RETRY(poll(fds, cnt, timeout_ms)); 395 if (n <= 0) { 396 if (n < 0) { 397 ALOGE("listening poll() on RFCOMM sockets: %s (%d)", 398 strerror(errno), 399 errno); 400 } 401 else { 402 env->SetIntField(object, field_mTimeoutRemainingMs, 0); 403 // ALOGI("listening poll() on RFCOMM socket timed out"); 404 } 405 return JNI_FALSE; 406 } 407 408 //ALOGI("listening poll() on RFCOMM socket returned %d", n); 409 int err = 0; 410 for (cnt = 0; cnt < (int)(sizeof(fds)/sizeof(fds[0])); cnt++) { 411 //ALOGI("Poll on fd %d revent = %d.", fds[cnt].fd, fds[cnt].revents); 412 if (fds[cnt].fd == nat->hf_ag_rfcomm_sock) { 413 if (fds[cnt].revents & (POLLIN | POLLPRI | POLLOUT)) { 414 ALOGI("Accepting HF connection.\n"); 415 err += do_accept(env, object, fds[cnt].fd, 416 field_mConnectingHandsfreeSocketFd, 417 field_mConnectingHandsfreeAddress, 418 field_mConnectingHandsfreeRfcommChannel); 419 n--; 420 } 421 } 422 else if (fds[cnt].fd == nat->hs_ag_rfcomm_sock) { 423 if (fds[cnt].revents & (POLLIN | POLLPRI | POLLOUT)) { 424 ALOGI("Accepting HS connection.\n"); 425 err += do_accept(env, object, fds[cnt].fd, 426 field_mConnectingHeadsetSocketFd, 427 field_mConnectingHeadsetAddress, 428 field_mConnectingHeadsetRfcommChannel); 429 n--; 430 } 431 } 432 } /* for */ 433 434 if (n != 0) { 435 ALOGI("Bogus poll(): %d fake pollfd entrie(s)!", n); 436 return JNI_FALSE; 437 } 438 439 return !err ? JNI_TRUE : JNI_FALSE; 440 #endif /* USE_SELECT */ 441 #endif /* USE_ACCEPT_DIRECTLY */ 442 #else 443 return JNI_FALSE; 444 #endif /* HAVE_BLUETOOTH */ 445 } 446 447 static jboolean setUpListeningSocketsNative(JNIEnv* env, jobject object) { 448 ALOGV("%s", __FUNCTION__); 449 #ifdef HAVE_BLUETOOTH 450 native_data_t *nat = get_native_data(env, object); 451 452 nat->hf_ag_rfcomm_sock = 453 setup_listening_socket(nat->hcidev, nat->hf_ag_rfcomm_channel); 454 if (nat->hf_ag_rfcomm_sock < 0) 455 return JNI_FALSE; 456 457 nat->hs_ag_rfcomm_sock = 458 setup_listening_socket(nat->hcidev, nat->hs_ag_rfcomm_channel); 459 if (nat->hs_ag_rfcomm_sock < 0) { 460 close(nat->hf_ag_rfcomm_sock); 461 nat->hf_ag_rfcomm_sock = -1; 462 return JNI_FALSE; 463 } 464 465 return JNI_TRUE; 466 #else 467 return JNI_FALSE; 468 #endif /* HAVE_BLUETOOTH */ 469 } 470 471 #ifdef HAVE_BLUETOOTH 472 static int setup_listening_socket(int dev, int channel) { 473 struct sockaddr_rc laddr; 474 int sk, lm; 475 476 sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); 477 if (sk < 0) { 478 ALOGE("Can't create RFCOMM socket"); 479 return -1; 480 } 481 482 if (debug_no_encrypt()) { 483 lm = RFCOMM_LM_AUTH; 484 } else { 485 lm = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT; 486 } 487 488 if (lm && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) { 489 ALOGE("Can't set RFCOMM link mode"); 490 close(sk); 491 return -1; 492 } 493 494 laddr.rc_family = AF_BLUETOOTH; 495 bdaddr_t any = android_bluetooth_bdaddr_any(); 496 memcpy(&laddr.rc_bdaddr, &any, sizeof(bdaddr_t)); 497 laddr.rc_channel = channel; 498 499 if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) { 500 ALOGE("Can't bind RFCOMM socket"); 501 close(sk); 502 return -1; 503 } 504 505 listen(sk, 10); 506 return sk; 507 } 508 #endif /* HAVE_BLUETOOTH */ 509 510 /* 511 private native void tearDownListeningSocketsNative(); 512 */ 513 static void tearDownListeningSocketsNative(JNIEnv *env, jobject object) { 514 ALOGV("%s", __FUNCTION__); 515 #ifdef HAVE_BLUETOOTH 516 native_data_t *nat = get_native_data(env, object); 517 518 if (nat->hf_ag_rfcomm_sock > 0) { 519 if (close(nat->hf_ag_rfcomm_sock) < 0) { 520 ALOGE("Could not close HF server socket: %s (%d)\n", 521 strerror(errno), errno); 522 } 523 nat->hf_ag_rfcomm_sock = -1; 524 } 525 if (nat->hs_ag_rfcomm_sock > 0) { 526 if (close(nat->hs_ag_rfcomm_sock) < 0) { 527 ALOGE("Could not close HS server socket: %s (%d)\n", 528 strerror(errno), errno); 529 } 530 nat->hs_ag_rfcomm_sock = -1; 531 } 532 #endif /* HAVE_BLUETOOTH */ 533 } 534 535 static JNINativeMethod sMethods[] = { 536 /* name, signature, funcPtr */ 537 538 {"classInitNative", "()V", (void*)classInitNative}, 539 {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative}, 540 {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative}, 541 542 {"setUpListeningSocketsNative", "()Z", (void *)setUpListeningSocketsNative}, 543 {"tearDownListeningSocketsNative", "()V", (void *)tearDownListeningSocketsNative}, 544 {"waitForHandsfreeConnectNative", "(I)Z", (void *)waitForHandsfreeConnectNative}, 545 }; 546 547 int register_android_bluetooth_BluetoothAudioGateway(JNIEnv *env) { 548 return AndroidRuntime::registerNativeMethods(env, 549 "android/bluetooth/BluetoothAudioGateway", sMethods, 550 NELEM(sMethods)); 551 } 552 553 } /* namespace android */ 554