diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:45 -0800 |
commit | d83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/jni/android_bluetooth_BluetoothAudioGateway.cpp | |
parent | 076357b8567458d4b6dfdcf839ef751634cd2bfb (diff) | |
download | frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.zip frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.gz frameworks_base-d83a98f4ce9cfa908f5c54bbd70f03eec07e7553.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'core/jni/android_bluetooth_BluetoothAudioGateway.cpp')
-rwxr-xr-x | core/jni/android_bluetooth_BluetoothAudioGateway.cpp | 553 |
1 files changed, 0 insertions, 553 deletions
diff --git a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp deleted file mode 100755 index 7f87d80..0000000 --- a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp +++ /dev/null @@ -1,553 +0,0 @@ -/* -** Copyright 2006, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#define LOG_TAG "BluetoothAudioGateway.cpp" - -#include "android_bluetooth_common.h" -#include "android_runtime/AndroidRuntime.h" -#include "JNIHelp.h" -#include "jni.h" -#include "utils/Log.h" -#include "utils/misc.h" - -#define USE_ACCEPT_DIRECTLY (0) -#define USE_SELECT (0) /* 1 for select(), 0 for poll(); used only when - USE_ACCEPT_DIRECTLY == 0 */ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/socket.h> -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/uio.h> -#include <ctype.h> - -#if USE_SELECT -#include <sys/select.h> -#else -#include <sys/poll.h> -#endif - -#ifdef HAVE_BLUETOOTH -#include <bluetooth/bluetooth.h> -#include <bluetooth/hci.h> -#include <bluetooth/hci_lib.h> -#include <bluetooth/rfcomm.h> -#include <bluetooth/sco.h> -#endif - -namespace android { - -#ifdef HAVE_BLUETOOTH -static jfieldID field_mNativeData; - /* in */ -static jfieldID field_mHandsfreeAgRfcommChannel; -static jfieldID field_mHeadsetAgRfcommChannel; - /* out */ -static jfieldID field_mTimeoutRemainingMs; /* out */ - -static jfieldID field_mConnectingHeadsetAddress; -static jfieldID field_mConnectingHeadsetRfcommChannel; /* -1 when not connected */ -static jfieldID field_mConnectingHeadsetSocketFd; - -static jfieldID field_mConnectingHandsfreeAddress; -static jfieldID field_mConnectingHandsfreeRfcommChannel; /* -1 when not connected */ -static jfieldID field_mConnectingHandsfreeSocketFd; - - -typedef struct { - int hcidev; - int hf_ag_rfcomm_channel; - int hs_ag_rfcomm_channel; - int hf_ag_rfcomm_sock; - int hs_ag_rfcomm_sock; -} native_data_t; - -static inline native_data_t * get_native_data(JNIEnv *env, jobject object) { - return (native_data_t *)(env->GetIntField(object, - field_mNativeData)); -} - -static int setup_listening_socket(int dev, int channel); -#endif - -static void classInitNative(JNIEnv* env, jclass clazz) { - LOGV(__FUNCTION__); -#ifdef HAVE_BLUETOOTH - - /* in */ - field_mNativeData = get_field(env, clazz, "mNativeData", "I"); - field_mHandsfreeAgRfcommChannel = - get_field(env, clazz, "mHandsfreeAgRfcommChannel", "I"); - field_mHeadsetAgRfcommChannel = - get_field(env, clazz, "mHeadsetAgRfcommChannel", "I"); - - /* out */ - field_mConnectingHeadsetAddress = - get_field(env, clazz, - "mConnectingHeadsetAddress", "Ljava/lang/String;"); - field_mConnectingHeadsetRfcommChannel = - get_field(env, clazz, "mConnectingHeadsetRfcommChannel", "I"); - field_mConnectingHeadsetSocketFd = - get_field(env, clazz, "mConnectingHeadsetSocketFd", "I"); - - field_mConnectingHandsfreeAddress = - get_field(env, clazz, - "mConnectingHandsfreeAddress", "Ljava/lang/String;"); - field_mConnectingHandsfreeRfcommChannel = - get_field(env, clazz, "mConnectingHandsfreeRfcommChannel", "I"); - field_mConnectingHandsfreeSocketFd = - get_field(env, clazz, "mConnectingHandsfreeSocketFd", "I"); - - field_mTimeoutRemainingMs = - get_field(env, clazz, "mTimeoutRemainingMs", "I"); -#endif -} - -static void initializeNativeDataNative(JNIEnv* env, jobject object) { - LOGV(__FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t)); - if (NULL == nat) { - LOGE("%s: out of memory!", __FUNCTION__); - return; - } - - nat->hcidev = BLUETOOTH_ADAPTER_HCI_NUM; - - env->SetIntField(object, field_mNativeData, (jint)nat); - nat->hf_ag_rfcomm_channel = - env->GetIntField(object, field_mHandsfreeAgRfcommChannel); - nat->hs_ag_rfcomm_channel = - env->GetIntField(object, field_mHeadsetAgRfcommChannel); - LOGV("HF RFCOMM channel = %d.", nat->hf_ag_rfcomm_channel); - LOGV("HS RFCOMM channel = %d.", nat->hs_ag_rfcomm_channel); - - /* Set the default values of these to -1. */ - env->SetIntField(object, field_mConnectingHeadsetRfcommChannel, -1); - env->SetIntField(object, field_mConnectingHandsfreeRfcommChannel, -1); - - nat->hf_ag_rfcomm_sock = -1; - nat->hs_ag_rfcomm_sock = -1; -#endif -} - -static void cleanupNativeDataNative(JNIEnv* env, jobject object) { - LOGV(__FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - free(nat); - } -#endif -} - -#ifdef HAVE_BLUETOOTH - -#if USE_ACCEPT_DIRECTLY==0 -static int set_nb(int sk, bool nb) { - int flags = fcntl(sk, F_GETFL); - if (flags < 0) { - LOGE("Can't get socket flags with fcntl(): %s (%d)", - strerror(errno), errno); - close(sk); - return -1; - } - flags &= ~O_NONBLOCK; - if (nb) flags |= O_NONBLOCK; - int status = fcntl(sk, F_SETFL, flags); - if (status < 0) { - LOGE("Can't set socket to nonblocking mode with fcntl(): %s (%d)", - strerror(errno), errno); - close(sk); - return -1; - } - return 0; -} -#endif /*USE_ACCEPT_DIRECTLY==0*/ - -static int do_accept(JNIEnv* env, jobject object, int ag_fd, - jfieldID out_fd, - jfieldID out_address, - jfieldID out_channel) { - -#if USE_ACCEPT_DIRECTLY==0 - if (set_nb(ag_fd, true) < 0) - return -1; -#endif - - struct sockaddr_rc raddr; - int alen = sizeof(raddr); - int nsk = accept(ag_fd, (struct sockaddr *) &raddr, &alen); - if (nsk < 0) { - LOGE("Error on accept from socket fd %d: %s (%d).", - ag_fd, - strerror(errno), - errno); -#if USE_ACCEPT_DIRECTLY==0 - set_nb(ag_fd, false); -#endif - return -1; - } - - env->SetIntField(object, out_fd, nsk); - env->SetIntField(object, out_channel, raddr.rc_channel); - - char addr[BTADDR_SIZE]; - get_bdaddr_as_string(&raddr.rc_bdaddr, addr); - env->SetObjectField(object, out_address, env->NewStringUTF(addr)); - - LOGI("Successful accept() on AG socket %d: new socket %d, address %s, RFCOMM channel %d", - ag_fd, - nsk, - addr, - raddr.rc_channel); -#if USE_ACCEPT_DIRECTLY==0 - set_nb(ag_fd, false); -#endif - return 0; -} - -#if USE_SELECT -static inline int on_accept_set_fields(JNIEnv* env, jobject object, - fd_set *rset, int ag_fd, - jfieldID out_fd, - jfieldID out_address, - jfieldID out_channel) { - - env->SetIntField(object, out_channel, -1); - - if (ag_fd >= 0 && FD_ISSET(ag_fd, &rset)) { - return do_accept(env, object, ag_fd, - out_fd, out_address, out_channel); - } - else { - LOGI("fd = %d, FD_ISSET() = %d", - ag_fd, - FD_ISSET(ag_fd, &rset)); - if (ag_fd >= 0 && !FD_ISSET(ag_fd, &rset)) { - LOGE("WTF???"); - return -1; - } - } - - return 0; -} -#endif -#endif /* HAVE_BLUETOOTH */ - -static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, - jint timeout_ms) { -// LOGV(__FUNCTION__); -#ifdef HAVE_BLUETOOTH - - env->SetIntField(object, field_mTimeoutRemainingMs, timeout_ms); - - int n = 0; - native_data_t *nat = get_native_data(env, object); -#if USE_ACCEPT_DIRECTLY - if (nat->hf_ag_rfcomm_channel > 0) { - LOGI("Setting HF AG server socket to RFCOMM port %d!", - nat->hf_ag_rfcomm_channel); - struct timeval tv; - int len = sizeof(tv); - if (getsockopt(nat->hf_ag_rfcomm_channel, - SOL_SOCKET, SO_RCVTIMEO, &tv, &len) < 0) { - LOGE("getsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)", - nat->hf_ag_rfcomm_channel, - strerror(errno), - errno); - return JNI_FALSE; - } - LOGI("Current HF AG server socket RCVTIMEO is (%d(s), %d(us))!", - (int)tv.tv_sec, (int)tv.tv_usec); - if (timeout_ms >= 0) { - tv.tv_sec = timeout_ms / 1000; - tv.tv_usec = 1000 * (timeout_ms % 1000); - if (setsockopt(nat->hf_ag_rfcomm_channel, - SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { - LOGE("setsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)", - nat->hf_ag_rfcomm_channel, - strerror(errno), - errno); - return JNI_FALSE; - } - LOGI("Changed HF AG server socket RCVTIMEO to (%d(s), %d(us))!", - (int)tv.tv_sec, (int)tv.tv_usec); - } - - if (!do_accept(env, object, nat->hf_ag_rfcomm_sock, - field_mConnectingHandsfreeSocketFd, - field_mConnectingHandsfreeAddress, - field_mConnectingHandsfreeRfcommChannel)) - { - env->SetIntField(object, field_mTimeoutRemainingMs, 0); - return JNI_TRUE; - } - return JNI_FALSE; - } -#else -#if USE_SELECT - fd_set rset; - FD_ZERO(&rset); - int cnt = 0; - if (nat->hf_ag_rfcomm_channel > 0) { - LOGI("Setting HF AG server socket to RFCOMM port %d!", - nat->hf_ag_rfcomm_channel); - cnt++; - FD_SET(nat->hf_ag_rfcomm_sock, &rset); - } - if (nat->hs_ag_rfcomm_channel > 0) { - LOGI("Setting HS AG server socket to RFCOMM port %d!", - nat->hs_ag_rfcomm_channel); - cnt++; - FD_SET(nat->hs_ag_rfcomm_sock, &rset); - } - if (cnt == 0) { - LOGE("Neither HF nor HS listening sockets are open!"); - return JNI_FALSE; - } - - struct timeval to; - if (timeout_ms >= 0) { - to.tv_sec = timeout_ms / 1000; - to.tv_usec = 1000 * (timeout_ms % 1000); - } - n = select(MAX(nat->hf_ag_rfcomm_sock, - nat->hs_ag_rfcomm_sock) + 1, - &rset, - NULL, - NULL, - (timeout_ms < 0 ? NULL : &to)); - if (timeout_ms > 0) { - jint remaining = to.tv_sec*1000 + to.tv_usec/1000; - LOGI("Remaining time %ldms", (long)remaining); - env->SetIntField(object, field_mTimeoutRemainingMs, - remaining); - } - - LOGI("listening select() returned %d", n); - - if (n <= 0) { - if (n < 0) { - LOGE("listening select() on RFCOMM sockets: %s (%d)", - strerror(errno), - errno); - } - return JNI_FALSE; - } - - n = on_accept_set_fields(env, object, - &rset, nat->hf_ag_rfcomm_sock, - field_mConnectingHandsfreeSocketFd, - field_mConnectingHandsfreeAddress, - field_mConnectingHandsfreeRfcommChannel); - - n += on_accept_set_fields(env, object, - &rset, nat->hs_ag_rfcomm_sock, - field_mConnectingHeadsetSocketFd, - field_mConnectingHeadsetAddress, - field_mConnectingHeadsetRfcommChannel); - - return !n ? JNI_TRUE : JNI_FALSE; -#else - struct pollfd fds[2]; - int cnt = 0; - if (nat->hf_ag_rfcomm_channel > 0) { -// LOGI("Setting HF AG server socket %d to RFCOMM port %d!", -// nat->hf_ag_rfcomm_sock, -// nat->hf_ag_rfcomm_channel); - fds[cnt].fd = nat->hf_ag_rfcomm_sock; - fds[cnt].events = POLLIN | POLLPRI | POLLOUT | POLLERR; - cnt++; - } - if (nat->hs_ag_rfcomm_channel > 0) { -// LOGI("Setting HS AG server socket %d to RFCOMM port %d!", -// nat->hs_ag_rfcomm_sock, -// nat->hs_ag_rfcomm_channel); - fds[cnt].fd = nat->hs_ag_rfcomm_sock; - fds[cnt].events = POLLIN | POLLPRI | POLLOUT | POLLERR; - cnt++; - } - if (cnt == 0) { - LOGE("Neither HF nor HS listening sockets are open!"); - return JNI_FALSE; - } - n = poll(fds, cnt, timeout_ms); - if (n <= 0) { - if (n < 0) { - LOGE("listening poll() on RFCOMM sockets: %s (%d)", - strerror(errno), - errno); - } - else { - env->SetIntField(object, field_mTimeoutRemainingMs, 0); -// LOGI("listening poll() on RFCOMM socket timed out"); - } - return JNI_FALSE; - } - - //LOGI("listening poll() on RFCOMM socket returned %d", n); - int err = 0; - for (cnt = 0; cnt < (int)(sizeof(fds)/sizeof(fds[0])); cnt++) { - //LOGI("Poll on fd %d revent = %d.", fds[cnt].fd, fds[cnt].revents); - if (fds[cnt].fd == nat->hf_ag_rfcomm_sock) { - if (fds[cnt].revents & (POLLIN | POLLPRI | POLLOUT)) { - LOGI("Accepting HF connection.\n"); - err += do_accept(env, object, fds[cnt].fd, - field_mConnectingHandsfreeSocketFd, - field_mConnectingHandsfreeAddress, - field_mConnectingHandsfreeRfcommChannel); - n--; - } - } - else if (fds[cnt].fd == nat->hs_ag_rfcomm_sock) { - if (fds[cnt].revents & (POLLIN | POLLPRI | POLLOUT)) { - LOGI("Accepting HS connection.\n"); - err += do_accept(env, object, fds[cnt].fd, - field_mConnectingHeadsetSocketFd, - field_mConnectingHeadsetAddress, - field_mConnectingHeadsetRfcommChannel); - n--; - } - } - } /* for */ - - if (n != 0) { - LOGI("Bogus poll(): %d fake pollfd entrie(s)!", n); - return JNI_FALSE; - } - - return !err ? JNI_TRUE : JNI_FALSE; -#endif /* USE_SELECT */ -#endif /* USE_ACCEPT_DIRECTLY */ -#else - return JNI_FALSE; -#endif /* HAVE_BLUETOOTH */ -} - -static jboolean setUpListeningSocketsNative(JNIEnv* env, jobject object) { - LOGV(__FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - - nat->hf_ag_rfcomm_sock = - setup_listening_socket(nat->hcidev, nat->hf_ag_rfcomm_channel); - if (nat->hf_ag_rfcomm_sock < 0) - return JNI_FALSE; - - nat->hs_ag_rfcomm_sock = - setup_listening_socket(nat->hcidev, nat->hs_ag_rfcomm_channel); - if (nat->hs_ag_rfcomm_sock < 0) { - close(nat->hf_ag_rfcomm_sock); - nat->hf_ag_rfcomm_sock = -1; - return JNI_FALSE; - } - - return JNI_TRUE; -#else - return JNI_FALSE; -#endif /* HAVE_BLUETOOTH */ -} - -#ifdef HAVE_BLUETOOTH -static int setup_listening_socket(int dev, int channel) { - struct sockaddr_rc laddr; - int sk, lm; - - sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (sk < 0) { - LOGE("Can't create RFCOMM socket"); - return -1; - } - - if (debug_no_encrypt()) { - lm = RFCOMM_LM_AUTH; - } else { - lm = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT; - } - - if (lm && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) { - LOGE("Can't set RFCOMM link mode"); - close(sk); - return -1; - } - - laddr.rc_family = AF_BLUETOOTH; - bacpy(&laddr.rc_bdaddr, BDADDR_ANY); - laddr.rc_channel = channel; - - if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) { - LOGE("Can't bind RFCOMM socket"); - close(sk); - return -1; - } - - listen(sk, 10); - return sk; -} -#endif /* HAVE_BLUETOOTH */ - -/* - private native void tearDownListeningSocketsNative(); -*/ -static void tearDownListeningSocketsNative(JNIEnv *env, jobject object) { - LOGV(__FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - - if (nat->hf_ag_rfcomm_sock > 0) { - if (close(nat->hf_ag_rfcomm_sock) < 0) { - LOGE("Could not close HF server socket: %s (%d)\n", - strerror(errno), errno); - } - nat->hf_ag_rfcomm_sock = -1; - } - if (nat->hs_ag_rfcomm_sock > 0) { - if (close(nat->hs_ag_rfcomm_sock) < 0) { - LOGE("Could not close HS server socket: %s (%d)\n", - strerror(errno), errno); - } - nat->hs_ag_rfcomm_sock = -1; - } -#endif /* HAVE_BLUETOOTH */ -} - -static JNINativeMethod sMethods[] = { - /* name, signature, funcPtr */ - - {"classInitNative", "()V", (void*)classInitNative}, - {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative}, - {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative}, - - {"setUpListeningSocketsNative", "()Z", (void *)setUpListeningSocketsNative}, - {"tearDownListeningSocketsNative", "()V", (void *)tearDownListeningSocketsNative}, - {"waitForHandsfreeConnectNative", "(I)Z", (void *)waitForHandsfreeConnectNative}, -}; - -int register_android_bluetooth_BluetoothAudioGateway(JNIEnv *env) { - return AndroidRuntime::registerNativeMethods(env, - "android/bluetooth/BluetoothAudioGateway", sMethods, - NELEM(sMethods)); -} - -} /* namespace android */ |