19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2006, The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "BluetoothAudioGateway.cpp" 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_bluetooth_common.h" 2075d086e5b2ed3c7ff70f60ca1f616138b825f551Doug Kwan#include "android_bluetooth_c.h" 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_runtime/AndroidRuntime.h" 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "JNIHelp.h" 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "jni.h" 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/Log.h" 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "utils/misc.h" 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define USE_ACCEPT_DIRECTLY (0) 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define USE_SELECT (0) /* 1 for select(), 0 for poll(); used only when 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project USE_ACCEPT_DIRECTLY == 0 */ 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h> 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h> 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h> 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h> 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/socket.h> 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/time.h> 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h> 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h> 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h> 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/uio.h> 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ctype.h> 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if USE_SELECT 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/select.h> 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/poll.h> 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_BLUETOOTH 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <bluetooth/bluetooth.h> 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <bluetooth/rfcomm.h> 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <bluetooth/sco.h> 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_BLUETOOTH 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID field_mNativeData; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* in */ 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID field_mHandsfreeAgRfcommChannel; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID field_mHeadsetAgRfcommChannel; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* out */ 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID field_mTimeoutRemainingMs; /* out */ 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID field_mConnectingHeadsetAddress; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID field_mConnectingHeadsetRfcommChannel; /* -1 when not connected */ 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID field_mConnectingHeadsetSocketFd; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID field_mConnectingHandsfreeAddress; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID field_mConnectingHandsfreeRfcommChannel; /* -1 when not connected */ 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID field_mConnectingHandsfreeSocketFd; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttypedef struct { 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int hcidev; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int hf_ag_rfcomm_channel; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int hs_ag_rfcomm_channel; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int hf_ag_rfcomm_sock; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int hs_ag_rfcomm_sock; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} native_data_t; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline native_data_t * get_native_data(JNIEnv *env, jobject object) { 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (native_data_t *)(env->GetIntField(object, 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mNativeData)); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int setup_listening_socket(int dev, int channel); 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void classInitNative(JNIEnv* env, jclass clazz) { 932653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh LOGV("%s", __FUNCTION__); 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_BLUETOOTH 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* in */ 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mNativeData = get_field(env, clazz, "mNativeData", "I"); 982653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh field_mHandsfreeAgRfcommChannel = 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project get_field(env, clazz, "mHandsfreeAgRfcommChannel", "I"); 1002653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh field_mHeadsetAgRfcommChannel = 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project get_field(env, clazz, "mHeadsetAgRfcommChannel", "I"); 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* out */ 1042653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh field_mConnectingHeadsetAddress = 1052653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh get_field(env, clazz, 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "mConnectingHeadsetAddress", "Ljava/lang/String;"); 1072653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh field_mConnectingHeadsetRfcommChannel = 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project get_field(env, clazz, "mConnectingHeadsetRfcommChannel", "I"); 1092653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh field_mConnectingHeadsetSocketFd = 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project get_field(env, clazz, "mConnectingHeadsetSocketFd", "I"); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1122653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh field_mConnectingHandsfreeAddress = 1132653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh get_field(env, clazz, 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "mConnectingHandsfreeAddress", "Ljava/lang/String;"); 1152653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh field_mConnectingHandsfreeRfcommChannel = 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project get_field(env, clazz, "mConnectingHandsfreeRfcommChannel", "I"); 1172653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh field_mConnectingHandsfreeSocketFd = 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project get_field(env, clazz, "mConnectingHandsfreeSocketFd", "I"); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1202653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh field_mTimeoutRemainingMs = 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project get_field(env, clazz, "mTimeoutRemainingMs", "I"); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void initializeNativeDataNative(JNIEnv* env, jobject object) { 1262653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh LOGV("%s", __FUNCTION__); 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_BLUETOOTH 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t)); 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (NULL == nat) { 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("%s: out of memory!", __FUNCTION__); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hcidev = BLUETOOTH_ADAPTER_HCI_NUM; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, field_mNativeData, (jint)nat); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hf_ag_rfcomm_channel = 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->GetIntField(object, field_mHandsfreeAgRfcommChannel); 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hs_ag_rfcomm_channel = 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->GetIntField(object, field_mHeadsetAgRfcommChannel); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("HF RFCOMM channel = %d.", nat->hf_ag_rfcomm_channel); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("HS RFCOMM channel = %d.", nat->hs_ag_rfcomm_channel); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Set the default values of these to -1. */ 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, field_mConnectingHeadsetRfcommChannel, -1); 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, field_mConnectingHandsfreeRfcommChannel, -1); 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hf_ag_rfcomm_sock = -1; 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hs_ag_rfcomm_sock = -1; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void cleanupNativeDataNative(JNIEnv* env, jobject object) { 1542653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh LOGV("%s", __FUNCTION__); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_BLUETOOTH 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_data_t *nat = get_native_data(env, object); 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nat) { 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(nat); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_BLUETOOTH 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if USE_ACCEPT_DIRECTLY==0 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int set_nb(int sk, bool nb) { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flags = fcntl(sk, F_GETFL); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flags < 0) { 1692653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh LOGE("Can't get socket flags with fcntl(): %s (%d)", 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strerror(errno), errno); 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(sk); 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flags &= ~O_NONBLOCK; 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nb) flags |= O_NONBLOCK; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int status = fcntl(sk, F_SETFL, flags); 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (status < 0) { 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Can't set socket to nonblocking mode with fcntl(): %s (%d)", 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strerror(errno), errno); 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(sk); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif /*USE_ACCEPT_DIRECTLY==0*/ 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int do_accept(JNIEnv* env, jobject object, int ag_fd, 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID out_fd, 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID out_address, 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID out_channel) { 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if USE_ACCEPT_DIRECTLY==0 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (set_nb(ag_fd, true) < 0) 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct sockaddr_rc raddr; 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int alen = sizeof(raddr); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nsk = accept(ag_fd, (struct sockaddr *) &raddr, &alen); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nsk < 0) { 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Error on accept from socket fd %d: %s (%d).", 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ag_fd, 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strerror(errno), 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project errno); 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if USE_ACCEPT_DIRECTLY==0 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project set_nb(ag_fd, false); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, out_fd, nsk); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, out_channel, raddr.rc_channel); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char addr[BTADDR_SIZE]; 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project get_bdaddr_as_string(&raddr.rc_bdaddr, addr); 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetObjectField(object, out_address, env->NewStringUTF(addr)); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGI("Successful accept() on AG socket %d: new socket %d, address %s, RFCOMM channel %d", 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ag_fd, 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nsk, 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addr, 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project raddr.rc_channel); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if USE_ACCEPT_DIRECTLY==0 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project set_nb(ag_fd, false); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if USE_SELECT 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline int on_accept_set_fields(JNIEnv* env, jobject object, 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd_set *rset, int ag_fd, 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID out_fd, 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID out_address, 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID out_channel) { 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, out_channel, -1); 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ag_fd >= 0 && FD_ISSET(ag_fd, &rset)) { 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return do_accept(env, object, ag_fd, 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out_fd, out_address, out_channel); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else { 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGI("fd = %d, FD_ISSET() = %d", 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ag_fd, 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FD_ISSET(ag_fd, &rset)); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ag_fd >= 0 && !FD_ISSET(ag_fd, &rset)) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("WTF???"); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif /* HAVE_BLUETOOTH */ 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint timeout_ms) { 2592653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh// LOGV("%s", __FUNCTION__); 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_BLUETOOTH 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, field_mTimeoutRemainingMs, timeout_ms); 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int n = 0; 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_data_t *nat = get_native_data(env, object); 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if USE_ACCEPT_DIRECTLY 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nat->hf_ag_rfcomm_channel > 0) { 2682653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh LOGI("Setting HF AG server socket to RFCOMM port %d!", 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hf_ag_rfcomm_channel); 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct timeval tv; 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = sizeof(tv); 2722653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh if (getsockopt(nat->hf_ag_rfcomm_channel, 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SOL_SOCKET, SO_RCVTIMEO, &tv, &len) < 0) { 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("getsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)", 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hf_ag_rfcomm_channel, 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strerror(errno), 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project errno); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return JNI_FALSE; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2802653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh LOGI("Current HF AG server socket RCVTIMEO is (%d(s), %d(us))!", 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (int)tv.tv_sec, (int)tv.tv_usec); 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (timeout_ms >= 0) { 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tv.tv_sec = timeout_ms / 1000; 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tv.tv_usec = 1000 * (timeout_ms % 1000); 2852653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh if (setsockopt(nat->hf_ag_rfcomm_channel, 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("setsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)", 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hf_ag_rfcomm_channel, 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strerror(errno), 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project errno); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return JNI_FALSE; 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2932653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh LOGI("Changed HF AG server socket RCVTIMEO to (%d(s), %d(us))!", 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (int)tv.tv_sec, (int)tv.tv_usec); 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2972653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh if (!do_accept(env, object, nat->hf_ag_rfcomm_sock, 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHandsfreeSocketFd, 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHandsfreeAddress, 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHandsfreeRfcommChannel)) 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, field_mTimeoutRemainingMs, 0); 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return JNI_TRUE; 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return JNI_FALSE; 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if USE_SELECT 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd_set rset; 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FD_ZERO(&rset); 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int cnt = 0; 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nat->hf_ag_rfcomm_channel > 0) { 3132653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh LOGI("Setting HF AG server socket to RFCOMM port %d!", 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hf_ag_rfcomm_channel); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cnt++; 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FD_SET(nat->hf_ag_rfcomm_sock, &rset); 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nat->hs_ag_rfcomm_channel > 0) { 3192653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh LOGI("Setting HS AG server socket to RFCOMM port %d!", 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hs_ag_rfcomm_channel); 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cnt++; 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FD_SET(nat->hs_ag_rfcomm_sock, &rset); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cnt == 0) { 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Neither HF nor HS listening sockets are open!"); 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return JNI_FALSE; 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct timeval to; 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (timeout_ms >= 0) { 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project to.tv_sec = timeout_ms / 1000; 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project to.tv_usec = 1000 * (timeout_ms % 1000); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3342653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh n = select(MAX(nat->hf_ag_rfcomm_sock, 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hs_ag_rfcomm_sock) + 1, 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project &rset, 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NULL, 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NULL, 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (timeout_ms < 0 ? NULL : &to)); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (timeout_ms > 0) { 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint remaining = to.tv_sec*1000 + to.tv_usec/1000; 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGI("Remaining time %ldms", (long)remaining); 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, field_mTimeoutRemainingMs, 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project remaining); 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGI("listening select() returned %d", n); 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (n <= 0) { 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (n < 0) { 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("listening select() on RFCOMM sockets: %s (%d)", 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strerror(errno), 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project errno); 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return JNI_FALSE; 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3582653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh n = on_accept_set_fields(env, object, 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project &rset, nat->hf_ag_rfcomm_sock, 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHandsfreeSocketFd, 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHandsfreeAddress, 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHandsfreeRfcommChannel); 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project n += on_accept_set_fields(env, object, 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project &rset, nat->hs_ag_rfcomm_sock, 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHeadsetSocketFd, 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHeadsetAddress, 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHeadsetRfcommChannel); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return !n ? JNI_TRUE : JNI_FALSE; 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct pollfd fds[2]; 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int cnt = 0; 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nat->hf_ag_rfcomm_channel > 0) { 3752653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh// LOGI("Setting HF AG server socket %d to RFCOMM port %d!", 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// nat->hf_ag_rfcomm_sock, 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// nat->hf_ag_rfcomm_channel); 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fds[cnt].fd = nat->hf_ag_rfcomm_sock; 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fds[cnt].events = POLLIN | POLLPRI | POLLOUT | POLLERR; 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cnt++; 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nat->hs_ag_rfcomm_channel > 0) { 3832653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh// LOGI("Setting HS AG server socket %d to RFCOMM port %d!", 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// nat->hs_ag_rfcomm_sock, 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// nat->hs_ag_rfcomm_channel); 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fds[cnt].fd = nat->hs_ag_rfcomm_sock; 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fds[cnt].events = POLLIN | POLLPRI | POLLOUT | POLLERR; 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cnt++; 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cnt == 0) { 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Neither HF nor HS listening sockets are open!"); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return JNI_FALSE; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project n = poll(fds, cnt, timeout_ms); 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (n <= 0) { 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (n < 0) { 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("listening poll() on RFCOMM sockets: %s (%d)", 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strerror(errno), 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project errno); 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else { 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->SetIntField(object, field_mTimeoutRemainingMs, 0); 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// LOGI("listening poll() on RFCOMM socket timed out"); 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return JNI_FALSE; 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //LOGI("listening poll() on RFCOMM socket returned %d", n); 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err = 0; 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (cnt = 0; cnt < (int)(sizeof(fds)/sizeof(fds[0])); cnt++) { 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //LOGI("Poll on fd %d revent = %d.", fds[cnt].fd, fds[cnt].revents); 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fds[cnt].fd == nat->hf_ag_rfcomm_sock) { 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fds[cnt].revents & (POLLIN | POLLPRI | POLLOUT)) { 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGI("Accepting HF connection.\n"); 4152653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh err += do_accept(env, object, fds[cnt].fd, 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHandsfreeSocketFd, 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHandsfreeAddress, 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHandsfreeRfcommChannel); 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project n--; 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (fds[cnt].fd == nat->hs_ag_rfcomm_sock) { 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fds[cnt].revents & (POLLIN | POLLPRI | POLLOUT)) { 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGI("Accepting HS connection.\n"); 4252653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh err += do_accept(env, object, fds[cnt].fd, 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHeadsetSocketFd, 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHeadsetAddress, 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_mConnectingHeadsetRfcommChannel); 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project n--; 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } /* for */ 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (n != 0) { 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGI("Bogus poll(): %d fake pollfd entrie(s)!", n); 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return JNI_FALSE; 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return !err ? JNI_TRUE : JNI_FALSE; 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif /* USE_SELECT */ 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif /* USE_ACCEPT_DIRECTLY */ 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return JNI_FALSE; 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif /* HAVE_BLUETOOTH */ 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jboolean setUpListeningSocketsNative(JNIEnv* env, jobject object) { 4482653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh LOGV("%s", __FUNCTION__); 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_BLUETOOTH 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_data_t *nat = get_native_data(env, object); 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hf_ag_rfcomm_sock = 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setup_listening_socket(nat->hcidev, nat->hf_ag_rfcomm_channel); 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nat->hf_ag_rfcomm_sock < 0) 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return JNI_FALSE; 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hs_ag_rfcomm_sock = 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setup_listening_socket(nat->hcidev, nat->hs_ag_rfcomm_channel); 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nat->hs_ag_rfcomm_sock < 0) { 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(nat->hf_ag_rfcomm_sock); 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hf_ag_rfcomm_sock = -1; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return JNI_FALSE; 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return JNI_TRUE; 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return JNI_FALSE; 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif /* HAVE_BLUETOOTH */ 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_BLUETOOTH 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int setup_listening_socket(int dev, int channel) { 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct sockaddr_rc laddr; 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int sk, lm; 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sk < 0) { 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Can't create RFCOMM socket"); 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (debug_no_encrypt()) { 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lm = RFCOMM_LM_AUTH; 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lm = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT; 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 48814faa3bd8bd6d1deab63a40ad2f8b6e451a16208Jaikumar Ganesh if (lm && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) { 48914faa3bd8bd6d1deab63a40ad2f8b6e451a16208Jaikumar Ganesh LOGE("Can't set RFCOMM link mode"); 49014faa3bd8bd6d1deab63a40ad2f8b6e451a16208Jaikumar Ganesh close(sk); 49114faa3bd8bd6d1deab63a40ad2f8b6e451a16208Jaikumar Ganesh return -1; 49214faa3bd8bd6d1deab63a40ad2f8b6e451a16208Jaikumar Ganesh } 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project laddr.rc_family = AF_BLUETOOTH; 49575d086e5b2ed3c7ff70f60ca1f616138b825f551Doug Kwan bdaddr_t any = android_bluetooth_bdaddr_any(); 49675d086e5b2ed3c7ff70f60ca1f616138b825f551Doug Kwan memcpy(&laddr.rc_bdaddr, &any, sizeof(bdaddr_t)); 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project laddr.rc_channel = channel; 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 49914faa3bd8bd6d1deab63a40ad2f8b6e451a16208Jaikumar Ganesh if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) { 50014faa3bd8bd6d1deab63a40ad2f8b6e451a16208Jaikumar Ganesh LOGE("Can't bind RFCOMM socket"); 50114faa3bd8bd6d1deab63a40ad2f8b6e451a16208Jaikumar Ganesh close(sk); 50214faa3bd8bd6d1deab63a40ad2f8b6e451a16208Jaikumar Ganesh return -1; 50314faa3bd8bd6d1deab63a40ad2f8b6e451a16208Jaikumar Ganesh } 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project listen(sk, 10); 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sk; 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif /* HAVE_BLUETOOTH */ 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native void tearDownListeningSocketsNative(); 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void tearDownListeningSocketsNative(JNIEnv *env, jobject object) { 5142653a1e7ca55b03f5230dffa85dfe2705757e2b7Jaikumar Ganesh LOGV("%s", __FUNCTION__); 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifdef HAVE_BLUETOOTH 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_data_t *nat = get_native_data(env, object); 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nat->hf_ag_rfcomm_sock > 0) { 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (close(nat->hf_ag_rfcomm_sock) < 0) { 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Could not close HF server socket: %s (%d)\n", 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strerror(errno), errno); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hf_ag_rfcomm_sock = -1; 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nat->hs_ag_rfcomm_sock > 0) { 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (close(nat->hs_ag_rfcomm_sock) < 0) { 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Could not close HS server socket: %s (%d)\n", 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strerror(errno), errno); 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nat->hs_ag_rfcomm_sock = -1; 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif /* HAVE_BLUETOOTH */ 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod sMethods[] = { 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* name, signature, funcPtr */ 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"classInitNative", "()V", (void*)classInitNative}, 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative}, 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative}, 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"setUpListeningSocketsNative", "()Z", (void *)setUpListeningSocketsNative}, 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"tearDownListeningSocketsNative", "()V", (void *)tearDownListeningSocketsNative}, 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"waitForHandsfreeConnectNative", "(I)Z", (void *)waitForHandsfreeConnectNative}, 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_bluetooth_BluetoothAudioGateway(JNIEnv *env) { 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods(env, 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "android/bluetooth/BluetoothAudioGateway", sMethods, 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NELEM(sMethods)); 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} /* namespace android */ 554