summaryrefslogtreecommitdiffstats
path: root/core/jni/android_bluetooth_BluetoothAudioGateway.cpp
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:45 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:45 -0800
commitd83a98f4ce9cfa908f5c54bbd70f03eec07e7553 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /core/jni/android_bluetooth_BluetoothAudioGateway.cpp
parent076357b8567458d4b6dfdcf839ef751634cd2bfb (diff)
downloadframeworks_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-xcore/jni/android_bluetooth_BluetoothAudioGateway.cpp553
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 */