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