diff options
author | Matthew Xie <mattx@google.com> | 2012-07-16 21:09:13 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-07-16 21:09:13 -0700 |
commit | d4d4e715c5f4423b9fadce77b120b8488e011337 (patch) | |
tree | cf2e85c3dd7a9877427a6238452a5f07ccd48403 /core/jni | |
parent | 9e4a6baee333b3ea5e8e2c291a8c94d4e8aabf75 (diff) | |
parent | 313a2167098ce8498db3a50d70724f260e8169c0 (diff) | |
download | frameworks_base-d4d4e715c5f4423b9fadce77b120b8488e011337.zip frameworks_base-d4d4e715c5f4423b9fadce77b120b8488e011337.tar.gz frameworks_base-d4d4e715c5f4423b9fadce77b120b8488e011337.tar.bz2 |
Merge "Delete various Bluetooth files for stack integration."
Diffstat (limited to 'core/jni')
-rw-r--r-- | core/jni/Android.mk | 8 | ||||
-rw-r--r-- | core/jni/AndroidRuntime.cpp | 12 | ||||
-rw-r--r-- | core/jni/android_bluetooth_BluetoothAudioGateway.cpp | 553 | ||||
-rw-r--r-- | core/jni/android_bluetooth_BluetoothSocket.cpp | 588 | ||||
-rw-r--r-- | core/jni/android_bluetooth_HeadsetBase.cpp | 567 | ||||
-rw-r--r-- | core/jni/android_bluetooth_c.c | 31 | ||||
-rw-r--r-- | core/jni/android_bluetooth_c.h | 39 | ||||
-rw-r--r-- | core/jni/android_bluetooth_common.cpp | 867 | ||||
-rw-r--r-- | core/jni/android_bluetooth_common.h | 215 | ||||
-rw-r--r-- | core/jni/android_server_BluetoothA2dpService.cpp | 344 | ||||
-rw-r--r-- | core/jni/android_server_BluetoothEventLoop.cpp | 1585 | ||||
-rw-r--r-- | core/jni/android_server_BluetoothService.cpp | 1785 |
12 files changed, 0 insertions, 6594 deletions
diff --git a/core/jni/Android.mk b/core/jni/Android.mk index eb39b12..99ec057 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -138,14 +138,6 @@ LOCAL_SRC_FILES:= \ android_util_FileObserver.cpp \ android/opengl/poly_clip.cpp.arm \ android/opengl/util.cpp.arm \ - android_bluetooth_HeadsetBase.cpp \ - android_bluetooth_common.cpp \ - android_bluetooth_BluetoothAudioGateway.cpp \ - android_bluetooth_BluetoothSocket.cpp \ - android_bluetooth_c.c \ - android_server_BluetoothService.cpp \ - android_server_BluetoothEventLoop.cpp \ - android_server_BluetoothA2dpService.cpp \ android_server_NetworkManagementSocketTagger.cpp \ android_server_Watchdog.cpp \ android_ddm_DdmHandleNativeHeap.cpp \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 532a6e5..f0dd321 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -150,12 +150,6 @@ extern int register_android_net_wifi_WifiManager(JNIEnv* env); extern int register_android_text_AndroidCharacter(JNIEnv *env); extern int register_android_text_AndroidBidi(JNIEnv *env); extern int register_android_opengl_classes(JNIEnv *env); -extern int register_android_bluetooth_HeadsetBase(JNIEnv* env); -extern int register_android_bluetooth_BluetoothAudioGateway(JNIEnv* env); -extern int register_android_bluetooth_BluetoothSocket(JNIEnv *env); -extern int register_android_server_BluetoothService(JNIEnv* env); -extern int register_android_server_BluetoothEventLoop(JNIEnv *env); -extern int register_android_server_BluetoothA2dpService(JNIEnv* env); extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env); extern int register_android_server_Watchdog(JNIEnv* env); extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env); @@ -1172,12 +1166,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_media_ToneGenerator), REG_JNI(register_android_opengl_classes), - REG_JNI(register_android_bluetooth_HeadsetBase), - REG_JNI(register_android_bluetooth_BluetoothAudioGateway), - REG_JNI(register_android_bluetooth_BluetoothSocket), - REG_JNI(register_android_server_BluetoothService), - REG_JNI(register_android_server_BluetoothEventLoop), - REG_JNI(register_android_server_BluetoothA2dpService), REG_JNI(register_android_server_NetworkManagementSocketTagger), REG_JNI(register_android_server_Watchdog), REG_JNI(register_android_ddm_DdmHandleNativeHeap), diff --git a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp deleted file mode 100644 index 294c626..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_bluetooth_c.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/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) { - ALOGV("%s", __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) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t)); - if (NULL == nat) { - ALOGE("%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); - ALOGV("HF RFCOMM channel = %d.", nat->hf_ag_rfcomm_channel); - ALOGV("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) { - ALOGV("%s", __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) { - ALOGE("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) { - ALOGE("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 = TEMP_FAILURE_RETRY(accept(ag_fd, (struct sockaddr *) &raddr, &alen)); - if (nsk < 0) { - ALOGE("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)); - - ALOGI("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 { - ALOGI("fd = %d, FD_ISSET() = %d", - ag_fd, - FD_ISSET(ag_fd, &rset)); - if (ag_fd >= 0 && !FD_ISSET(ag_fd, &rset)) { - ALOGE("WTF???"); - return -1; - } - } - - return 0; -} -#endif -#endif /* HAVE_BLUETOOTH */ - -static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object, - jint timeout_ms) { -// ALOGV("%s", __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) { - ALOGI("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) { - ALOGE("getsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)", - nat->hf_ag_rfcomm_channel, - strerror(errno), - errno); - return JNI_FALSE; - } - ALOGI("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) { - ALOGE("setsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)", - nat->hf_ag_rfcomm_channel, - strerror(errno), - errno); - return JNI_FALSE; - } - ALOGI("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) { - ALOGI("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) { - ALOGI("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) { - ALOGE("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 = TEMP_FAILURE_RETRY(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; - ALOGI("Remaining time %ldms", (long)remaining); - env->SetIntField(object, field_mTimeoutRemainingMs, - remaining); - } - - ALOGI("listening select() returned %d", n); - - if (n <= 0) { - if (n < 0) { - ALOGE("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) { -// ALOGI("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) { -// ALOGI("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) { - ALOGE("Neither HF nor HS listening sockets are open!"); - return JNI_FALSE; - } - n = TEMP_FAILURE_RETRY(poll(fds, cnt, timeout_ms)); - if (n <= 0) { - if (n < 0) { - ALOGE("listening poll() on RFCOMM sockets: %s (%d)", - strerror(errno), - errno); - } - else { - env->SetIntField(object, field_mTimeoutRemainingMs, 0); -// ALOGI("listening poll() on RFCOMM socket timed out"); - } - return JNI_FALSE; - } - - //ALOGI("listening poll() on RFCOMM socket returned %d", n); - int err = 0; - for (cnt = 0; cnt < (int)(sizeof(fds)/sizeof(fds[0])); cnt++) { - //ALOGI("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)) { - ALOGI("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)) { - ALOGI("Accepting HS connection.\n"); - err += do_accept(env, object, fds[cnt].fd, - field_mConnectingHeadsetSocketFd, - field_mConnectingHeadsetAddress, - field_mConnectingHeadsetRfcommChannel); - n--; - } - } - } /* for */ - - if (n != 0) { - ALOGI("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) { - ALOGV("%s", __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) { - ALOGE("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) { - ALOGE("Can't set RFCOMM link mode"); - close(sk); - return -1; - } - - laddr.rc_family = AF_BLUETOOTH; - bdaddr_t any = android_bluetooth_bdaddr_any(); - memcpy(&laddr.rc_bdaddr, &any, sizeof(bdaddr_t)); - laddr.rc_channel = channel; - - if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) { - ALOGE("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) { - ALOGV("%s", __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) { - ALOGE("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) { - ALOGE("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 */ diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp deleted file mode 100644 index d9ff36a..0000000 --- a/core/jni/android_bluetooth_BluetoothSocket.cpp +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Copyright 2009, 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 "BluetoothSocket.cpp" - -#include "android_bluetooth_common.h" -#include "android_bluetooth_c.h" -#include "android_runtime/AndroidRuntime.h" -#include "JNIHelp.h" -#include "utils/Log.h" -#include "cutils/abort_socket.h" - -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> -#include <sys/socket.h> -#include <sys/ioctl.h> - -#ifdef HAVE_BLUETOOTH -#include <bluetooth/bluetooth.h> -#include <bluetooth/rfcomm.h> -#include <bluetooth/l2cap.h> -#include <bluetooth/sco.h> -#endif - -#define TYPE_AS_STR(t) \ - ((t) == TYPE_RFCOMM ? "RFCOMM" : ((t) == TYPE_SCO ? "SCO" : "L2CAP")) - -namespace android { - -static jfieldID field_mAuth; /* read-only */ -static jfieldID field_mEncrypt; /* read-only */ -static jfieldID field_mType; /* read-only */ -static jfieldID field_mAddress; /* read-only */ -static jfieldID field_mPort; /* read-only */ -static jfieldID field_mSocketData; -static jmethodID method_BluetoothSocket_ctor; -static jclass class_BluetoothSocket; - -/* Keep TYPE_RFCOMM etc in sync with BluetoothSocket.java */ -static const int TYPE_RFCOMM = 1; -static const int TYPE_SCO = 2; -static const int TYPE_L2CAP = 3; // TODO: Test l2cap code paths - -static const int RFCOMM_SO_SNDBUF = 70 * 1024; // 70 KB send buffer - -static void abortNative(JNIEnv *env, jobject obj); -static void destroyNative(JNIEnv *env, jobject obj); - -static struct asocket *get_socketData(JNIEnv *env, jobject obj) { - struct asocket *s = - (struct asocket *) env->GetIntField(obj, field_mSocketData); - if (!s) - jniThrowException(env, "java/io/IOException", "null socketData"); - return s; -} - -static void initSocketFromFdNative(JNIEnv *env, jobject obj, jint fd) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - - struct asocket *s = asocket_init(fd); - - if (!s) { - ALOGV("asocket_init() failed, throwing"); - jniThrowIOException(env, errno); - return; - } - - env->SetIntField(obj, field_mSocketData, (jint)s); - - return; -#endif - jniThrowIOException(env, ENOSYS); -} - -static void initSocketNative(JNIEnv *env, jobject obj) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - - int fd; - int lm = 0; - int sndbuf; - jboolean auth; - jboolean encrypt; - jint type; - - type = env->GetIntField(obj, field_mType); - - switch (type) { - case TYPE_RFCOMM: - fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - break; - case TYPE_SCO: - fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO); - break; - case TYPE_L2CAP: - fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); - break; - default: - jniThrowIOException(env, ENOSYS); - return; - } - - if (fd < 0) { - ALOGV("socket() failed, throwing"); - jniThrowIOException(env, errno); - return; - } - - auth = env->GetBooleanField(obj, field_mAuth); - encrypt = env->GetBooleanField(obj, field_mEncrypt); - - /* kernel does not yet support LM for SCO */ - switch (type) { - case TYPE_RFCOMM: - lm |= auth ? RFCOMM_LM_AUTH : 0; - lm |= encrypt ? RFCOMM_LM_ENCRYPT : 0; - lm |= (auth && encrypt) ? RFCOMM_LM_SECURE : 0; - break; - case TYPE_L2CAP: - lm |= auth ? L2CAP_LM_AUTH : 0; - lm |= encrypt ? L2CAP_LM_ENCRYPT : 0; - lm |= (auth && encrypt) ? L2CAP_LM_SECURE : 0; - break; - } - - if (lm) { - if (setsockopt(fd, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm))) { - ALOGV("setsockopt(RFCOMM_LM) failed, throwing"); - jniThrowIOException(env, errno); - return; - } - } - - if (type == TYPE_RFCOMM) { - sndbuf = RFCOMM_SO_SNDBUF; - if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf))) { - ALOGV("setsockopt(SO_SNDBUF) failed, throwing"); - jniThrowIOException(env, errno); - return; - } - } - - ALOGV("...fd %d created (%s, lm = %x)", fd, TYPE_AS_STR(type), lm); - - initSocketFromFdNative(env, obj, fd); - return; -#endif - jniThrowIOException(env, ENOSYS); -} - -static void connectNative(JNIEnv *env, jobject obj) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - - int ret; - jint type; - const char *c_address; - jstring address; - bdaddr_t bdaddress; - socklen_t addr_sz; - struct sockaddr *addr; - struct asocket *s = get_socketData(env, obj); - int retry = 0; - - if (!s) - return; - - type = env->GetIntField(obj, field_mType); - - /* parse address into bdaddress */ - address = (jstring) env->GetObjectField(obj, field_mAddress); - c_address = env->GetStringUTFChars(address, NULL); - if (get_bdaddr(c_address, &bdaddress)) { - env->ReleaseStringUTFChars(address, c_address); - jniThrowIOException(env, EINVAL); - return; - } - env->ReleaseStringUTFChars(address, c_address); - - switch (type) { - case TYPE_RFCOMM: - struct sockaddr_rc addr_rc; - addr = (struct sockaddr *)&addr_rc; - addr_sz = sizeof(addr_rc); - - memset(addr, 0, addr_sz); - addr_rc.rc_family = AF_BLUETOOTH; - addr_rc.rc_channel = env->GetIntField(obj, field_mPort); - memcpy(&addr_rc.rc_bdaddr, &bdaddress, sizeof(bdaddr_t)); - - break; - case TYPE_SCO: - struct sockaddr_sco addr_sco; - addr = (struct sockaddr *)&addr_sco; - addr_sz = sizeof(addr_sco); - - memset(addr, 0, addr_sz); - addr_sco.sco_family = AF_BLUETOOTH; - memcpy(&addr_sco.sco_bdaddr, &bdaddress, sizeof(bdaddr_t)); - - break; - case TYPE_L2CAP: - struct sockaddr_l2 addr_l2; - addr = (struct sockaddr *)&addr_l2; - addr_sz = sizeof(addr_l2); - - memset(addr, 0, addr_sz); - addr_l2.l2_family = AF_BLUETOOTH; - addr_l2.l2_psm = env->GetIntField(obj, field_mPort); - memcpy(&addr_l2.l2_bdaddr, &bdaddress, sizeof(bdaddr_t)); - - break; - default: - jniThrowIOException(env, ENOSYS); - return; - } - -connect: - ret = asocket_connect(s, addr, addr_sz, -1); - ALOGV("...connect(%d, %s) = %d (errno %d)", - s->fd, TYPE_AS_STR(type), ret, errno); - - if (ret && errno == EALREADY && retry < 2) { - /* workaround for bug 5082381 (EALREADY on ACL collision): - * retry the connect. Unfortunately we have to create a new fd. - * It's not ideal to switch the fd underneath the object, but - * is currently safe */ - ALOGD("Hit bug 5082381 (EALREADY on ACL collision), trying workaround"); - usleep(100000); - retry++; - abortNative(env, obj); - destroyNative(env, obj); - initSocketNative(env, obj); - if (env->ExceptionOccurred()) { - return; - } - goto connect; - } - if (!ret && retry > 0) - ALOGD("...workaround ok"); - - if (ret) - jniThrowIOException(env, errno); - - return; -#endif - jniThrowIOException(env, ENOSYS); -} - -/* Returns errno instead of throwing, so java can check errno */ -static int bindListenNative(JNIEnv *env, jobject obj) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - - jint type; - socklen_t addr_sz; - struct sockaddr *addr; - bdaddr_t bdaddr = android_bluetooth_bdaddr_any(); - struct asocket *s = get_socketData(env, obj); - - if (!s) - return EINVAL; - - type = env->GetIntField(obj, field_mType); - - switch (type) { - case TYPE_RFCOMM: - struct sockaddr_rc addr_rc; - addr = (struct sockaddr *)&addr_rc; - addr_sz = sizeof(addr_rc); - - memset(addr, 0, addr_sz); - addr_rc.rc_family = AF_BLUETOOTH; - addr_rc.rc_channel = env->GetIntField(obj, field_mPort); - memcpy(&addr_rc.rc_bdaddr, &bdaddr, sizeof(bdaddr_t)); - break; - case TYPE_SCO: - struct sockaddr_sco addr_sco; - addr = (struct sockaddr *)&addr_sco; - addr_sz = sizeof(addr_sco); - - memset(addr, 0, addr_sz); - addr_sco.sco_family = AF_BLUETOOTH; - memcpy(&addr_sco.sco_bdaddr, &bdaddr, sizeof(bdaddr_t)); - break; - case TYPE_L2CAP: - struct sockaddr_l2 addr_l2; - addr = (struct sockaddr *)&addr_l2; - addr_sz = sizeof(addr_l2); - - memset(addr, 0, addr_sz); - addr_l2.l2_family = AF_BLUETOOTH; - addr_l2.l2_psm = env->GetIntField(obj, field_mPort); - memcpy(&addr_l2.l2_bdaddr, &bdaddr, sizeof(bdaddr_t)); - break; - default: - return ENOSYS; - } - - if (bind(s->fd, addr, addr_sz)) { - ALOGV("...bind(%d) gave errno %d", s->fd, errno); - return errno; - } - - if (listen(s->fd, 1)) { - ALOGV("...listen(%d) gave errno %d", s->fd, errno); - return errno; - } - - ALOGV("...bindListenNative(%d) success", s->fd); - - return 0; - -#endif - return ENOSYS; -} - -static jobject acceptNative(JNIEnv *env, jobject obj, int timeout) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - - int fd; - jint type; - struct sockaddr *addr; - socklen_t addr_sz; - jstring addr_jstr; - char addr_cstr[BTADDR_SIZE]; - bdaddr_t *bdaddr; - jboolean auth; - jboolean encrypt; - - struct asocket *s = get_socketData(env, obj); - - if (!s) - return NULL; - - type = env->GetIntField(obj, field_mType); - - switch (type) { - case TYPE_RFCOMM: - struct sockaddr_rc addr_rc; - addr = (struct sockaddr *)&addr_rc; - addr_sz = sizeof(addr_rc); - bdaddr = &addr_rc.rc_bdaddr; - memset(addr, 0, addr_sz); - break; - case TYPE_SCO: - struct sockaddr_sco addr_sco; - addr = (struct sockaddr *)&addr_sco; - addr_sz = sizeof(addr_sco); - bdaddr = &addr_sco.sco_bdaddr; - memset(addr, 0, addr_sz); - break; - case TYPE_L2CAP: - struct sockaddr_l2 addr_l2; - addr = (struct sockaddr *)&addr_l2; - addr_sz = sizeof(addr_l2); - bdaddr = &addr_l2.l2_bdaddr; - memset(addr, 0, addr_sz); - break; - default: - jniThrowIOException(env, ENOSYS); - return NULL; - } - - fd = asocket_accept(s, addr, &addr_sz, timeout); - - ALOGV("...accept(%d, %s) = %d (errno %d)", - s->fd, TYPE_AS_STR(type), fd, errno); - - if (fd < 0) { - jniThrowIOException(env, errno); - return NULL; - } - - /* Connected - return new BluetoothSocket */ - auth = env->GetBooleanField(obj, field_mAuth); - encrypt = env->GetBooleanField(obj, field_mEncrypt); - - get_bdaddr_as_string(bdaddr, addr_cstr); - - addr_jstr = env->NewStringUTF(addr_cstr); - return env->NewObject(class_BluetoothSocket, method_BluetoothSocket_ctor, - type, fd, auth, encrypt, addr_jstr, -1); - -#endif - jniThrowIOException(env, ENOSYS); - return NULL; -} - -static jint availableNative(JNIEnv *env, jobject obj) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - - int available; - struct asocket *s = get_socketData(env, obj); - - if (!s) - return -1; - - if (ioctl(s->fd, FIONREAD, &available) < 0) { - jniThrowIOException(env, errno); - return -1; - } - - return available; - -#endif - jniThrowIOException(env, ENOSYS); - return -1; -} - -static jint readNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset, - jint length) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - - int ret; - jbyte *b; - int sz; - struct asocket *s = get_socketData(env, obj); - - if (!s) - return -1; - if (jb == NULL) { - jniThrowIOException(env, EINVAL); - return -1; - } - sz = env->GetArrayLength(jb); - if (offset < 0 || length < 0 || offset + length > sz) { - jniThrowIOException(env, EINVAL); - return -1; - } - - b = env->GetByteArrayElements(jb, NULL); - if (b == NULL) { - jniThrowIOException(env, EINVAL); - return -1; - } - - ret = asocket_read(s, &b[offset], length, -1); - if (ret < 0) { - jniThrowIOException(env, errno); - env->ReleaseByteArrayElements(jb, b, JNI_ABORT); - return -1; - } - - env->ReleaseByteArrayElements(jb, b, 0); - return (jint)ret; - -#endif - jniThrowIOException(env, ENOSYS); - return -1; -} - -static jint writeNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset, - jint length) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - - int ret, total; - jbyte *b; - int sz; - struct asocket *s = get_socketData(env, obj); - - if (!s) - return -1; - if (jb == NULL) { - jniThrowIOException(env, EINVAL); - return -1; - } - sz = env->GetArrayLength(jb); - if (offset < 0 || length < 0 || offset + length > sz) { - jniThrowIOException(env, EINVAL); - return -1; - } - - b = env->GetByteArrayElements(jb, NULL); - if (b == NULL) { - jniThrowIOException(env, EINVAL); - return -1; - } - - total = 0; - while (length > 0) { - ret = asocket_write(s, &b[offset], length, -1); - if (ret < 0) { - jniThrowIOException(env, errno); - env->ReleaseByteArrayElements(jb, b, JNI_ABORT); - return -1; - } - offset += ret; - total += ret; - length -= ret; - } - - env->ReleaseByteArrayElements(jb, b, JNI_ABORT); // no need to commit - return (jint)total; - -#endif - jniThrowIOException(env, ENOSYS); - return -1; -} - -static void abortNative(JNIEnv *env, jobject obj) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - struct asocket *s = get_socketData(env, obj); - - if (!s) - return; - - asocket_abort(s); - - ALOGV("...asocket_abort(%d) complete", s->fd); - return; -#endif - jniThrowIOException(env, ENOSYS); -} - -static void destroyNative(JNIEnv *env, jobject obj) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - struct asocket *s = get_socketData(env, obj); - int fd = s->fd; - - if (!s) - return; - - asocket_destroy(s); - - ALOGV("...asocket_destroy(%d) complete", fd); - return; -#endif - jniThrowIOException(env, ENOSYS); -} - -static void throwErrnoNative(JNIEnv *env, jobject obj, jint err) { - jniThrowIOException(env, err); -} - -static JNINativeMethod sMethods[] = { - {"initSocketNative", "()V", (void*) initSocketNative}, - {"initSocketFromFdNative", "(I)V", (void*) initSocketFromFdNative}, - {"connectNative", "()V", (void *) connectNative}, - {"bindListenNative", "()I", (void *) bindListenNative}, - {"acceptNative", "(I)Landroid/bluetooth/BluetoothSocket;", (void *) acceptNative}, - {"availableNative", "()I", (void *) availableNative}, - {"readNative", "([BII)I", (void *) readNative}, - {"writeNative", "([BII)I", (void *) writeNative}, - {"abortNative", "()V", (void *) abortNative}, - {"destroyNative", "()V", (void *) destroyNative}, - {"throwErrnoNative", "(I)V", (void *) throwErrnoNative}, -}; - -int register_android_bluetooth_BluetoothSocket(JNIEnv *env) { - jclass clazz = env->FindClass("android/bluetooth/BluetoothSocket"); - if (clazz == NULL) - return -1; - class_BluetoothSocket = (jclass) env->NewGlobalRef(clazz); - field_mType = env->GetFieldID(clazz, "mType", "I"); - field_mAddress = env->GetFieldID(clazz, "mAddress", "Ljava/lang/String;"); - field_mPort = env->GetFieldID(clazz, "mPort", "I"); - field_mAuth = env->GetFieldID(clazz, "mAuth", "Z"); - field_mEncrypt = env->GetFieldID(clazz, "mEncrypt", "Z"); - field_mSocketData = env->GetFieldID(clazz, "mSocketData", "I"); - method_BluetoothSocket_ctor = env->GetMethodID(clazz, "<init>", "(IIZZLjava/lang/String;I)V"); - return AndroidRuntime::registerNativeMethods(env, - "android/bluetooth/BluetoothSocket", sMethods, NELEM(sMethods)); -} - -} /* namespace android */ - diff --git a/core/jni/android_bluetooth_HeadsetBase.cpp b/core/jni/android_bluetooth_HeadsetBase.cpp deleted file mode 100644 index 34447ef..0000000 --- a/core/jni/android_bluetooth_HeadsetBase.cpp +++ /dev/null @@ -1,567 +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 "BT HSHFP" - -#include "android_bluetooth_common.h" -#include "android_runtime/AndroidRuntime.h" -#include "JNIHelp.h" -#include "jni.h" -#include "utils/Log.h" -#include "utils/misc.h" - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/socket.h> -#include <sys/uio.h> -#include <sys/poll.h> - -#ifdef HAVE_BLUETOOTH -#include <bluetooth/bluetooth.h> -#include <bluetooth/rfcomm.h> -#include <bluetooth/sco.h> -#endif - -namespace android { - -#ifdef HAVE_BLUETOOTH -static jfieldID field_mNativeData; -static jfieldID field_mAddress; -static jfieldID field_mRfcommChannel; -static jfieldID field_mTimeoutRemainingMs; - -typedef struct { - jstring address; - const char *c_address; - int rfcomm_channel; - int last_read_err; - int rfcomm_sock; - int rfcomm_connected; // -1 in progress, 0 not connected, 1 connected - int rfcomm_sock_flags; -} 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 const char CRLF[] = "\xd\xa"; -static const int CRLF_LEN = 2; - -static inline int write_error_check(int fd, const char* line, int len) { - int ret; - errno = 0; - ret = write(fd, line, len); - if (ret < 0) { - ALOGE("%s: write() failed: %s (%d)", __FUNCTION__, strerror(errno), - errno); - return -1; - } - if (ret != len) { - ALOGE("%s: write() only wrote %d of %d bytes", __FUNCTION__, ret, len); - return -1; - } - return 0; -} - -static int send_line(int fd, const char* line) { - int nw; - int len = strlen(line); - int llen = len + CRLF_LEN * 2 + 1; - char *buffer = (char *)calloc(llen, sizeof(char)); - - snprintf(buffer, llen, "%s%s%s", CRLF, line, CRLF); - - if (write_error_check(fd, buffer, llen - 1)) { - free(buffer); - return -1; - } - free(buffer); - return 0; -} - -static void mask_eighth_bit(char *line) -{ - for (;;line++) { - if (0 == *line) return; - *line &= 0x7F; - } -} - -static const char* get_line(int fd, char *buf, int len, int timeout_ms, - int *err) { - char *bufit=buf; - int fd_flags = fcntl(fd, F_GETFL, 0); - struct pollfd pfd; - -again: - *bufit = 0; - pfd.fd = fd; - pfd.events = POLLIN; - *err = errno = 0; - int ret = TEMP_FAILURE_RETRY(poll(&pfd, 1, timeout_ms)); - if (ret < 0) { - ALOGE("poll() error\n"); - *err = errno; - return NULL; - } - if (ret == 0) { - return NULL; - } - - if (pfd.revents & (POLLHUP | POLLERR | POLLNVAL)) { - ALOGW("RFCOMM poll() returned success (%d), " - "but with an unexpected revents bitmask: %#x\n", ret, pfd.revents); - errno = EIO; - *err = errno; - return NULL; - } - - while ((int)(bufit - buf) < (len - 1)) - { - errno = 0; - int rc = TEMP_FAILURE_RETRY(read(fd, bufit, 1)); - - if (!rc) - break; - - if (rc < 0) { - if (errno == EBUSY) { - ALOGI("read() error %s (%d): repeating read()...", - strerror(errno), errno); - goto again; - } - *err = errno; - ALOGE("read() error %s (%d)", strerror(errno), errno); - return NULL; - } - - - if (*bufit=='\xd') { - break; - } - - if (*bufit=='\xa') - bufit = buf; - else - bufit++; - } - - *bufit = 0; - - // According to ITU V.250 section 5.1, IA5 7 bit chars are used, - // the eighth bit or higher bits are ignored if they exists - // We mask out only eighth bit, no higher bit, since we do char - // string here, not wide char. - // We added this processing due to 2 real world problems. - // 1 BMW 2005 E46 which sends binary junk - // 2 Audi 2010 A3, dial command use 0xAD (soft-hyphen) as number - // formater, which was rejected by the AT handler - mask_eighth_bit(buf); - - return buf; -} -#endif - -static void classInitNative(JNIEnv* env, jclass clazz) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - field_mNativeData = get_field(env, clazz, "mNativeData", "I"); - field_mAddress = get_field(env, clazz, "mAddress", "Ljava/lang/String;"); - field_mTimeoutRemainingMs = get_field(env, clazz, "mTimeoutRemainingMs", "I"); - field_mRfcommChannel = get_field(env, clazz, "mRfcommChannel", "I"); -#endif -} - -static void initializeNativeDataNative(JNIEnv* env, jobject object, - jint socketFd) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t)); - if (NULL == nat) { - ALOGE("%s: out of memory!", __FUNCTION__); - return; - } - - env->SetIntField(object, field_mNativeData, (jint)nat); - nat->address = - (jstring)env->NewGlobalRef(env->GetObjectField(object, - field_mAddress)); - nat->c_address = env->GetStringUTFChars(nat->address, NULL); - nat->rfcomm_channel = env->GetIntField(object, field_mRfcommChannel); - nat->rfcomm_sock = socketFd; - nat->rfcomm_connected = socketFd >= 0; - if (nat->rfcomm_connected) - ALOGI("%s: ALREADY CONNECTED!", __FUNCTION__); -#endif -} - -static void cleanupNativeDataNative(JNIEnv* env, jobject object) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = - (native_data_t *)env->GetIntField(object, field_mNativeData); - env->ReleaseStringUTFChars(nat->address, nat->c_address); - env->DeleteGlobalRef(nat->address); - if (nat) - free(nat); -#endif -} - -static jboolean connectNative(JNIEnv *env, jobject obj) -{ - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - int lm; - struct sockaddr_rc addr; - native_data_t *nat = get_native_data(env, obj); - - nat->rfcomm_sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - - if (nat->rfcomm_sock < 0) { - ALOGE("%s: Could not create RFCOMM socket: %s\n", __FUNCTION__, - strerror(errno)); - return JNI_FALSE; - } - - if (debug_no_encrypt()) { - lm = RFCOMM_LM_AUTH; - } else { - lm = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT; - } - - if (lm && setsockopt(nat->rfcomm_sock, SOL_RFCOMM, RFCOMM_LM, &lm, - sizeof(lm)) < 0) { - ALOGE("%s: Can't set RFCOMM link mode", __FUNCTION__); - close(nat->rfcomm_sock); - return JNI_FALSE; - } - - memset(&addr, 0, sizeof(struct sockaddr_rc)); - get_bdaddr(nat->c_address, &addr.rc_bdaddr); - addr.rc_channel = nat->rfcomm_channel; - addr.rc_family = AF_BLUETOOTH; - nat->rfcomm_connected = 0; - while (nat->rfcomm_connected == 0) { - if (connect(nat->rfcomm_sock, (struct sockaddr *)&addr, - sizeof(addr)) < 0) { - if (errno == EINTR) continue; - ALOGE("%s: connect() failed: %s\n", __FUNCTION__, strerror(errno)); - close(nat->rfcomm_sock); - nat->rfcomm_sock = -1; - return JNI_FALSE; - } else { - nat->rfcomm_connected = 1; - } - } - - return JNI_TRUE; -#else - return JNI_FALSE; -#endif -} - -static jint connectAsyncNative(JNIEnv *env, jobject obj) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - struct sockaddr_rc addr; - native_data_t *nat = get_native_data(env, obj); - - if (nat->rfcomm_connected) { - ALOGV("RFCOMM socket is already connected or connection is in progress."); - return 0; - } - - if (nat->rfcomm_sock < 0) { - int lm; - - nat->rfcomm_sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (nat->rfcomm_sock < 0) { - ALOGE("%s: Could not create RFCOMM socket: %s\n", __FUNCTION__, - strerror(errno)); - return -1; - } - - if (debug_no_encrypt()) { - lm = RFCOMM_LM_AUTH; - } else { - lm = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT; - } - - if (lm && setsockopt(nat->rfcomm_sock, SOL_RFCOMM, RFCOMM_LM, &lm, - sizeof(lm)) < 0) { - ALOGE("%s: Can't set RFCOMM link mode", __FUNCTION__); - close(nat->rfcomm_sock); - return -1; - } - ALOGI("Created RFCOMM socket fd %d.", nat->rfcomm_sock); - } - - memset(&addr, 0, sizeof(struct sockaddr_rc)); - get_bdaddr(nat->c_address, &addr.rc_bdaddr); - addr.rc_channel = nat->rfcomm_channel; - addr.rc_family = AF_BLUETOOTH; - if (nat->rfcomm_sock_flags >= 0) { - nat->rfcomm_sock_flags = fcntl(nat->rfcomm_sock, F_GETFL, 0); - if (fcntl(nat->rfcomm_sock, - F_SETFL, nat->rfcomm_sock_flags | O_NONBLOCK) >= 0) { - int rc; - nat->rfcomm_connected = 0; - errno = 0; - rc = connect(nat->rfcomm_sock, - (struct sockaddr *)&addr, - sizeof(addr)); - - if (rc >= 0) { - nat->rfcomm_connected = 1; - ALOGI("async connect successful"); - return 0; - } - else if (rc < 0) { - if (errno == EINPROGRESS || errno == EAGAIN) - { - ALOGI("async connect is in progress (%s)", - strerror(errno)); - nat->rfcomm_connected = -1; - return 0; - } - else - { - ALOGE("async connect error: %s (%d)", strerror(errno), errno); - close(nat->rfcomm_sock); - nat->rfcomm_sock = -1; - return -errno; - } - } - } // fcntl(nat->rfcomm_sock ...) - } // if (nat->rfcomm_sock_flags >= 0) -#endif - return -1; -} - -static jint waitForAsyncConnectNative(JNIEnv *env, jobject obj, - jint timeout_ms) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - struct sockaddr_rc addr; - native_data_t *nat = get_native_data(env, obj); - - env->SetIntField(obj, field_mTimeoutRemainingMs, timeout_ms); - - if (nat->rfcomm_connected > 0) { - ALOGI("RFCOMM is already connected!"); - return 1; - } - - if (nat->rfcomm_sock >= 0 && nat->rfcomm_connected == 0) { - ALOGI("Re-opening RFCOMM socket."); - close(nat->rfcomm_sock); - nat->rfcomm_sock = -1; - } - int ret = connectAsyncNative(env, obj); - - if (ret < 0) { - ALOGI("Failed to re-open RFCOMM socket!"); - return ret; - } - - if (nat->rfcomm_sock >= 0) { - /* Do an asynchronous select() */ - int n; - fd_set rset, wset; - struct timeval to; - - FD_ZERO(&rset); - FD_ZERO(&wset); - FD_SET(nat->rfcomm_sock, &rset); - FD_SET(nat->rfcomm_sock, &wset); - if (timeout_ms >= 0) { - to.tv_sec = timeout_ms / 1000; - to.tv_usec = 1000 * (timeout_ms % 1000); - } - n = select(nat->rfcomm_sock + 1, - &rset, - &wset, - NULL, - (timeout_ms < 0 ? NULL : &to)); - - if (timeout_ms > 0) { - jint remaining = to.tv_sec*1000 + to.tv_usec/1000; - ALOGV("Remaining time %ldms", (long)remaining); - env->SetIntField(obj, field_mTimeoutRemainingMs, - remaining); - } - - if (n <= 0) { - if (n < 0) { - ALOGE("select() on RFCOMM socket: %s (%d)", - strerror(errno), - errno); - return -errno; - } - return 0; - } - /* n must be equal to 1 and either rset or wset must have the - file descriptor set. */ - ALOGV("select() returned %d.", n); - if (FD_ISSET(nat->rfcomm_sock, &rset) || - FD_ISSET(nat->rfcomm_sock, &wset)) - { - /* A trial async read() will tell us if everything is OK. */ - { - char ch; - errno = 0; - int nr = TEMP_FAILURE_RETRY(read(nat->rfcomm_sock, &ch, 1)); - /* It should be that nr != 1 because we just opened a socket - and we haven't sent anything over it for the other side to - respond... but one can't be paranoid enough. - */ - if (nr >= 0 || errno != EAGAIN) { - ALOGE("RFCOMM async connect() error: %s (%d), nr = %d\n", - strerror(errno), - errno, - nr); - /* Clear the rfcomm_connected flag to cause this function - to re-create the socket and re-attempt the connect() - the next time it is called. - */ - nat->rfcomm_connected = 0; - /* Restore the blocking properties of the socket. */ - fcntl(nat->rfcomm_sock, F_SETFL, nat->rfcomm_sock_flags); - close(nat->rfcomm_sock); - nat->rfcomm_sock = -1; - return -errno; - } - } - /* Restore the blocking properties of the socket. */ - fcntl(nat->rfcomm_sock, F_SETFL, nat->rfcomm_sock_flags); - ALOGI("Successful RFCOMM socket connect."); - nat->rfcomm_connected = 1; - return 1; - } - } - else ALOGE("RFCOMM socket file descriptor %d is bad!", - nat->rfcomm_sock); -#endif - return -1; -} - -static void disconnectNative(JNIEnv *env, jobject obj) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, obj); - if (nat->rfcomm_sock >= 0) { - close(nat->rfcomm_sock); - nat->rfcomm_sock = -1; - nat->rfcomm_connected = 0; - } -#endif -} - -static void pretty_log_urc(const char *urc) { - size_t i; - bool in_line_break = false; - char *buf = (char *)calloc(strlen(urc) + 1, sizeof(char)); - - strcpy(buf, urc); - for (i = 0; i < strlen(buf); i++) { - switch(buf[i]) { - case '\r': - case '\n': - in_line_break = true; - buf[i] = ' '; - break; - default: - if (in_line_break) { - in_line_break = false; - buf[i-1] = '\n'; - } - } - } - IF_ALOGV() ALOG(LOG_VERBOSE, "Bluetooth AT sent", "%s", buf); - - free(buf); -} - -static jboolean sendURCNative(JNIEnv *env, jobject obj, jstring urc) { -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, obj); - if (nat->rfcomm_connected) { - const char *c_urc = env->GetStringUTFChars(urc, NULL); - jboolean ret = send_line(nat->rfcomm_sock, c_urc) == 0 ? JNI_TRUE : JNI_FALSE; - if (ret == JNI_TRUE) pretty_log_urc(c_urc); - env->ReleaseStringUTFChars(urc, c_urc); - return ret; - } -#endif - return JNI_FALSE; -} - -static jstring readNative(JNIEnv *env, jobject obj, jint timeout_ms) { -#ifdef HAVE_BLUETOOTH - { - native_data_t *nat = get_native_data(env, obj); - if (nat->rfcomm_connected) { - char buf[256]; - const char *ret = get_line(nat->rfcomm_sock, - buf, sizeof(buf), - timeout_ms, - &nat->last_read_err); - return ret ? env->NewStringUTF(ret) : NULL; - } - return NULL; - } -#else - return NULL; -#endif -} - -static jint getLastReadStatusNative(JNIEnv *env, jobject obj) { -#ifdef HAVE_BLUETOOTH - { - native_data_t *nat = get_native_data(env, obj); - if (nat->rfcomm_connected) - return (jint)nat->last_read_err; - return 0; - } -#else - return 0; -#endif -} - -static JNINativeMethod sMethods[] = { - /* name, signature, funcPtr */ - {"classInitNative", "()V", (void*)classInitNative}, - {"initializeNativeDataNative", "(I)V", (void *)initializeNativeDataNative}, - {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative}, - {"connectNative", "()Z", (void *)connectNative}, - {"connectAsyncNative", "()I", (void *)connectAsyncNative}, - {"waitForAsyncConnectNative", "(I)I", (void *)waitForAsyncConnectNative}, - {"disconnectNative", "()V", (void *)disconnectNative}, - {"sendURCNative", "(Ljava/lang/String;)Z", (void *)sendURCNative}, - {"readNative", "(I)Ljava/lang/String;", (void *)readNative}, - {"getLastReadStatusNative", "()I", (void *)getLastReadStatusNative}, -}; - -int register_android_bluetooth_HeadsetBase(JNIEnv *env) { - return AndroidRuntime::registerNativeMethods(env, - "android/bluetooth/HeadsetBase", sMethods, NELEM(sMethods)); -} - -} /* namespace android */ diff --git a/core/jni/android_bluetooth_c.c b/core/jni/android_bluetooth_c.c deleted file mode 100644 index b4c6727..0000000 --- a/core/jni/android_bluetooth_c.c +++ /dev/null @@ -1,31 +0,0 @@ -/* -** Copyright 2011, 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. -*/ - -#ifdef HAVE_BLUETOOTH - -#include "android_bluetooth_c.h" - -/* - * A C helper for creating a bdaddr_t object with the value BDADDR_ANY. - * We have to do this in C because the macro BDADDR_ANY in bluetooth.h - * is not valid C++ code. - */ -bdaddr_t android_bluetooth_bdaddr_any(void) -{ - bdaddr_t any = *BDADDR_ANY; - return any; -} -#endif diff --git a/core/jni/android_bluetooth_c.h b/core/jni/android_bluetooth_c.h deleted file mode 100644 index e890244..0000000 --- a/core/jni/android_bluetooth_c.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -** Copyright 2010, 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. -*/ - -#ifndef ANDROID_BLUETOOTH_C_H -#define ANDROID_BLUETOOTH_C_H -#ifdef HAVE_BLUETOOTH - -#include <bluetooth/bluetooth.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * A C helper for creating a bdaddr_t object with the value BDADDR_ANY. - * We have to do this in C because the macro BDADDR_ANY in bluetooth.h - * is not valid C++ code. - */ -bdaddr_t android_bluetooth_bdaddr_any(void); - -#ifdef __cplusplus -} -#endif - -#endif /*HAVE_BLUETOOTH*/ -#endif /*ANDROID_BLUETOOTH_C_H*/ diff --git a/core/jni/android_bluetooth_common.cpp b/core/jni/android_bluetooth_common.cpp deleted file mode 100644 index 5cdaa6c..0000000 --- a/core/jni/android_bluetooth_common.cpp +++ /dev/null @@ -1,867 +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 "bluetooth_common.cpp" - -#include "android_bluetooth_common.h" -#include "JNIHelp.h" -#include "jni.h" -#include "utils/Log.h" -#include "utils/misc.h" - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> -#include <cutils/properties.h> - -#ifdef HAVE_BLUETOOTH -#include <dbus/dbus.h> -#endif - -namespace android { - -#ifdef HAVE_BLUETOOTH - -static Properties remote_device_properties[] = { - {"Address", DBUS_TYPE_STRING}, - {"Name", DBUS_TYPE_STRING}, - {"Icon", DBUS_TYPE_STRING}, - {"Class", DBUS_TYPE_UINT32}, - {"UUIDs", DBUS_TYPE_ARRAY}, - {"Services", DBUS_TYPE_ARRAY}, - {"Paired", DBUS_TYPE_BOOLEAN}, - {"Connected", DBUS_TYPE_BOOLEAN}, - {"Trusted", DBUS_TYPE_BOOLEAN}, - {"Blocked", DBUS_TYPE_BOOLEAN}, - {"Alias", DBUS_TYPE_STRING}, - {"Nodes", DBUS_TYPE_ARRAY}, - {"Adapter", DBUS_TYPE_OBJECT_PATH}, - {"LegacyPairing", DBUS_TYPE_BOOLEAN}, - {"RSSI", DBUS_TYPE_INT16}, - {"TX", DBUS_TYPE_UINT32}, - {"Broadcaster", DBUS_TYPE_BOOLEAN} -}; - -static Properties adapter_properties[] = { - {"Address", DBUS_TYPE_STRING}, - {"Name", DBUS_TYPE_STRING}, - {"Class", DBUS_TYPE_UINT32}, - {"Powered", DBUS_TYPE_BOOLEAN}, - {"Discoverable", DBUS_TYPE_BOOLEAN}, - {"DiscoverableTimeout", DBUS_TYPE_UINT32}, - {"Pairable", DBUS_TYPE_BOOLEAN}, - {"PairableTimeout", DBUS_TYPE_UINT32}, - {"Discovering", DBUS_TYPE_BOOLEAN}, - {"Devices", DBUS_TYPE_ARRAY}, - {"UUIDs", DBUS_TYPE_ARRAY}, -}; - -static Properties input_properties[] = { - {"Connected", DBUS_TYPE_BOOLEAN}, -}; - -static Properties pan_properties[] = { - {"Connected", DBUS_TYPE_BOOLEAN}, - {"Interface", DBUS_TYPE_STRING}, - {"UUID", DBUS_TYPE_STRING}, -}; - -static Properties health_device_properties[] = { - {"MainChannel", DBUS_TYPE_OBJECT_PATH}, -}; - -static Properties health_channel_properties[] = { - {"Type", DBUS_TYPE_STRING}, - {"Device", DBUS_TYPE_OBJECT_PATH}, - {"Application", DBUS_TYPE_OBJECT_PATH}, -}; - -typedef union { - char *str_val; - int int_val; - char **array_val; -} property_value; - -jfieldID get_field(JNIEnv *env, jclass clazz, const char *member, - const char *mtype) { - jfieldID field = env->GetFieldID(clazz, member, mtype); - if (field == NULL) { - ALOGE("Can't find member %s", member); - } - return field; -} - -typedef struct { - void (*user_cb)(DBusMessage *, void *, void *); - void *user; - void *nat; - JNIEnv *env; -} dbus_async_call_t; - -void dbus_func_args_async_callback(DBusPendingCall *call, void *data) { - - dbus_async_call_t *req = (dbus_async_call_t *)data; - DBusMessage *msg; - - /* This is guaranteed to be non-NULL, because this function is called only - when once the remote method invokation returns. */ - msg = dbus_pending_call_steal_reply(call); - - if (msg) { - if (req->user_cb) { - // The user may not deref the message object. - req->user_cb(msg, req->user, req->nat); - } - dbus_message_unref(msg); - } - - //dbus_message_unref(req->method); - dbus_pending_call_cancel(call); - dbus_pending_call_unref(call); - free(req); -} - -static dbus_bool_t dbus_func_args_async_valist(JNIEnv *env, - DBusConnection *conn, - int timeout_ms, - void (*user_cb)(DBusMessage *, - void *, - void*), - void *user, - void *nat, - const char *path, - const char *ifc, - const char *func, - int first_arg_type, - va_list args) { - DBusMessage *msg = NULL; - const char *name; - dbus_async_call_t *pending; - dbus_bool_t reply = FALSE; - - /* Compose the command */ - msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func); - - if (msg == NULL) { - ALOGE("Could not allocate D-Bus message object!"); - goto done; - } - - /* append arguments */ - if (!dbus_message_append_args_valist(msg, first_arg_type, args)) { - ALOGE("Could not append argument to method call!"); - goto done; - } - - /* Make the call. */ - pending = (dbus_async_call_t *)malloc(sizeof(dbus_async_call_t)); - if (pending) { - DBusPendingCall *call; - - pending->env = env; - pending->user_cb = user_cb; - pending->user = user; - pending->nat = nat; - //pending->method = msg; - - reply = dbus_connection_send_with_reply(conn, msg, - &call, - timeout_ms); - if (reply == TRUE) { - dbus_pending_call_set_notify(call, - dbus_func_args_async_callback, - pending, - NULL); - } - } - -done: - if (msg) dbus_message_unref(msg); - return reply; -} - -dbus_bool_t dbus_func_args_async(JNIEnv *env, - DBusConnection *conn, - int timeout_ms, - void (*reply)(DBusMessage *, void *, void*), - void *user, - void *nat, - const char *path, - const char *ifc, - const char *func, - int first_arg_type, - ...) { - dbus_bool_t ret; - va_list lst; - va_start(lst, first_arg_type); - - ret = dbus_func_args_async_valist(env, conn, - timeout_ms, - reply, user, nat, - path, ifc, func, - first_arg_type, lst); - va_end(lst); - return ret; -} - -// If err is NULL, then any errors will be ALOGE'd, and free'd and the reply -// will be NULL. -// If err is not NULL, then it is assumed that dbus_error_init was already -// called, and error's will be returned to the caller without logging. The -// return value is NULL iff an error was set. The client must free the error if -// set. -DBusMessage * dbus_func_args_timeout_valist(JNIEnv *env, - DBusConnection *conn, - int timeout_ms, - DBusError *err, - const char *path, - const char *ifc, - const char *func, - int first_arg_type, - va_list args) { - - DBusMessage *msg = NULL, *reply = NULL; - const char *name; - bool return_error = (err != NULL); - - if (!return_error) { - err = (DBusError*)malloc(sizeof(DBusError)); - dbus_error_init(err); - } - - /* Compose the command */ - msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func); - - if (msg == NULL) { - ALOGE("Could not allocate D-Bus message object!"); - goto done; - } - - /* append arguments */ - if (!dbus_message_append_args_valist(msg, first_arg_type, args)) { - ALOGE("Could not append argument to method call!"); - goto done; - } - - /* Make the call. */ - reply = dbus_connection_send_with_reply_and_block(conn, msg, timeout_ms, err); - if (!return_error && dbus_error_is_set(err)) { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(err, msg); - } - -done: - if (!return_error) { - free(err); - } - if (msg) dbus_message_unref(msg); - return reply; -} - -DBusMessage * dbus_func_args_timeout(JNIEnv *env, - DBusConnection *conn, - int timeout_ms, - const char *path, - const char *ifc, - const char *func, - int first_arg_type, - ...) { - DBusMessage *ret; - va_list lst; - va_start(lst, first_arg_type); - ret = dbus_func_args_timeout_valist(env, conn, timeout_ms, NULL, - path, ifc, func, - first_arg_type, lst); - va_end(lst); - return ret; -} - -DBusMessage * dbus_func_args(JNIEnv *env, - DBusConnection *conn, - const char *path, - const char *ifc, - const char *func, - int first_arg_type, - ...) { - DBusMessage *ret; - va_list lst; - va_start(lst, first_arg_type); - ret = dbus_func_args_timeout_valist(env, conn, -1, NULL, - path, ifc, func, - first_arg_type, lst); - va_end(lst); - return ret; -} - -DBusMessage * dbus_func_args_error(JNIEnv *env, - DBusConnection *conn, - DBusError *err, - const char *path, - const char *ifc, - const char *func, - int first_arg_type, - ...) { - DBusMessage *ret; - va_list lst; - va_start(lst, first_arg_type); - ret = dbus_func_args_timeout_valist(env, conn, -1, err, - path, ifc, func, - first_arg_type, lst); - va_end(lst); - return ret; -} - -jint dbus_returns_unixfd(JNIEnv *env, DBusMessage *reply) { - - DBusError err; - jint ret = -1; - - dbus_error_init(&err); - if (!dbus_message_get_args(reply, &err, - DBUS_TYPE_UNIX_FD, &ret, - DBUS_TYPE_INVALID)) { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); - } - dbus_message_unref(reply); - return ret; -} - - -jint dbus_returns_int32(JNIEnv *env, DBusMessage *reply) { - - DBusError err; - jint ret = -1; - - dbus_error_init(&err); - if (!dbus_message_get_args(reply, &err, - DBUS_TYPE_INT32, &ret, - DBUS_TYPE_INVALID)) { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); - } - dbus_message_unref(reply); - return ret; -} - -jint dbus_returns_uint32(JNIEnv *env, DBusMessage *reply) { - - DBusError err; - jint ret = -1; - - dbus_error_init(&err); - if (!dbus_message_get_args(reply, &err, - DBUS_TYPE_UINT32, &ret, - DBUS_TYPE_INVALID)) { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); - } - dbus_message_unref(reply); - return ret; -} - -jstring dbus_returns_string(JNIEnv *env, DBusMessage *reply) { - - DBusError err; - jstring ret = NULL; - const char *name; - - dbus_error_init(&err); - if (dbus_message_get_args(reply, &err, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) { - ret = env->NewStringUTF(name); - } else { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); - } - dbus_message_unref(reply); - - return ret; -} - -jboolean dbus_returns_boolean(JNIEnv *env, DBusMessage *reply) { - DBusError err; - jboolean ret = JNI_FALSE; - dbus_bool_t val = FALSE; - - dbus_error_init(&err); - - /* Check the return value. */ - if (dbus_message_get_args(reply, &err, - DBUS_TYPE_BOOLEAN, &val, - DBUS_TYPE_INVALID)) { - ret = val == TRUE ? JNI_TRUE : JNI_FALSE; - } else { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); - } - - dbus_message_unref(reply); - return ret; -} - -static void set_object_array_element(JNIEnv *env, jobjectArray strArray, - const char *value, int index) { - jstring obj; - obj = env->NewStringUTF(value); - env->SetObjectArrayElement(strArray, index, obj); - env->DeleteLocalRef(obj); -} - -jobjectArray dbus_returns_array_of_object_path(JNIEnv *env, - DBusMessage *reply) { - - DBusError err; - char **list; - int i, len; - jobjectArray strArray = NULL; - - dbus_error_init(&err); - if (dbus_message_get_args (reply, - &err, - DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, - &list, &len, - DBUS_TYPE_INVALID)) { - jclass stringClass; - jstring classNameStr; - - stringClass = env->FindClass("java/lang/String"); - strArray = env->NewObjectArray(len, stringClass, NULL); - - for (i = 0; i < len; i++) - set_object_array_element(env, strArray, list[i], i); - } else { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); - } - - dbus_message_unref(reply); - return strArray; -} - -jobjectArray dbus_returns_array_of_strings(JNIEnv *env, DBusMessage *reply) { - - DBusError err; - char **list; - int i, len; - jobjectArray strArray = NULL; - - dbus_error_init(&err); - if (dbus_message_get_args (reply, - &err, - DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &list, &len, - DBUS_TYPE_INVALID)) { - jclass stringClass; - jstring classNameStr; - - //ALOGV("%s: there are %d elements in string array!", __FUNCTION__, len); - - stringClass = env->FindClass("java/lang/String"); - strArray = env->NewObjectArray(len, stringClass, NULL); - - for (i = 0; i < len; i++) - set_object_array_element(env, strArray, list[i], i); - } else { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); - } - - dbus_message_unref(reply); - return strArray; -} - -jbyteArray dbus_returns_array_of_bytes(JNIEnv *env, DBusMessage *reply) { - - DBusError err; - int i, len; - jbyte *list; - jbyteArray byteArray = NULL; - - dbus_error_init(&err); - if (dbus_message_get_args(reply, &err, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &list, &len, - DBUS_TYPE_INVALID)) { - //ALOGV("%s: there are %d elements in byte array!", __FUNCTION__, len); - byteArray = env->NewByteArray(len); - if (byteArray) - env->SetByteArrayRegion(byteArray, 0, len, list); - - } else { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); - } - - dbus_message_unref(reply); - return byteArray; -} - -void append_variant(DBusMessageIter *iter, int type, void *val) -{ - DBusMessageIter value_iter; - char var_type[2] = { type, '\0'}; - dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, var_type, &value_iter); - dbus_message_iter_append_basic(&value_iter, type, val); - dbus_message_iter_close_container(iter, &value_iter); -} - -static void dict_append_entry(DBusMessageIter *dict, - const char *key, int type, void *val) -{ - DBusMessageIter dict_entry; - dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, - NULL, &dict_entry); - - dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &key); - append_variant(&dict_entry, type, val); - dbus_message_iter_close_container(dict, &dict_entry); -} - -static void append_dict_valist(DBusMessageIter *iterator, const char *first_key, - va_list var_args) -{ - DBusMessageIter dict; - int val_type; - const char *val_key; - void *val; - - dbus_message_iter_open_container(iterator, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - - val_key = first_key; - while (val_key) { - val_type = va_arg(var_args, int); - val = va_arg(var_args, void *); - dict_append_entry(&dict, val_key, val_type, val); - val_key = va_arg(var_args, char *); - } - - dbus_message_iter_close_container(iterator, &dict); -} - -void append_dict_args(DBusMessage *reply, const char *first_key, ...) -{ - DBusMessageIter iter; - va_list var_args; - - dbus_message_iter_init_append(reply, &iter); - - va_start(var_args, first_key); - append_dict_valist(&iter, first_key, var_args); - va_end(var_args); -} - - -int get_property(DBusMessageIter iter, Properties *properties, - int max_num_properties, int *prop_index, property_value *value, int *len) { - DBusMessageIter prop_val, array_val_iter; - char *property = NULL; - uint32_t array_type; - char *str_val; - int i, j, type, int_val; - - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) - return -1; - dbus_message_iter_get_basic(&iter, &property); - if (!dbus_message_iter_next(&iter)) - return -1; - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) - return -1; - for (i = 0; i < max_num_properties; i++) { - if (!strncmp(property, properties[i].name, strlen(property))) - break; - } - *prop_index = i; - if (i == max_num_properties) - return -1; - - dbus_message_iter_recurse(&iter, &prop_val); - type = properties[*prop_index].type; - if (dbus_message_iter_get_arg_type(&prop_val) != type) { - ALOGE("Property type mismatch in get_property: %d, expected:%d, index:%d", - dbus_message_iter_get_arg_type(&prop_val), type, *prop_index); - return -1; - } - - switch(type) { - case DBUS_TYPE_STRING: - case DBUS_TYPE_OBJECT_PATH: - dbus_message_iter_get_basic(&prop_val, &value->str_val); - *len = 1; - break; - case DBUS_TYPE_UINT32: - case DBUS_TYPE_INT16: - case DBUS_TYPE_BOOLEAN: - dbus_message_iter_get_basic(&prop_val, &int_val); - value->int_val = int_val; - *len = 1; - break; - case DBUS_TYPE_ARRAY: - dbus_message_iter_recurse(&prop_val, &array_val_iter); - array_type = dbus_message_iter_get_arg_type(&array_val_iter); - *len = 0; - value->array_val = NULL; - if (array_type == DBUS_TYPE_OBJECT_PATH || - array_type == DBUS_TYPE_STRING){ - j = 0; - do { - j ++; - } while(dbus_message_iter_next(&array_val_iter)); - dbus_message_iter_recurse(&prop_val, &array_val_iter); - // Allocate an array of char * - *len = j; - char **tmp = (char **)malloc(sizeof(char *) * *len); - if (!tmp) - return -1; - j = 0; - do { - dbus_message_iter_get_basic(&array_val_iter, &tmp[j]); - j ++; - } while(dbus_message_iter_next(&array_val_iter)); - value->array_val = tmp; - } - break; - default: - return -1; - } - return 0; -} - -void create_prop_array(JNIEnv *env, jobjectArray strArray, Properties *property, - property_value *value, int len, int *array_index ) { - char **prop_val = NULL; - char buf[32] = {'\0'}, buf1[32] = {'\0'}; - int i; - - char *name = property->name; - int prop_type = property->type; - - set_object_array_element(env, strArray, name, *array_index); - *array_index += 1; - - if (prop_type == DBUS_TYPE_UINT32 || prop_type == DBUS_TYPE_INT16) { - sprintf(buf, "%d", value->int_val); - set_object_array_element(env, strArray, buf, *array_index); - *array_index += 1; - } else if (prop_type == DBUS_TYPE_BOOLEAN) { - sprintf(buf, "%s", value->int_val ? "true" : "false"); - - set_object_array_element(env, strArray, buf, *array_index); - *array_index += 1; - } else if (prop_type == DBUS_TYPE_ARRAY) { - // Write the length first - sprintf(buf1, "%d", len); - set_object_array_element(env, strArray, buf1, *array_index); - *array_index += 1; - - prop_val = value->array_val; - for (i = 0; i < len; i++) { - set_object_array_element(env, strArray, prop_val[i], *array_index); - *array_index += 1; - } - } else { - set_object_array_element(env, strArray, (const char *) value->str_val, *array_index); - *array_index += 1; - } -} - -jobjectArray parse_properties(JNIEnv *env, DBusMessageIter *iter, Properties *properties, - const int max_num_properties) { - DBusMessageIter dict_entry, dict; - jobjectArray strArray = NULL; - property_value value; - int i, size = 0,array_index = 0; - int len = 0, prop_type = DBUS_TYPE_INVALID, prop_index = -1, type; - struct { - property_value value; - int len; - bool used; - } values[max_num_properties]; - int t, j; - - jclass stringClass = env->FindClass("java/lang/String"); - DBusError err; - dbus_error_init(&err); - - for (i = 0; i < max_num_properties; i++) { - values[i].used = false; - } - - if(dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) - goto failure; - dbus_message_iter_recurse(iter, &dict); - do { - len = 0; - if (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY) - goto failure; - dbus_message_iter_recurse(&dict, &dict_entry); - - if (!get_property(dict_entry, properties, max_num_properties, &prop_index, - &value, &len)) { - size += 2; - if (properties[prop_index].type == DBUS_TYPE_ARRAY) - size += len; - values[prop_index].value = value; - values[prop_index].len = len; - values[prop_index].used = true; - } else { - goto failure; - } - } while(dbus_message_iter_next(&dict)); - - strArray = env->NewObjectArray(size, stringClass, NULL); - - for (i = 0; i < max_num_properties; i++) { - if (values[i].used) { - create_prop_array(env, strArray, &properties[i], &values[i].value, values[i].len, - &array_index); - - if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used - && values[i].value.array_val != NULL) - free(values[i].value.array_val); - } - - } - return strArray; - -failure: - if (dbus_error_is_set(&err)) - LOG_AND_FREE_DBUS_ERROR(&err); - for (i = 0; i < max_num_properties; i++) - if (properties[i].type == DBUS_TYPE_ARRAY && values[i].used == true - && values[i].value.array_val != NULL) - free(values[i].value.array_val); - return NULL; -} - -jobjectArray parse_property_change(JNIEnv *env, DBusMessage *msg, - Properties *properties, int max_num_properties) { - DBusMessageIter iter; - DBusError err; - jobjectArray strArray = NULL; - jclass stringClass= env->FindClass("java/lang/String"); - int len = 0, prop_index = -1; - int array_index = 0, size = 0; - property_value value; - - dbus_error_init(&err); - if (!dbus_message_iter_init(msg, &iter)) - goto failure; - - if (!get_property(iter, properties, max_num_properties, - &prop_index, &value, &len)) { - size += 2; - if (properties[prop_index].type == DBUS_TYPE_ARRAY) - size += len; - strArray = env->NewObjectArray(size, stringClass, NULL); - - create_prop_array(env, strArray, &properties[prop_index], - &value, len, &array_index); - - if (properties[prop_index].type == DBUS_TYPE_ARRAY && value.array_val != NULL) - free(value.array_val); - - return strArray; - } -failure: - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - return NULL; -} - -jobjectArray parse_adapter_property_change(JNIEnv *env, DBusMessage *msg) { - return parse_property_change(env, msg, (Properties *) &adapter_properties, - sizeof(adapter_properties) / sizeof(Properties)); -} - -jobjectArray parse_remote_device_property_change(JNIEnv *env, DBusMessage *msg) { - return parse_property_change(env, msg, (Properties *) &remote_device_properties, - sizeof(remote_device_properties) / sizeof(Properties)); -} - -jobjectArray parse_input_property_change(JNIEnv *env, DBusMessage *msg) { - return parse_property_change(env, msg, (Properties *) &input_properties, - sizeof(input_properties) / sizeof(Properties)); -} - -jobjectArray parse_pan_property_change(JNIEnv *env, DBusMessage *msg) { - return parse_property_change(env, msg, (Properties *) &pan_properties, - sizeof(pan_properties) / sizeof(Properties)); -} - -jobjectArray parse_adapter_properties(JNIEnv *env, DBusMessageIter *iter) { - return parse_properties(env, iter, (Properties *) &adapter_properties, - sizeof(adapter_properties) / sizeof(Properties)); -} - -jobjectArray parse_remote_device_properties(JNIEnv *env, DBusMessageIter *iter) { - return parse_properties(env, iter, (Properties *) &remote_device_properties, - sizeof(remote_device_properties) / sizeof(Properties)); -} - -jobjectArray parse_input_properties(JNIEnv *env, DBusMessageIter *iter) { - return parse_properties(env, iter, (Properties *) &input_properties, - sizeof(input_properties) / sizeof(Properties)); -} - -jobjectArray parse_health_device_properties(JNIEnv *env, DBusMessageIter *iter) { - return parse_properties(env, iter, (Properties *) &health_device_properties, - sizeof(health_device_properties) / sizeof(Properties)); -} - -jobjectArray parse_health_device_property_change(JNIEnv *env, DBusMessage *msg) { - return parse_property_change(env, msg, (Properties *) &health_device_properties, - sizeof(health_device_properties) / sizeof(Properties)); -} - -jobjectArray parse_health_channel_properties(JNIEnv *env, DBusMessageIter *iter) { - return parse_properties(env, iter, (Properties *) &health_channel_properties, - sizeof(health_channel_properties) / sizeof(Properties)); -} - -int get_bdaddr(const char *str, bdaddr_t *ba) { - char *d = ((char *)ba) + 5, *endp; - int i; - for(i = 0; i < 6; i++) { - *d-- = strtol(str, &endp, 16); - if (*endp != ':' && i != 5) { - memset(ba, 0, sizeof(bdaddr_t)); - return -1; - } - str = endp + 1; - } - return 0; -} - -void get_bdaddr_as_string(const bdaddr_t *ba, char *str) { - const uint8_t *b = (const uint8_t *)ba; - sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", - b[5], b[4], b[3], b[2], b[1], b[0]); -} - -bool debug_no_encrypt() { - return false; -#if 0 - char value[PROPERTY_VALUE_MAX] = ""; - - property_get("debug.bt.no_encrypt", value, ""); - if (!strncmp("true", value, PROPERTY_VALUE_MAX) || - !strncmp("1", value, PROPERTY_VALUE_MAX)) { - ALOGD("mandatory bluetooth encryption disabled"); - return true; - } else { - return false; - } -#endif -} -#endif - -} /* namespace android */ diff --git a/core/jni/android_bluetooth_common.h b/core/jni/android_bluetooth_common.h deleted file mode 100644 index daf4bb2..0000000 --- a/core/jni/android_bluetooth_common.h +++ /dev/null @@ -1,215 +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. -*/ - -#ifndef ANDROID_BLUETOOTH_COMMON_H -#define ANDROID_BLUETOOTH_COMMON_H - -// Set to 0 to enable verbose bluetooth logging -#define LOG_NDEBUG 1 - -#include "jni.h" -#include "utils/Log.h" - -#include <errno.h> -#include <pthread.h> -#include <stdint.h> -#include <sys/poll.h> - -#ifdef HAVE_BLUETOOTH -#include <dbus/dbus.h> -#include <bluetooth/bluetooth.h> -#endif - -namespace android { - -#ifdef HAVE_BLUETOOTH -#define BLUEZ_DBUS_BASE_PATH "/org/bluez" -#define BLUEZ_DBUS_BASE_IFC "org.bluez" -#define BLUEZ_ERROR_IFC "org.bluez.Error" - -// It would be nicer to retrieve this from bluez using GetDefaultAdapter, -// but this is only possible when the adapter is up (and hcid is running). -// It is much easier just to hardcode bluetooth adapter to hci0 -#define BLUETOOTH_ADAPTER_HCI_NUM 0 -#define BLUEZ_ADAPTER_OBJECT_NAME BLUEZ_DBUS_BASE_PATH "/hci0" - -#define BTADDR_SIZE 18 // size of BT address character array (including null) - -// size of the dbus event loops pollfd structure, hopefully never to be grown -#define DEFAULT_INITIAL_POLLFD_COUNT 8 - -jfieldID get_field(JNIEnv *env, - jclass clazz, - const char *member, - const char *mtype); - -// ALOGE and free a D-Bus error -// Using #define so that __FUNCTION__ resolves usefully -#define LOG_AND_FREE_DBUS_ERROR_WITH_MSG(err, msg) \ - { ALOGE("%s: D-Bus error in %s: %s (%s)", __FUNCTION__, \ - dbus_message_get_member((msg)), (err)->name, (err)->message); \ - dbus_error_free((err)); } -#define LOG_AND_FREE_DBUS_ERROR(err) \ - { ALOGE("%s: D-Bus error: %s (%s)", __FUNCTION__, \ - (err)->name, (err)->message); \ - dbus_error_free((err)); } - -struct event_loop_native_data_t { - DBusConnection *conn; - const char *adapter; - - /* protects the thread */ - pthread_mutex_t thread_mutex; - pthread_t thread; - /* our comms socket */ - /* mem for the list of sockets to listen to */ - struct pollfd *pollData; - int pollMemberCount; - int pollDataSize; - /* mem for matching set of dbus watch ptrs */ - DBusWatch **watchData; - /* pair of sockets for event loop control, Reader and Writer */ - int controlFdR; - int controlFdW; - /* our vm and env Version for future env generation */ - JavaVM *vm; - int envVer; - /* reference to our java self */ - jobject me; - /* flag to indicate if the event loop thread is running */ - bool running; -}; - -struct _Properties { - char name[32]; - int type; -}; -typedef struct _Properties Properties; - -dbus_bool_t dbus_func_args_async(JNIEnv *env, - DBusConnection *conn, - int timeout_ms, - void (*reply)(DBusMessage *, void *, void *), - void *user, - void *nat, - const char *path, - const char *ifc, - const char *func, - int first_arg_type, - ...); - -DBusMessage * dbus_func_args(JNIEnv *env, - DBusConnection *conn, - const char *path, - const char *ifc, - const char *func, - int first_arg_type, - ...); - -DBusMessage * dbus_func_args_error(JNIEnv *env, - DBusConnection *conn, - DBusError *err, - const char *path, - const char *ifc, - const char *func, - int first_arg_type, - ...); - -DBusMessage * dbus_func_args_timeout(JNIEnv *env, - DBusConnection *conn, - int timeout_ms, - const char *path, - const char *ifc, - const char *func, - int first_arg_type, - ...); - -DBusMessage * dbus_func_args_timeout_valist(JNIEnv *env, - DBusConnection *conn, - int timeout_ms, - DBusError *err, - const char *path, - const char *ifc, - const char *func, - int first_arg_type, - va_list args); - -jint dbus_returns_int32(JNIEnv *env, DBusMessage *reply); -jint dbus_returns_uint32(JNIEnv *env, DBusMessage *reply); -jint dbus_returns_unixfd(JNIEnv *env, DBusMessage *reply); -jstring dbus_returns_string(JNIEnv *env, DBusMessage *reply); -jboolean dbus_returns_boolean(JNIEnv *env, DBusMessage *reply); -jobjectArray dbus_returns_array_of_strings(JNIEnv *env, DBusMessage *reply); -jobjectArray dbus_returns_array_of_object_path(JNIEnv *env, DBusMessage *reply); -jbyteArray dbus_returns_array_of_bytes(JNIEnv *env, DBusMessage *reply); - -jobjectArray parse_properties(JNIEnv *env, DBusMessageIter *iter, Properties *properties, - const int max_num_properties); -jobjectArray parse_property_change(JNIEnv *env, DBusMessage *msg, - Properties *properties, int max_num_properties); -jobjectArray parse_adapter_properties(JNIEnv *env, DBusMessageIter *iter); -jobjectArray parse_remote_device_properties(JNIEnv *env, DBusMessageIter *iter); -jobjectArray parse_remote_device_property_change(JNIEnv *env, DBusMessage *msg); -jobjectArray parse_adapter_property_change(JNIEnv *env, DBusMessage *msg); -jobjectArray parse_input_properties(JNIEnv *env, DBusMessageIter *iter); -jobjectArray parse_health_device_properties(JNIEnv *env, DBusMessageIter *iter); -jobjectArray parse_health_channel_properties(JNIEnv *env, DBusMessageIter *iter); -jobjectArray parse_input_property_change(JNIEnv *env, DBusMessage *msg); -jobjectArray parse_pan_property_change(JNIEnv *env, DBusMessage *msg); -jobjectArray parse_health_device_property_change(JNIEnv *env, DBusMessage *msg); - -void append_dict_args(DBusMessage *reply, const char *first_key, ...); -void append_variant(DBusMessageIter *iter, int type, void *val); -int get_bdaddr(const char *str, bdaddr_t *ba); -void get_bdaddr_as_string(const bdaddr_t *ba, char *str); - -bool debug_no_encrypt(); - - -// Result codes from Bluez DBus calls -#define BOND_RESULT_ERROR -1 -#define BOND_RESULT_SUCCESS 0 -#define BOND_RESULT_AUTH_FAILED 1 -#define BOND_RESULT_AUTH_REJECTED 2 -#define BOND_RESULT_AUTH_CANCELED 3 -#define BOND_RESULT_REMOTE_DEVICE_DOWN 4 -#define BOND_RESULT_DISCOVERY_IN_PROGRESS 5 -#define BOND_RESULT_AUTH_TIMEOUT 6 -#define BOND_RESULT_REPEATED_ATTEMPTS 7 - -#define PAN_DISCONNECT_FAILED_NOT_CONNECTED 1000 -#define PAN_CONNECT_FAILED_ALREADY_CONNECTED 1001 -#define PAN_CONNECT_FAILED_ATTEMPT_FAILED 1002 -#define PAN_OPERATION_GENERIC_FAILURE 1003 -#define PAN_OPERATION_SUCCESS 1004 - -#define INPUT_DISCONNECT_FAILED_NOT_CONNECTED 5000 -#define INPUT_CONNECT_FAILED_ALREADY_CONNECTED 5001 -#define INPUT_CONNECT_FAILED_ATTEMPT_FAILED 5002 -#define INPUT_OPERATION_GENERIC_FAILURE 5003 -#define INPUT_OPERATION_SUCCESS 5004 - -#define HEALTH_OPERATION_SUCCESS 6000 -#define HEALTH_OPERATION_ERROR 6001 -#define HEALTH_OPERATION_INVALID_ARGS 6002 -#define HEALTH_OPERATION_GENERIC_FAILURE 6003 -#define HEALTH_OPERATION_NOT_FOUND 6004 -#define HEALTH_OPERATION_NOT_ALLOWED 6005 - -#endif -} /* namespace android */ - -#endif/*ANDROID_BLUETOOTH_COMMON_H*/ diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp deleted file mode 100644 index d065a9e..0000000 --- a/core/jni/android_server_BluetoothA2dpService.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* -** Copyright 2008, 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 "BluetoothA2dpService.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" - -#include <ctype.h> -#include <errno.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> - -#ifdef HAVE_BLUETOOTH -#include <dbus/dbus.h> -#endif - -namespace android { - -#ifdef HAVE_BLUETOOTH -static jmethodID method_onSinkPropertyChanged; -static jmethodID method_onConnectSinkResult; - -typedef struct { - JavaVM *vm; - int envVer; - DBusConnection *conn; - jobject me; // for callbacks to java -} native_data_t; - -static native_data_t *nat = NULL; // global native data -static void onConnectSinkResult(DBusMessage *msg, void *user, void *n); - -static Properties sink_properties[] = { - {"State", DBUS_TYPE_STRING}, - {"Connected", DBUS_TYPE_BOOLEAN}, - {"Playing", DBUS_TYPE_BOOLEAN}, - }; -#endif - -/* Returns true on success (even if adapter is present but disabled). - * Return false if dbus is down, or another serious error (out of memory) -*/ -static bool initNative(JNIEnv* env, jobject object) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - nat = (native_data_t *)calloc(1, sizeof(native_data_t)); - if (NULL == nat) { - ALOGE("%s: out of memory!", __FUNCTION__); - return false; - } - env->GetJavaVM( &(nat->vm) ); - nat->envVer = env->GetVersion(); - nat->me = env->NewGlobalRef(object); - - DBusError err; - dbus_error_init(&err); - dbus_threads_init_default(); - nat->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); - if (dbus_error_is_set(&err)) { - ALOGE("Could not get onto the system bus: %s", err.message); - dbus_error_free(&err); - return false; - } - dbus_connection_set_exit_on_disconnect(nat->conn, FALSE); -#endif /*HAVE_BLUETOOTH*/ - return true; -} - -static void cleanupNative(JNIEnv* env, jobject object) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - if (nat) { - dbus_connection_close(nat->conn); - env->DeleteGlobalRef(nat->me); - free(nat); - nat = NULL; - } -#endif -} - -static jobjectArray getSinkPropertiesNative(JNIEnv *env, jobject object, - jstring path) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - if (nat) { - DBusMessage *msg, *reply; - DBusError err; - dbus_error_init(&err); - - const char *c_path = env->GetStringUTFChars(path, NULL); - reply = dbus_func_args_timeout(env, - nat->conn, -1, c_path, - "org.bluez.AudioSink", "GetProperties", - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(path, c_path); - if (!reply && dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply); - return NULL; - } else if (!reply) { - ALOGE("DBus reply is NULL in function %s", __FUNCTION__); - return NULL; - } - DBusMessageIter iter; - if (dbus_message_iter_init(reply, &iter)) - return parse_properties(env, &iter, (Properties *)&sink_properties, - sizeof(sink_properties) / sizeof(Properties)); - } -#endif - return NULL; -} - - -static jboolean connectSinkNative(JNIEnv *env, jobject object, jstring path) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - if (nat) { - const char *c_path = env->GetStringUTFChars(path, NULL); - int len = env->GetStringLength(path) + 1; - char *context_path = (char *)calloc(len, sizeof(char)); - strlcpy(context_path, c_path, len); // for callback - - bool ret = dbus_func_args_async(env, nat->conn, -1, onConnectSinkResult, context_path, - nat, c_path, "org.bluez.AudioSink", "Connect", - DBUS_TYPE_INVALID); - - env->ReleaseStringUTFChars(path, c_path); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean disconnectSinkNative(JNIEnv *env, jobject object, - jstring path) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - if (nat) { - const char *c_path = env->GetStringUTFChars(path, NULL); - - bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, - c_path, "org.bluez.AudioSink", "Disconnect", - DBUS_TYPE_INVALID); - - env->ReleaseStringUTFChars(path, c_path); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean suspendSinkNative(JNIEnv *env, jobject object, - jstring path) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - if (nat) { - const char *c_path = env->GetStringUTFChars(path, NULL); - bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, - c_path, "org.bluez.audio.Sink", "Suspend", - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(path, c_path); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean resumeSinkNative(JNIEnv *env, jobject object, - jstring path) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - if (nat) { - const char *c_path = env->GetStringUTFChars(path, NULL); - bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, - c_path, "org.bluez.audio.Sink", "Resume", - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(path, c_path); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean avrcpVolumeUpNative(JNIEnv *env, jobject object, - jstring path) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - if (nat) { - const char *c_path = env->GetStringUTFChars(path, NULL); - bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, - c_path, "org.bluez.Control", "VolumeUp", - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(path, c_path); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean avrcpVolumeDownNative(JNIEnv *env, jobject object, - jstring path) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - if (nat) { - const char *c_path = env->GetStringUTFChars(path, NULL); - bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, - c_path, "org.bluez.Control", "VolumeDown", - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(path, c_path); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -#ifdef HAVE_BLUETOOTH -DBusHandlerResult a2dp_event_filter(DBusMessage *msg, JNIEnv *env) { - DBusError err; - - if (!nat) { - ALOGV("... skipping %s\n", __FUNCTION__); - ALOGV("... ignored\n"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - dbus_error_init(&err); - - if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - if (dbus_message_is_signal(msg, "org.bluez.AudioSink", - "PropertyChanged")) { - jobjectArray str_array = - parse_property_change(env, msg, (Properties *)&sink_properties, - sizeof(sink_properties) / sizeof(Properties)); - const char *c_path = dbus_message_get_path(msg); - jstring path = env->NewStringUTF(c_path); - env->CallVoidMethod(nat->me, - method_onSinkPropertyChanged, - path, - str_array); - env->DeleteLocalRef(path); - result = DBUS_HANDLER_RESULT_HANDLED; - return result; - } else { - ALOGV("... ignored"); - } - if (env->ExceptionCheck()) { - ALOGE("VM Exception occurred while handling %s.%s (%s) in %s," - " leaving for VM", - dbus_message_get_interface(msg), dbus_message_get_member(msg), - dbus_message_get_path(msg), __FUNCTION__); - } - - return result; -} - -void onConnectSinkResult(DBusMessage *msg, void *user, void *n) { - ALOGV("%s", __FUNCTION__); - - native_data_t *nat = (native_data_t *)n; - const char *path = (const char *)user; - DBusError err; - dbus_error_init(&err); - JNIEnv *env; - nat->vm->GetEnv((void**)&env, nat->envVer); - - - bool result = JNI_TRUE; - if (dbus_set_error_from_message(&err, msg)) { - LOG_AND_FREE_DBUS_ERROR(&err); - result = JNI_FALSE; - } - ALOGV("... Device Path = %s, result = %d", path, result); - - jstring jPath = env->NewStringUTF(path); - env->CallVoidMethod(nat->me, - method_onConnectSinkResult, - jPath, - result); - env->DeleteLocalRef(jPath); - free(user); -} - - -#endif - - -static JNINativeMethod sMethods[] = { - {"initNative", "()Z", (void *)initNative}, - {"cleanupNative", "()V", (void *)cleanupNative}, - - /* Bluez audio 4.47 API */ - {"connectSinkNative", "(Ljava/lang/String;)Z", (void *)connectSinkNative}, - {"disconnectSinkNative", "(Ljava/lang/String;)Z", (void *)disconnectSinkNative}, - {"suspendSinkNative", "(Ljava/lang/String;)Z", (void*)suspendSinkNative}, - {"resumeSinkNative", "(Ljava/lang/String;)Z", (void*)resumeSinkNative}, - {"getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;", - (void *)getSinkPropertiesNative}, - {"avrcpVolumeUpNative", "(Ljava/lang/String;)Z", (void*)avrcpVolumeUpNative}, - {"avrcpVolumeDownNative", "(Ljava/lang/String;)Z", (void*)avrcpVolumeDownNative}, -}; - -int register_android_server_BluetoothA2dpService(JNIEnv *env) { - jclass clazz = env->FindClass("android/server/BluetoothA2dpService"); - if (clazz == NULL) { - ALOGE("Can't find android/server/BluetoothA2dpService"); - return -1; - } - -#ifdef HAVE_BLUETOOTH - method_onSinkPropertyChanged = env->GetMethodID(clazz, "onSinkPropertyChanged", - "(Ljava/lang/String;[Ljava/lang/String;)V"); - method_onConnectSinkResult = env->GetMethodID(clazz, "onConnectSinkResult", - "(Ljava/lang/String;Z)V"); -#endif - - return AndroidRuntime::registerNativeMethods(env, - "android/server/BluetoothA2dpService", sMethods, NELEM(sMethods)); -} - -} /* namespace android */ diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp deleted file mode 100644 index 8a69ba4..0000000 --- a/core/jni/android_server_BluetoothEventLoop.cpp +++ /dev/null @@ -1,1585 +0,0 @@ -/* -** Copyright 2008, 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 "BluetoothEventLoop.cpp" - -#include "android_bluetooth_common.h" -#include "android_runtime/AndroidRuntime.h" -#include "cutils/sockets.h" -#include "JNIHelp.h" -#include "jni.h" -#include "utils/Log.h" -#include "utils/misc.h" - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> - -#ifdef HAVE_BLUETOOTH -#include <dbus/dbus.h> -#endif - -namespace android { - -#define CREATE_DEVICE_ALREADY_EXISTS 1 -#define CREATE_DEVICE_SUCCESS 0 -#define CREATE_DEVICE_FAILED -1 - -#ifdef HAVE_BLUETOOTH -static jfieldID field_mNativeData; - -static jmethodID method_onPropertyChanged; -static jmethodID method_onDevicePropertyChanged; -static jmethodID method_onDeviceFound; -static jmethodID method_onDeviceDisappeared; -static jmethodID method_onDeviceCreated; -static jmethodID method_onDeviceRemoved; -static jmethodID method_onDeviceDisconnectRequested; -static jmethodID method_onNetworkDeviceDisconnected; -static jmethodID method_onNetworkDeviceConnected; - -static jmethodID method_onCreatePairedDeviceResult; -static jmethodID method_onCreateDeviceResult; -static jmethodID method_onDiscoverServicesResult; -static jmethodID method_onGetDeviceServiceChannelResult; - -static jmethodID method_onRequestPinCode; -static jmethodID method_onRequestPasskey; -static jmethodID method_onRequestPasskeyConfirmation; -static jmethodID method_onRequestPairingConsent; -static jmethodID method_onDisplayPasskey; -static jmethodID method_onRequestOobData; -static jmethodID method_onAgentOutOfBandDataAvailable; -static jmethodID method_onAgentAuthorize; -static jmethodID method_onAgentCancel; - -static jmethodID method_onInputDevicePropertyChanged; -static jmethodID method_onInputDeviceConnectionResult; -static jmethodID method_onPanDevicePropertyChanged; -static jmethodID method_onPanDeviceConnectionResult; -static jmethodID method_onHealthDevicePropertyChanged; -static jmethodID method_onHealthDeviceChannelChanged; -static jmethodID method_onHealthDeviceConnectionResult; - -typedef event_loop_native_data_t native_data_t; - -#define EVENT_LOOP_REFS 10 - -static inline native_data_t * get_native_data(JNIEnv *env, jobject object) { - return (native_data_t *)(env->GetIntField(object, - field_mNativeData)); -} - -native_data_t *get_EventLoop_native_data(JNIEnv *env, jobject object) { - return get_native_data(env, object); -} - -#endif -static void classInitNative(JNIEnv* env, jclass clazz) { - ALOGV("%s", __FUNCTION__); - -#ifdef HAVE_BLUETOOTH - method_onPropertyChanged = env->GetMethodID(clazz, "onPropertyChanged", - "([Ljava/lang/String;)V"); - method_onDevicePropertyChanged = env->GetMethodID(clazz, - "onDevicePropertyChanged", - "(Ljava/lang/String;[Ljava/lang/String;)V"); - method_onDeviceFound = env->GetMethodID(clazz, "onDeviceFound", - "(Ljava/lang/String;[Ljava/lang/String;)V"); - method_onDeviceDisappeared = env->GetMethodID(clazz, "onDeviceDisappeared", - "(Ljava/lang/String;)V"); - method_onDeviceCreated = env->GetMethodID(clazz, "onDeviceCreated", "(Ljava/lang/String;)V"); - method_onDeviceRemoved = env->GetMethodID(clazz, "onDeviceRemoved", "(Ljava/lang/String;)V"); - method_onDeviceDisconnectRequested = env->GetMethodID(clazz, "onDeviceDisconnectRequested", - "(Ljava/lang/String;)V"); - method_onNetworkDeviceConnected = env->GetMethodID(clazz, "onNetworkDeviceConnected", - "(Ljava/lang/String;Ljava/lang/String;I)V"); - method_onNetworkDeviceDisconnected = env->GetMethodID(clazz, "onNetworkDeviceDisconnected", - "(Ljava/lang/String;)V"); - - method_onCreatePairedDeviceResult = env->GetMethodID(clazz, "onCreatePairedDeviceResult", - "(Ljava/lang/String;I)V"); - method_onCreateDeviceResult = env->GetMethodID(clazz, "onCreateDeviceResult", - "(Ljava/lang/String;I)V"); - method_onDiscoverServicesResult = env->GetMethodID(clazz, "onDiscoverServicesResult", - "(Ljava/lang/String;Z)V"); - - method_onAgentAuthorize = env->GetMethodID(clazz, "onAgentAuthorize", - "(Ljava/lang/String;Ljava/lang/String;I)V"); - method_onAgentOutOfBandDataAvailable = env->GetMethodID(clazz, "onAgentOutOfBandDataAvailable", - "(Ljava/lang/String;)Z"); - method_onAgentCancel = env->GetMethodID(clazz, "onAgentCancel", "()V"); - method_onRequestPinCode = env->GetMethodID(clazz, "onRequestPinCode", - "(Ljava/lang/String;I)V"); - method_onRequestPasskey = env->GetMethodID(clazz, "onRequestPasskey", - "(Ljava/lang/String;I)V"); - method_onRequestPasskeyConfirmation = env->GetMethodID(clazz, "onRequestPasskeyConfirmation", - "(Ljava/lang/String;II)V"); - method_onRequestPairingConsent = env->GetMethodID(clazz, "onRequestPairingConsent", - "(Ljava/lang/String;I)V"); - method_onDisplayPasskey = env->GetMethodID(clazz, "onDisplayPasskey", - "(Ljava/lang/String;II)V"); - method_onInputDevicePropertyChanged = env->GetMethodID(clazz, "onInputDevicePropertyChanged", - "(Ljava/lang/String;[Ljava/lang/String;)V"); - method_onInputDeviceConnectionResult = env->GetMethodID(clazz, "onInputDeviceConnectionResult", - "(Ljava/lang/String;I)V"); - method_onPanDevicePropertyChanged = env->GetMethodID(clazz, "onPanDevicePropertyChanged", - "(Ljava/lang/String;[Ljava/lang/String;)V"); - method_onPanDeviceConnectionResult = env->GetMethodID(clazz, "onPanDeviceConnectionResult", - "(Ljava/lang/String;I)V"); - method_onHealthDeviceConnectionResult = env->GetMethodID(clazz, - "onHealthDeviceConnectionResult", - "(II)V"); - method_onHealthDevicePropertyChanged = env->GetMethodID(clazz, "onHealthDevicePropertyChanged", - "(Ljava/lang/String;[Ljava/lang/String;)V"); - method_onHealthDeviceChannelChanged = env->GetMethodID(clazz, "onHealthDeviceChannelChanged", - "(Ljava/lang/String;Ljava/lang/String;Z)V"); - method_onRequestOobData = env->GetMethodID(clazz, "onRequestOobData", - "(Ljava/lang/String;I)V"); - - field_mNativeData = env->GetFieldID(clazz, "mNativeData", "I"); -#endif -} - -static void initializeNativeDataNative(JNIEnv* env, jobject object) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t)); - if (NULL == nat) { - ALOGE("%s: out of memory!", __FUNCTION__); - return; - } - - pthread_mutex_init(&(nat->thread_mutex), NULL); - - env->SetIntField(object, field_mNativeData, (jint)nat); - - { - DBusError err; - dbus_error_init(&err); - dbus_threads_init_default(); - nat->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); - if (dbus_error_is_set(&err)) { - ALOGE("%s: Could not get onto the system bus!", __FUNCTION__); - dbus_error_free(&err); - } - dbus_connection_set_exit_on_disconnect(nat->conn, FALSE); - } -#endif -} - -static void cleanupNativeDataNative(JNIEnv* env, jobject object) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = - (native_data_t *)env->GetIntField(object, field_mNativeData); - - pthread_mutex_destroy(&(nat->thread_mutex)); - - if (nat) { - free(nat); - } -#endif -} - -#ifdef HAVE_BLUETOOTH -static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg, - void *data); -DBusHandlerResult agent_event_filter(DBusConnection *conn, - DBusMessage *msg, - void *data); -static int register_agent(native_data_t *nat, - const char *agent_path, const char *capabilities); - -static const DBusObjectPathVTable agent_vtable = { - NULL, agent_event_filter, NULL, NULL, NULL, NULL -}; - -static unsigned int unix_events_to_dbus_flags(short events) { - return (events & DBUS_WATCH_READABLE ? POLLIN : 0) | - (events & DBUS_WATCH_WRITABLE ? POLLOUT : 0) | - (events & DBUS_WATCH_ERROR ? POLLERR : 0) | - (events & DBUS_WATCH_HANGUP ? POLLHUP : 0); -} - -static short dbus_flags_to_unix_events(unsigned int flags) { - return (flags & POLLIN ? DBUS_WATCH_READABLE : 0) | - (flags & POLLOUT ? DBUS_WATCH_WRITABLE : 0) | - (flags & POLLERR ? DBUS_WATCH_ERROR : 0) | - (flags & POLLHUP ? DBUS_WATCH_HANGUP : 0); -} - -static jboolean setUpEventLoop(native_data_t *nat) { - ALOGV("%s", __FUNCTION__); - - if (nat != NULL && nat->conn != NULL) { - dbus_threads_init_default(); - DBusError err; - dbus_error_init(&err); - - const char *agent_path = "/android/bluetooth/agent"; - const char *capabilities = "DisplayYesNo"; - if (register_agent(nat, agent_path, capabilities) < 0) { - dbus_connection_unregister_object_path (nat->conn, agent_path); - return JNI_FALSE; - } - - // Add a filter for all incoming messages - if (!dbus_connection_add_filter(nat->conn, event_filter, nat, NULL)){ - return JNI_FALSE; - } - - // Set which messages will be processed by this dbus connection - dbus_bus_add_match(nat->conn, - "type='signal',interface='org.freedesktop.DBus'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - return JNI_FALSE; - } - dbus_bus_add_match(nat->conn, - "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Adapter'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - return JNI_FALSE; - } - dbus_bus_add_match(nat->conn, - "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Device'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - return JNI_FALSE; - } - dbus_bus_add_match(nat->conn, - "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Input'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - return JNI_FALSE; - } - dbus_bus_add_match(nat->conn, - "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Network'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - return JNI_FALSE; - } - dbus_bus_add_match(nat->conn, - "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".NetworkServer'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - return JNI_FALSE; - } - - dbus_bus_add_match(nat->conn, - "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".HealthDevice'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - return JNI_FALSE; - } - - dbus_bus_add_match(nat->conn, - "type='signal',interface='org.bluez.AudioSink'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - return JNI_FALSE; - } - - return JNI_TRUE; - } - return JNI_FALSE; -} - - -const char * get_adapter_path(DBusConnection *conn) { - DBusMessage *msg = NULL, *reply = NULL; - DBusError err; - const char *device_path = NULL; - int attempt = 0; - - for (attempt = 0; attempt < 1000 && reply == NULL; attempt ++) { - msg = dbus_message_new_method_call("org.bluez", "/", - "org.bluez.Manager", "DefaultAdapter"); - if (!msg) { - ALOGE("%s: Can't allocate new method call for get_adapter_path!", - __FUNCTION__); - return NULL; - } - dbus_message_append_args(msg, DBUS_TYPE_INVALID); - dbus_error_init(&err); - reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err); - - if (!reply) { - if (dbus_error_is_set(&err)) { - if (dbus_error_has_name(&err, - "org.freedesktop.DBus.Error.ServiceUnknown")) { - // bluetoothd is still down, retry - LOG_AND_FREE_DBUS_ERROR(&err); - usleep(10000); // 10 ms - continue; - } else { - // Some other error we weren't expecting - LOG_AND_FREE_DBUS_ERROR(&err); - } - } - goto failed; - } - } - if (attempt == 1000) { - ALOGE("Time out while trying to get Adapter path, is bluetoothd up ?"); - goto failed; - } - - if (!dbus_message_get_args(reply, &err, DBUS_TYPE_OBJECT_PATH, - &device_path, DBUS_TYPE_INVALID) - || !device_path){ - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - goto failed; - } - dbus_message_unref(msg); - return device_path; - -failed: - dbus_message_unref(msg); - return NULL; -} - -static int register_agent(native_data_t *nat, - const char * agent_path, const char * capabilities) -{ - DBusMessage *msg, *reply; - DBusError err; - dbus_bool_t oob = TRUE; - - if (!dbus_connection_register_object_path(nat->conn, agent_path, - &agent_vtable, nat)) { - ALOGE("%s: Can't register object path %s for agent!", - __FUNCTION__, agent_path); - return -1; - } - - nat->adapter = get_adapter_path(nat->conn); - if (nat->adapter == NULL) { - return -1; - } - msg = dbus_message_new_method_call("org.bluez", nat->adapter, - "org.bluez.Adapter", "RegisterAgent"); - if (!msg) { - ALOGE("%s: Can't allocate new method call for agent!", - __FUNCTION__); - return -1; - } - dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent_path, - DBUS_TYPE_STRING, &capabilities, - DBUS_TYPE_INVALID); - - dbus_error_init(&err); - reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err); - dbus_message_unref(msg); - - if (!reply) { - ALOGE("%s: Can't register agent!", __FUNCTION__); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - return -1; - } - - dbus_message_unref(reply); - dbus_connection_flush(nat->conn); - - return 0; -} - -static void tearDownEventLoop(native_data_t *nat) { - ALOGV("%s", __FUNCTION__); - if (nat != NULL && nat->conn != NULL) { - - DBusMessage *msg, *reply; - DBusError err; - dbus_error_init(&err); - const char * agent_path = "/android/bluetooth/agent"; - - msg = dbus_message_new_method_call("org.bluez", - nat->adapter, - "org.bluez.Adapter", - "UnregisterAgent"); - if (msg != NULL) { - dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &agent_path, - DBUS_TYPE_INVALID); - reply = dbus_connection_send_with_reply_and_block(nat->conn, - msg, -1, &err); - - if (!reply) { - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - dbus_error_free(&err); - } - } else { - dbus_message_unref(reply); - } - dbus_message_unref(msg); - } else { - ALOGE("%s: Can't create new method call!", __FUNCTION__); - } - - dbus_connection_flush(nat->conn); - dbus_connection_unregister_object_path(nat->conn, agent_path); - - dbus_bus_remove_match(nat->conn, - "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".AudioSink'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - dbus_bus_remove_match(nat->conn, - "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Device'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - dbus_bus_remove_match(nat->conn, - "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Input'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - dbus_bus_remove_match(nat->conn, - "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Network'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - dbus_bus_remove_match(nat->conn, - "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".NetworkServer'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - dbus_bus_remove_match(nat->conn, - "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".HealthDevice'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - dbus_bus_remove_match(nat->conn, - "type='signal',interface='org.bluez.audio.Manager'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - dbus_bus_remove_match(nat->conn, - "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Adapter'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - dbus_bus_remove_match(nat->conn, - "type='signal',interface='org.freedesktop.DBus'", - &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - - dbus_connection_remove_filter(nat->conn, event_filter, nat); - } -} - - -#define EVENT_LOOP_EXIT 1 -#define EVENT_LOOP_ADD 2 -#define EVENT_LOOP_REMOVE 3 -#define EVENT_LOOP_WAKEUP 4 - -dbus_bool_t dbusAddWatch(DBusWatch *watch, void *data) { - native_data_t *nat = (native_data_t *)data; - - if (dbus_watch_get_enabled(watch)) { - // note that we can't just send the watch and inspect it later - // because we may get a removeWatch call before this data is reacted - // to by our eventloop and remove this watch.. reading the add first - // and then inspecting the recently deceased watch would be bad. - char control = EVENT_LOOP_ADD; - write(nat->controlFdW, &control, sizeof(char)); - - int fd = dbus_watch_get_fd(watch); - write(nat->controlFdW, &fd, sizeof(int)); - - unsigned int flags = dbus_watch_get_flags(watch); - write(nat->controlFdW, &flags, sizeof(unsigned int)); - - write(nat->controlFdW, &watch, sizeof(DBusWatch*)); - } - return true; -} - -void dbusRemoveWatch(DBusWatch *watch, void *data) { - native_data_t *nat = (native_data_t *)data; - - char control = EVENT_LOOP_REMOVE; - write(nat->controlFdW, &control, sizeof(char)); - - int fd = dbus_watch_get_fd(watch); - write(nat->controlFdW, &fd, sizeof(int)); - - unsigned int flags = dbus_watch_get_flags(watch); - write(nat->controlFdW, &flags, sizeof(unsigned int)); -} - -void dbusToggleWatch(DBusWatch *watch, void *data) { - if (dbus_watch_get_enabled(watch)) { - dbusAddWatch(watch, data); - } else { - dbusRemoveWatch(watch, data); - } -} - -void dbusWakeup(void *data) { - native_data_t *nat = (native_data_t *)data; - - char control = EVENT_LOOP_WAKEUP; - write(nat->controlFdW, &control, sizeof(char)); -} - -static void handleWatchAdd(native_data_t *nat) { - DBusWatch *watch; - int newFD; - unsigned int flags; - - read(nat->controlFdR, &newFD, sizeof(int)); - read(nat->controlFdR, &flags, sizeof(unsigned int)); - read(nat->controlFdR, &watch, sizeof(DBusWatch *)); - short events = dbus_flags_to_unix_events(flags); - - for (int y = 0; y<nat->pollMemberCount; y++) { - if ((nat->pollData[y].fd == newFD) && - (nat->pollData[y].events == events)) { - ALOGV("DBusWatch duplicate add"); - return; - } - } - if (nat->pollMemberCount == nat->pollDataSize) { - ALOGV("Bluetooth EventLoop poll struct growing"); - struct pollfd *temp = (struct pollfd *)malloc( - sizeof(struct pollfd) * (nat->pollMemberCount+1)); - if (!temp) { - return; - } - memcpy(temp, nat->pollData, sizeof(struct pollfd) * - nat->pollMemberCount); - free(nat->pollData); - nat->pollData = temp; - DBusWatch **temp2 = (DBusWatch **)malloc(sizeof(DBusWatch *) * - (nat->pollMemberCount+1)); - if (!temp2) { - return; - } - memcpy(temp2, nat->watchData, sizeof(DBusWatch *) * - nat->pollMemberCount); - free(nat->watchData); - nat->watchData = temp2; - nat->pollDataSize++; - } - nat->pollData[nat->pollMemberCount].fd = newFD; - nat->pollData[nat->pollMemberCount].revents = 0; - nat->pollData[nat->pollMemberCount].events = events; - nat->watchData[nat->pollMemberCount] = watch; - nat->pollMemberCount++; -} - -static void handleWatchRemove(native_data_t *nat) { - int removeFD; - unsigned int flags; - - read(nat->controlFdR, &removeFD, sizeof(int)); - read(nat->controlFdR, &flags, sizeof(unsigned int)); - short events = dbus_flags_to_unix_events(flags); - - for (int y = 0; y < nat->pollMemberCount; y++) { - if ((nat->pollData[y].fd == removeFD) && - (nat->pollData[y].events == events)) { - int newCount = --nat->pollMemberCount; - // copy the last live member over this one - nat->pollData[y].fd = nat->pollData[newCount].fd; - nat->pollData[y].events = nat->pollData[newCount].events; - nat->pollData[y].revents = nat->pollData[newCount].revents; - nat->watchData[y] = nat->watchData[newCount]; - return; - } - } - ALOGW("WatchRemove given with unknown watch"); -} - -static void *eventLoopMain(void *ptr) { - native_data_t *nat = (native_data_t *)ptr; - JNIEnv *env; - - JavaVMAttachArgs args; - char name[] = "BT EventLoop"; - args.version = nat->envVer; - args.name = name; - args.group = NULL; - - nat->vm->AttachCurrentThread(&env, &args); - - dbus_connection_set_watch_functions(nat->conn, dbusAddWatch, - dbusRemoveWatch, dbusToggleWatch, ptr, NULL); - dbus_connection_set_wakeup_main_function(nat->conn, dbusWakeup, ptr, NULL); - - nat->running = true; - - while (1) { - for (int i = 0; i < nat->pollMemberCount; i++) { - if (!nat->pollData[i].revents) { - continue; - } - if (nat->pollData[i].fd == nat->controlFdR) { - char data; - while (recv(nat->controlFdR, &data, sizeof(char), MSG_DONTWAIT) - != -1) { - switch (data) { - case EVENT_LOOP_EXIT: - { - dbus_connection_set_watch_functions(nat->conn, - NULL, NULL, NULL, NULL, NULL); - tearDownEventLoop(nat); - nat->vm->DetachCurrentThread(); - - int fd = nat->controlFdR; - nat->controlFdR = 0; - close(fd); - return NULL; - } - case EVENT_LOOP_ADD: - { - handleWatchAdd(nat); - break; - } - case EVENT_LOOP_REMOVE: - { - handleWatchRemove(nat); - break; - } - case EVENT_LOOP_WAKEUP: - { - // noop - break; - } - } - } - } else { - short events = nat->pollData[i].revents; - unsigned int flags = unix_events_to_dbus_flags(events); - dbus_watch_handle(nat->watchData[i], flags); - nat->pollData[i].revents = 0; - // can only do one - it may have caused a 'remove' - break; - } - } - while (dbus_connection_dispatch(nat->conn) == - DBUS_DISPATCH_DATA_REMAINS) { - } - - poll(nat->pollData, nat->pollMemberCount, -1); - } -} -#endif // HAVE_BLUETOOTH - -static jboolean startEventLoopNative(JNIEnv *env, jobject object) { - jboolean result = JNI_FALSE; -#ifdef HAVE_BLUETOOTH - event_loop_native_data_t *nat = get_native_data(env, object); - - pthread_mutex_lock(&(nat->thread_mutex)); - - nat->running = false; - - if (nat->pollData) { - ALOGW("trying to start EventLoop a second time!"); - pthread_mutex_unlock( &(nat->thread_mutex) ); - return JNI_FALSE; - } - - nat->pollData = (struct pollfd *)calloc( - DEFAULT_INITIAL_POLLFD_COUNT, sizeof(struct pollfd)); - if (!nat->pollData) { - ALOGE("out of memory error starting EventLoop!"); - goto done; - } - - nat->watchData = (DBusWatch **)calloc( - DEFAULT_INITIAL_POLLFD_COUNT, sizeof(DBusWatch *)); - if (!nat->watchData) { - ALOGE("out of memory error starting EventLoop!"); - goto done; - } - - nat->pollDataSize = DEFAULT_INITIAL_POLLFD_COUNT; - nat->pollMemberCount = 1; - - if (socketpair(AF_LOCAL, SOCK_STREAM, 0, &(nat->controlFdR))) { - ALOGE("Error getting BT control socket"); - goto done; - } - nat->pollData[0].fd = nat->controlFdR; - nat->pollData[0].events = POLLIN; - - env->GetJavaVM( &(nat->vm) ); - nat->envVer = env->GetVersion(); - - nat->me = env->NewGlobalRef(object); - - if (setUpEventLoop(nat) != JNI_TRUE) { - ALOGE("failure setting up Event Loop!"); - goto done; - } - - pthread_create(&(nat->thread), NULL, eventLoopMain, nat); - result = JNI_TRUE; - -done: - if (JNI_FALSE == result) { - if (nat->controlFdW) { - close(nat->controlFdW); - nat->controlFdW = 0; - } - if (nat->controlFdR) { - close(nat->controlFdR); - nat->controlFdR = 0; - } - if (nat->me) env->DeleteGlobalRef(nat->me); - nat->me = NULL; - if (nat->pollData) free(nat->pollData); - nat->pollData = NULL; - if (nat->watchData) free(nat->watchData); - nat->watchData = NULL; - nat->pollDataSize = 0; - nat->pollMemberCount = 0; - } - - pthread_mutex_unlock(&(nat->thread_mutex)); -#endif // HAVE_BLUETOOTH - return result; -} - -static void stopEventLoopNative(JNIEnv *env, jobject object) { -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - - pthread_mutex_lock(&(nat->thread_mutex)); - if (nat->pollData) { - char data = EVENT_LOOP_EXIT; - ssize_t t = write(nat->controlFdW, &data, sizeof(char)); - void *ret; - pthread_join(nat->thread, &ret); - - env->DeleteGlobalRef(nat->me); - nat->me = NULL; - free(nat->pollData); - nat->pollData = NULL; - free(nat->watchData); - nat->watchData = NULL; - nat->pollDataSize = 0; - nat->pollMemberCount = 0; - - int fd = nat->controlFdW; - nat->controlFdW = 0; - close(fd); - } - nat->running = false; - pthread_mutex_unlock(&(nat->thread_mutex)); -#endif // HAVE_BLUETOOTH -} - -static jboolean isEventLoopRunningNative(JNIEnv *env, jobject object) { - jboolean result = JNI_FALSE; -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - - pthread_mutex_lock(&(nat->thread_mutex)); - if (nat->running) { - result = JNI_TRUE; - } - pthread_mutex_unlock(&(nat->thread_mutex)); - -#endif // HAVE_BLUETOOTH - return result; -} - -#ifdef HAVE_BLUETOOTH -extern DBusHandlerResult a2dp_event_filter(DBusMessage *msg, JNIEnv *env); - -// Called by dbus during WaitForAndDispatchEventNative() -static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg, - void *data) { - native_data_t *nat; - JNIEnv *env; - DBusError err; - DBusHandlerResult ret; - - dbus_error_init(&err); - - nat = (native_data_t *)data; - nat->vm->GetEnv((void**)&env, nat->envVer); - if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) { - ALOGV("%s: not interested (not a signal).", __FUNCTION__); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - ALOGV("%s: Received signal %s:%s from %s", __FUNCTION__, - dbus_message_get_interface(msg), dbus_message_get_member(msg), - dbus_message_get_path(msg)); - - env->PushLocalFrame(EVENT_LOOP_REFS); - if (dbus_message_is_signal(msg, - "org.bluez.Adapter", - "DeviceFound")) { - char *c_address; - DBusMessageIter iter; - jobjectArray str_array = NULL; - if (dbus_message_iter_init(msg, &iter)) { - dbus_message_iter_get_basic(&iter, &c_address); - if (dbus_message_iter_next(&iter)) - str_array = - parse_remote_device_properties(env, &iter); - } - if (str_array != NULL) { - env->CallVoidMethod(nat->me, - method_onDeviceFound, - env->NewStringUTF(c_address), - str_array); - } else - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - goto success; - } else if (dbus_message_is_signal(msg, - "org.bluez.Adapter", - "DeviceDisappeared")) { - char *c_address; - if (dbus_message_get_args(msg, &err, - DBUS_TYPE_STRING, &c_address, - DBUS_TYPE_INVALID)) { - ALOGV("... address = %s", c_address); - env->CallVoidMethod(nat->me, method_onDeviceDisappeared, - env->NewStringUTF(c_address)); - } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - goto success; - } else if (dbus_message_is_signal(msg, - "org.bluez.Adapter", - "DeviceCreated")) { - char *c_object_path; - if (dbus_message_get_args(msg, &err, - DBUS_TYPE_OBJECT_PATH, &c_object_path, - DBUS_TYPE_INVALID)) { - ALOGV("... address = %s", c_object_path); - env->CallVoidMethod(nat->me, - method_onDeviceCreated, - env->NewStringUTF(c_object_path)); - } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - goto success; - } else if (dbus_message_is_signal(msg, - "org.bluez.Adapter", - "DeviceRemoved")) { - char *c_object_path; - if (dbus_message_get_args(msg, &err, - DBUS_TYPE_OBJECT_PATH, &c_object_path, - DBUS_TYPE_INVALID)) { - ALOGV("... Object Path = %s", c_object_path); - env->CallVoidMethod(nat->me, - method_onDeviceRemoved, - env->NewStringUTF(c_object_path)); - } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - goto success; - } else if (dbus_message_is_signal(msg, - "org.bluez.Adapter", - "PropertyChanged")) { - jobjectArray str_array = parse_adapter_property_change(env, msg); - if (str_array != NULL) { - /* Check if bluetoothd has (re)started, if so update the path. */ - jstring property =(jstring) env->GetObjectArrayElement(str_array, 0); - const char *c_property = env->GetStringUTFChars(property, NULL); - if (!strncmp(c_property, "Powered", strlen("Powered"))) { - jstring value = - (jstring) env->GetObjectArrayElement(str_array, 1); - const char *c_value = env->GetStringUTFChars(value, NULL); - if (!strncmp(c_value, "true", strlen("true"))) - nat->adapter = get_adapter_path(nat->conn); - env->ReleaseStringUTFChars(value, c_value); - } - env->ReleaseStringUTFChars(property, c_property); - - env->CallVoidMethod(nat->me, - method_onPropertyChanged, - str_array); - } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - goto success; - } else if (dbus_message_is_signal(msg, - "org.bluez.Device", - "PropertyChanged")) { - jobjectArray str_array = parse_remote_device_property_change(env, msg); - if (str_array != NULL) { - const char *remote_device_path = dbus_message_get_path(msg); - env->CallVoidMethod(nat->me, - method_onDevicePropertyChanged, - env->NewStringUTF(remote_device_path), - str_array); - } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - goto success; - } else if (dbus_message_is_signal(msg, - "org.bluez.Device", - "DisconnectRequested")) { - const char *remote_device_path = dbus_message_get_path(msg); - env->CallVoidMethod(nat->me, - method_onDeviceDisconnectRequested, - env->NewStringUTF(remote_device_path)); - goto success; - } else if (dbus_message_is_signal(msg, - "org.bluez.Input", - "PropertyChanged")) { - - jobjectArray str_array = - parse_input_property_change(env, msg); - if (str_array != NULL) { - const char *c_path = dbus_message_get_path(msg); - env->CallVoidMethod(nat->me, - method_onInputDevicePropertyChanged, - env->NewStringUTF(c_path), - str_array); - } else { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - } - goto success; - } else if (dbus_message_is_signal(msg, - "org.bluez.Network", - "PropertyChanged")) { - - jobjectArray str_array = - parse_pan_property_change(env, msg); - if (str_array != NULL) { - const char *c_path = dbus_message_get_path(msg); - env->CallVoidMethod(nat->me, - method_onPanDevicePropertyChanged, - env->NewStringUTF(c_path), - str_array); - } else { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - } - goto success; - } else if (dbus_message_is_signal(msg, - "org.bluez.NetworkServer", - "DeviceDisconnected")) { - char *c_address; - if (dbus_message_get_args(msg, &err, - DBUS_TYPE_STRING, &c_address, - DBUS_TYPE_INVALID)) { - env->CallVoidMethod(nat->me, - method_onNetworkDeviceDisconnected, - env->NewStringUTF(c_address)); - } else { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - } - goto success; - } else if (dbus_message_is_signal(msg, - "org.bluez.NetworkServer", - "DeviceConnected")) { - char *c_address; - char *c_iface; - uint16_t uuid; - - if (dbus_message_get_args(msg, &err, - DBUS_TYPE_STRING, &c_address, - DBUS_TYPE_STRING, &c_iface, - DBUS_TYPE_UINT16, &uuid, - DBUS_TYPE_INVALID)) { - env->CallVoidMethod(nat->me, - method_onNetworkDeviceConnected, - env->NewStringUTF(c_address), - env->NewStringUTF(c_iface), - uuid); - } else { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - } - goto success; - } else if (dbus_message_is_signal(msg, - "org.bluez.HealthDevice", - "ChannelConnected")) { - const char *c_path = dbus_message_get_path(msg); - const char *c_channel_path; - jboolean exists = JNI_TRUE; - if (dbus_message_get_args(msg, &err, - DBUS_TYPE_OBJECT_PATH, &c_channel_path, - DBUS_TYPE_INVALID)) { - env->CallVoidMethod(nat->me, - method_onHealthDeviceChannelChanged, - env->NewStringUTF(c_path), - env->NewStringUTF(c_channel_path), - exists); - } else { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - } - goto success; - } else if (dbus_message_is_signal(msg, - "org.bluez.HealthDevice", - "ChannelDeleted")) { - - const char *c_path = dbus_message_get_path(msg); - const char *c_channel_path; - jboolean exists = JNI_FALSE; - if (dbus_message_get_args(msg, &err, - DBUS_TYPE_OBJECT_PATH, &c_channel_path, - DBUS_TYPE_INVALID)) { - env->CallVoidMethod(nat->me, - method_onHealthDeviceChannelChanged, - env->NewStringUTF(c_path), - env->NewStringUTF(c_channel_path), - exists); - } else { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - } - goto success; - } else if (dbus_message_is_signal(msg, - "org.bluez.HealthDevice", - "PropertyChanged")) { - jobjectArray str_array = - parse_health_device_property_change(env, msg); - if (str_array != NULL) { - const char *c_path = dbus_message_get_path(msg); - env->CallVoidMethod(nat->me, - method_onHealthDevicePropertyChanged, - env->NewStringUTF(c_path), - str_array); - } else { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - } - goto success; - } - - ret = a2dp_event_filter(msg, env); - env->PopLocalFrame(NULL); - return ret; - -success: - env->PopLocalFrame(NULL); - return DBUS_HANDLER_RESULT_HANDLED; -} - -// Called by dbus during WaitForAndDispatchEventNative() -DBusHandlerResult agent_event_filter(DBusConnection *conn, - DBusMessage *msg, void *data) { - native_data_t *nat = (native_data_t *)data; - JNIEnv *env; - if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL) { - ALOGV("%s: not interested (not a method call).", __FUNCTION__); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - ALOGI("%s: Received method %s:%s", __FUNCTION__, - dbus_message_get_interface(msg), dbus_message_get_member(msg)); - - if (nat == NULL) return DBUS_HANDLER_RESULT_HANDLED; - - nat->vm->GetEnv((void**)&env, nat->envVer); - env->PushLocalFrame(EVENT_LOOP_REFS); - - if (dbus_message_is_method_call(msg, - "org.bluez.Agent", "Cancel")) { - env->CallVoidMethod(nat->me, method_onAgentCancel); - // reply - DBusMessage *reply = dbus_message_new_method_return(msg); - if (!reply) { - ALOGE("%s: Cannot create message reply\n", __FUNCTION__); - goto failure; - } - dbus_connection_send(nat->conn, reply, NULL); - dbus_message_unref(reply); - goto success; - - } else if (dbus_message_is_method_call(msg, - "org.bluez.Agent", "Authorize")) { - char *object_path; - const char *uuid; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_OBJECT_PATH, &object_path, - DBUS_TYPE_STRING, &uuid, - DBUS_TYPE_INVALID)) { - ALOGE("%s: Invalid arguments for Authorize() method", __FUNCTION__); - goto failure; - } - - ALOGV("... object_path = %s", object_path); - ALOGV("... uuid = %s", uuid); - - dbus_message_ref(msg); // increment refcount because we pass to java - env->CallVoidMethod(nat->me, method_onAgentAuthorize, - env->NewStringUTF(object_path), env->NewStringUTF(uuid), - int(msg)); - - goto success; - } else if (dbus_message_is_method_call(msg, - "org.bluez.Agent", "OutOfBandAvailable")) { - char *object_path; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_OBJECT_PATH, &object_path, - DBUS_TYPE_INVALID)) { - ALOGE("%s: Invalid arguments for OutOfBandData available() method", __FUNCTION__); - goto failure; - } - - ALOGV("... object_path = %s", object_path); - - bool available = - env->CallBooleanMethod(nat->me, method_onAgentOutOfBandDataAvailable, - env->NewStringUTF(object_path)); - - - // reply - if (available) { - DBusMessage *reply = dbus_message_new_method_return(msg); - if (!reply) { - ALOGE("%s: Cannot create message reply\n", __FUNCTION__); - goto failure; - } - dbus_connection_send(nat->conn, reply, NULL); - dbus_message_unref(reply); - } else { - DBusMessage *reply = dbus_message_new_error(msg, - "org.bluez.Error.DoesNotExist", "OutofBand data not available"); - if (!reply) { - ALOGE("%s: Cannot create message reply\n", __FUNCTION__); - goto failure; - } - dbus_connection_send(nat->conn, reply, NULL); - dbus_message_unref(reply); - } - goto success; - } else if (dbus_message_is_method_call(msg, - "org.bluez.Agent", "RequestPinCode")) { - char *object_path; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_OBJECT_PATH, &object_path, - DBUS_TYPE_INVALID)) { - ALOGE("%s: Invalid arguments for RequestPinCode() method", __FUNCTION__); - goto failure; - } - - dbus_message_ref(msg); // increment refcount because we pass to java - env->CallVoidMethod(nat->me, method_onRequestPinCode, - env->NewStringUTF(object_path), - int(msg)); - goto success; - } else if (dbus_message_is_method_call(msg, - "org.bluez.Agent", "RequestPasskey")) { - char *object_path; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_OBJECT_PATH, &object_path, - DBUS_TYPE_INVALID)) { - ALOGE("%s: Invalid arguments for RequestPasskey() method", __FUNCTION__); - goto failure; - } - - dbus_message_ref(msg); // increment refcount because we pass to java - env->CallVoidMethod(nat->me, method_onRequestPasskey, - env->NewStringUTF(object_path), - int(msg)); - goto success; - } else if (dbus_message_is_method_call(msg, - "org.bluez.Agent", "RequestOobData")) { - char *object_path; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_OBJECT_PATH, &object_path, - DBUS_TYPE_INVALID)) { - ALOGE("%s: Invalid arguments for RequestOobData() method", __FUNCTION__); - goto failure; - } - - dbus_message_ref(msg); // increment refcount because we pass to java - env->CallVoidMethod(nat->me, method_onRequestOobData, - env->NewStringUTF(object_path), - int(msg)); - goto success; - } else if (dbus_message_is_method_call(msg, - "org.bluez.Agent", "DisplayPasskey")) { - char *object_path; - uint32_t passkey; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_OBJECT_PATH, &object_path, - DBUS_TYPE_UINT32, &passkey, - DBUS_TYPE_INVALID)) { - ALOGE("%s: Invalid arguments for RequestPasskey() method", __FUNCTION__); - goto failure; - } - - dbus_message_ref(msg); // increment refcount because we pass to java - env->CallVoidMethod(nat->me, method_onDisplayPasskey, - env->NewStringUTF(object_path), - passkey, - int(msg)); - goto success; - } else if (dbus_message_is_method_call(msg, - "org.bluez.Agent", "RequestConfirmation")) { - char *object_path; - uint32_t passkey; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_OBJECT_PATH, &object_path, - DBUS_TYPE_UINT32, &passkey, - DBUS_TYPE_INVALID)) { - ALOGE("%s: Invalid arguments for RequestConfirmation() method", __FUNCTION__); - goto failure; - } - - dbus_message_ref(msg); // increment refcount because we pass to java - env->CallVoidMethod(nat->me, method_onRequestPasskeyConfirmation, - env->NewStringUTF(object_path), - passkey, - int(msg)); - goto success; - } else if (dbus_message_is_method_call(msg, - "org.bluez.Agent", "RequestPairingConsent")) { - char *object_path; - if (!dbus_message_get_args(msg, NULL, - DBUS_TYPE_OBJECT_PATH, &object_path, - DBUS_TYPE_INVALID)) { - ALOGE("%s: Invalid arguments for RequestPairingConsent() method", __FUNCTION__); - goto failure; - } - - dbus_message_ref(msg); // increment refcount because we pass to java - env->CallVoidMethod(nat->me, method_onRequestPairingConsent, - env->NewStringUTF(object_path), - int(msg)); - goto success; - } else if (dbus_message_is_method_call(msg, - "org.bluez.Agent", "Release")) { - // reply - DBusMessage *reply = dbus_message_new_method_return(msg); - if (!reply) { - ALOGE("%s: Cannot create message reply\n", __FUNCTION__); - goto failure; - } - dbus_connection_send(nat->conn, reply, NULL); - dbus_message_unref(reply); - goto success; - } else { - ALOGV("%s:%s is ignored", dbus_message_get_interface(msg), dbus_message_get_member(msg)); - } - -failure: - env->PopLocalFrame(NULL); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - -success: - env->PopLocalFrame(NULL); - return DBUS_HANDLER_RESULT_HANDLED; - -} -#endif - - -#ifdef HAVE_BLUETOOTH - -void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *n) { - ALOGV("%s", __FUNCTION__); - - native_data_t *nat = (native_data_t *)n; - const char *address = (const char *)user; - DBusError err; - dbus_error_init(&err); - JNIEnv *env; - jstring addr; - - nat->vm->GetEnv((void**)&env, nat->envVer); - - ALOGV("... address = %s", address); - - jint result = BOND_RESULT_SUCCESS; - if (dbus_set_error_from_message(&err, msg)) { - if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationFailed")) { - // Pins did not match, or remote device did not respond to pin - // request in time - ALOGV("... error = %s (%s)\n", err.name, err.message); - result = BOND_RESULT_AUTH_FAILED; - } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationRejected")) { - // We rejected pairing, or the remote side rejected pairing. This - // happens if either side presses 'cancel' at the pairing dialog. - ALOGV("... error = %s (%s)\n", err.name, err.message); - result = BOND_RESULT_AUTH_REJECTED; - } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationCanceled")) { - // Not sure if this happens - ALOGV("... error = %s (%s)\n", err.name, err.message); - result = BOND_RESULT_AUTH_CANCELED; - } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.ConnectionAttemptFailed")) { - // Other device is not responding at all - ALOGV("... error = %s (%s)\n", err.name, err.message); - result = BOND_RESULT_REMOTE_DEVICE_DOWN; - } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AlreadyExists")) { - // already bonded - ALOGV("... error = %s (%s)\n", err.name, err.message); - result = BOND_RESULT_SUCCESS; - } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.InProgress") && - !strcmp(err.message, "Bonding in progress")) { - ALOGV("... error = %s (%s)\n", err.name, err.message); - goto done; - } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.InProgress") && - !strcmp(err.message, "Discover in progress")) { - ALOGV("... error = %s (%s)\n", err.name, err.message); - result = BOND_RESULT_DISCOVERY_IN_PROGRESS; - } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.RepeatedAttempts")) { - ALOGV("... error = %s (%s)\n", err.name, err.message); - result = BOND_RESULT_REPEATED_ATTEMPTS; - } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationTimeout")) { - ALOGV("... error = %s (%s)\n", err.name, err.message); - result = BOND_RESULT_AUTH_TIMEOUT; - } else { - ALOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message); - result = BOND_RESULT_ERROR; - } - } - - addr = env->NewStringUTF(address); - env->CallVoidMethod(nat->me, - method_onCreatePairedDeviceResult, - addr, - result); - env->DeleteLocalRef(addr); -done: - dbus_error_free(&err); - free(user); -} - -void onCreateDeviceResult(DBusMessage *msg, void *user, void *n) { - ALOGV("%s", __FUNCTION__); - - native_data_t *nat = (native_data_t *)n; - const char *address= (const char *)user; - DBusError err; - dbus_error_init(&err); - JNIEnv *env; - nat->vm->GetEnv((void**)&env, nat->envVer); - - ALOGV("... Address = %s", address); - - jint result = CREATE_DEVICE_SUCCESS; - if (dbus_set_error_from_message(&err, msg)) { - if (dbus_error_has_name(&err, "org.bluez.Error.AlreadyExists")) { - result = CREATE_DEVICE_ALREADY_EXISTS; - } else { - result = CREATE_DEVICE_FAILED; - } - LOG_AND_FREE_DBUS_ERROR(&err); - } - jstring addr = env->NewStringUTF(address); - env->CallVoidMethod(nat->me, - method_onCreateDeviceResult, - addr, - result); - env->DeleteLocalRef(addr); - free(user); -} - -void onDiscoverServicesResult(DBusMessage *msg, void *user, void *n) { - ALOGV("%s", __FUNCTION__); - - native_data_t *nat = (native_data_t *)n; - const char *path = (const char *)user; - DBusError err; - dbus_error_init(&err); - JNIEnv *env; - nat->vm->GetEnv((void**)&env, nat->envVer); - - ALOGV("... Device Path = %s", path); - - bool result = JNI_TRUE; - if (dbus_set_error_from_message(&err, msg)) { - LOG_AND_FREE_DBUS_ERROR(&err); - result = JNI_FALSE; - } - jstring jPath = env->NewStringUTF(path); - env->CallVoidMethod(nat->me, - method_onDiscoverServicesResult, - jPath, - result); - env->DeleteLocalRef(jPath); - free(user); -} - -void onGetDeviceServiceChannelResult(DBusMessage *msg, void *user, void *n) { - ALOGV("%s", __FUNCTION__); - - const char *address = (const char *) user; - native_data_t *nat = (native_data_t *) n; - - DBusError err; - dbus_error_init(&err); - JNIEnv *env; - nat->vm->GetEnv((void**)&env, nat->envVer); - - jint channel = -2; - - ALOGV("... address = %s", address); - - if (dbus_set_error_from_message(&err, msg) || - !dbus_message_get_args(msg, &err, - DBUS_TYPE_INT32, &channel, - DBUS_TYPE_INVALID)) { - ALOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message); - dbus_error_free(&err); - } - -done: - jstring addr = env->NewStringUTF(address); - env->CallVoidMethod(nat->me, - method_onGetDeviceServiceChannelResult, - addr, - channel); - env->DeleteLocalRef(addr); - free(user); -} - -void onInputDeviceConnectionResult(DBusMessage *msg, void *user, void *n) { - ALOGV("%s", __FUNCTION__); - - native_data_t *nat = (native_data_t *)n; - const char *path = (const char *)user; - DBusError err; - dbus_error_init(&err); - JNIEnv *env; - nat->vm->GetEnv((void**)&env, nat->envVer); - - jint result = INPUT_OPERATION_SUCCESS; - if (dbus_set_error_from_message(&err, msg)) { - if (!strcmp(err.name, BLUEZ_ERROR_IFC ".ConnectionAttemptFailed")) { - result = INPUT_CONNECT_FAILED_ATTEMPT_FAILED; - } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".AlreadyConnected")) { - result = INPUT_CONNECT_FAILED_ALREADY_CONNECTED; - } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".Failed")) { - // TODO():This is flaky, need to change Bluez to add new error codes - if (!strcmp(err.message, "Transport endpoint is not connected")) { - result = INPUT_DISCONNECT_FAILED_NOT_CONNECTED; - } else { - result = INPUT_OPERATION_GENERIC_FAILURE; - } - } else { - result = INPUT_OPERATION_GENERIC_FAILURE; - } - LOG_AND_FREE_DBUS_ERROR(&err); - } - - ALOGV("... Device Path = %s, result = %d", path, result); - jstring jPath = env->NewStringUTF(path); - env->CallVoidMethod(nat->me, - method_onInputDeviceConnectionResult, - jPath, - result); - env->DeleteLocalRef(jPath); - free(user); -} - -void onPanDeviceConnectionResult(DBusMessage *msg, void *user, void *n) { - ALOGV("%s", __FUNCTION__); - - native_data_t *nat = (native_data_t *)n; - const char *path = (const char *)user; - DBusError err; - dbus_error_init(&err); - JNIEnv *env; - nat->vm->GetEnv((void**)&env, nat->envVer); - - jint result = PAN_OPERATION_SUCCESS; - if (dbus_set_error_from_message(&err, msg)) { - if (!strcmp(err.name, BLUEZ_ERROR_IFC ".ConnectionAttemptFailed")) { - result = PAN_CONNECT_FAILED_ATTEMPT_FAILED; - } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".Failed")) { - // TODO():This is flaky, need to change Bluez to add new error codes - if (!strcmp(err.message, "Device already connected")) { - result = PAN_CONNECT_FAILED_ALREADY_CONNECTED; - } else if (!strcmp(err.message, "Device not connected")) { - result = PAN_DISCONNECT_FAILED_NOT_CONNECTED; - } else { - result = PAN_OPERATION_GENERIC_FAILURE; - } - } else { - result = PAN_OPERATION_GENERIC_FAILURE; - } - LOG_AND_FREE_DBUS_ERROR(&err); - } - - ALOGV("... Pan Device Path = %s, result = %d", path, result); - jstring jPath = env->NewStringUTF(path); - env->CallVoidMethod(nat->me, - method_onPanDeviceConnectionResult, - jPath, - result); - env->DeleteLocalRef(jPath); - free(user); -} - -void onHealthDeviceConnectionResult(DBusMessage *msg, void *user, void *n) { - ALOGV("%s", __FUNCTION__); - - native_data_t *nat = (native_data_t *)n; - DBusError err; - dbus_error_init(&err); - JNIEnv *env; - nat->vm->GetEnv((void**)&env, nat->envVer); - - jint result = HEALTH_OPERATION_SUCCESS; - if (dbus_set_error_from_message(&err, msg)) { - if (!strcmp(err.name, BLUEZ_ERROR_IFC ".InvalidArgs")) { - result = HEALTH_OPERATION_INVALID_ARGS; - } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".HealthError")) { - result = HEALTH_OPERATION_ERROR; - } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".NotFound")) { - result = HEALTH_OPERATION_NOT_FOUND; - } else if (!strcmp(err.name, BLUEZ_ERROR_IFC ".NotAllowed")) { - result = HEALTH_OPERATION_NOT_ALLOWED; - } else { - result = HEALTH_OPERATION_GENERIC_FAILURE; - } - LOG_AND_FREE_DBUS_ERROR(&err); - } - - jint code = *(int *) user; - ALOGV("... Health Device Code = %d, result = %d", code, result); - env->CallVoidMethod(nat->me, - method_onHealthDeviceConnectionResult, - code, - result); - free(user); -} -#endif - -static JNINativeMethod sMethods[] = { - /* name, signature, funcPtr */ - {"classInitNative", "()V", (void *)classInitNative}, - {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative}, - {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative}, - {"startEventLoopNative", "()V", (void *)startEventLoopNative}, - {"stopEventLoopNative", "()V", (void *)stopEventLoopNative}, - {"isEventLoopRunningNative", "()Z", (void *)isEventLoopRunningNative} -}; - -int register_android_server_BluetoothEventLoop(JNIEnv *env) { - return AndroidRuntime::registerNativeMethods(env, - "android/server/BluetoothEventLoop", sMethods, NELEM(sMethods)); -} - -} /* namespace android */ diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp deleted file mode 100644 index 6c11121..0000000 --- a/core/jni/android_server_BluetoothService.cpp +++ /dev/null @@ -1,1785 +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 DBUS_ADAPTER_IFACE BLUEZ_DBUS_BASE_IFC ".Adapter" -#define DBUS_DEVICE_IFACE BLUEZ_DBUS_BASE_IFC ".Device" -#define DBUS_INPUT_IFACE BLUEZ_DBUS_BASE_IFC ".Input" -#define DBUS_NETWORK_IFACE BLUEZ_DBUS_BASE_IFC ".Network" -#define DBUS_NETWORKSERVER_IFACE BLUEZ_DBUS_BASE_IFC ".NetworkServer" -#define DBUS_HEALTH_MANAGER_PATH "/org/bluez" -#define DBUS_HEALTH_MANAGER_IFACE BLUEZ_DBUS_BASE_IFC ".HealthManager" -#define DBUS_HEALTH_DEVICE_IFACE BLUEZ_DBUS_BASE_IFC ".HealthDevice" -#define DBUS_HEALTH_CHANNEL_IFACE BLUEZ_DBUS_BASE_IFC ".HealthChannel" - -#define LOG_TAG "BluetoothService.cpp" - -#include "android_bluetooth_common.h" -#include "android_runtime/AndroidRuntime.h" -#include "android_util_Binder.h" -#include "JNIHelp.h" -#include "jni.h" -#include "utils/Log.h" -#include "utils/misc.h" - -#include <ctype.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> - -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <fcntl.h> - -#ifdef HAVE_BLUETOOTH -#include <dbus/dbus.h> -#include <bluedroid/bluetooth.h> -#endif - -#include <cutils/properties.h> - -namespace android { - -#define BLUETOOTH_CLASS_ERROR 0xFF000000 -#define PROPERTIES_NREFS 10 - -#ifdef HAVE_BLUETOOTH -// We initialize these variables when we load class -// android.server.BluetoothService -static jfieldID field_mNativeData; -static jfieldID field_mEventLoop; - -typedef struct { - JNIEnv *env; - DBusConnection *conn; - const char *adapter; // dbus object name of the local adapter -} native_data_t; - -extern event_loop_native_data_t *get_EventLoop_native_data(JNIEnv *, - jobject); -extern DBusHandlerResult agent_event_filter(DBusConnection *conn, - DBusMessage *msg, - void *data); -void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *nat); -void onDiscoverServicesResult(DBusMessage *msg, void *user, void *nat); -void onCreateDeviceResult(DBusMessage *msg, void *user, void *nat); -void onInputDeviceConnectionResult(DBusMessage *msg, void *user, void *nat); -void onPanDeviceConnectionResult(DBusMessage *msg, void *user, void *nat); -void onHealthDeviceConnectionResult(DBusMessage *msg, void *user, void *nat); - - -/** Get native data stored in the opaque (Java code maintained) pointer mNativeData - * Perform quick sanity check, if there are any problems return NULL - */ -static inline native_data_t * get_native_data(JNIEnv *env, jobject object) { - native_data_t *nat = - (native_data_t *)(env->GetIntField(object, field_mNativeData)); - if (nat == NULL || nat->conn == NULL) { - ALOGE("Uninitialized native data\n"); - return NULL; - } - return nat; -} -#endif - -static void classInitNative(JNIEnv* env, jclass clazz) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - field_mNativeData = get_field(env, clazz, "mNativeData", "I"); - field_mEventLoop = get_field(env, clazz, "mEventLoop", - "Landroid/server/BluetoothEventLoop;"); -#endif -} - -/* Returns true on success (even if adapter is present but disabled). - * Return false if dbus is down, or another serious error (out of memory) -*/ -static bool initializeNativeDataNative(JNIEnv* env, jobject object) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t)); - if (NULL == nat) { - ALOGE("%s: out of memory!", __FUNCTION__); - return false; - } - nat->env = env; - - env->SetIntField(object, field_mNativeData, (jint)nat); - DBusError err; - dbus_error_init(&err); - dbus_threads_init_default(); - nat->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); - if (dbus_error_is_set(&err)) { - ALOGE("Could not get onto the system bus: %s", err.message); - dbus_error_free(&err); - return false; - } - dbus_connection_set_exit_on_disconnect(nat->conn, FALSE); -#endif /*HAVE_BLUETOOTH*/ - return true; -} - -static const char *get_adapter_path(JNIEnv* env, jobject object) { -#ifdef HAVE_BLUETOOTH - event_loop_native_data_t *event_nat = - get_EventLoop_native_data(env, env->GetObjectField(object, - field_mEventLoop)); - if (event_nat == NULL) - return NULL; - return event_nat->adapter; -#else - return NULL; -#endif -} - -// This function is called when the adapter is enabled. -static jboolean setupNativeDataNative(JNIEnv* env, jobject object) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = - (native_data_t *)env->GetIntField(object, field_mNativeData); - event_loop_native_data_t *event_nat = - get_EventLoop_native_data(env, env->GetObjectField(object, - field_mEventLoop)); - // Register agent for remote devices. - const char *device_agent_path = "/android/bluetooth/remote_device_agent"; - static const DBusObjectPathVTable agent_vtable = { - NULL, agent_event_filter, NULL, NULL, NULL, NULL }; - - if (!dbus_connection_register_object_path(nat->conn, device_agent_path, - &agent_vtable, event_nat)) { - ALOGE("%s: Can't register object path %s for remote device agent!", - __FUNCTION__, device_agent_path); - return JNI_FALSE; - } -#endif /*HAVE_BLUETOOTH*/ - return JNI_TRUE; -} - -static jboolean tearDownNativeDataNative(JNIEnv *env, jobject object) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = - (native_data_t *)env->GetIntField(object, field_mNativeData); - if (nat != NULL) { - const char *device_agent_path = - "/android/bluetooth/remote_device_agent"; - dbus_connection_unregister_object_path (nat->conn, device_agent_path); - } -#endif /*HAVE_BLUETOOTH*/ - return JNI_TRUE; -} - -static void cleanupNativeDataNative(JNIEnv* env, jobject object) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = - (native_data_t *)env->GetIntField(object, field_mNativeData); - if (nat) { - free(nat); - nat = NULL; - } -#endif -} - -static jstring getAdapterPathNative(JNIEnv *env, jobject object) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - return (env->NewStringUTF(get_adapter_path(env, object))); - } -#endif - return NULL; -} - - -static jboolean startDiscoveryNative(JNIEnv *env, jobject object) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - DBusMessage *msg = NULL; - DBusMessage *reply = NULL; - DBusError err; - const char *name; - jboolean ret = JNI_FALSE; - - native_data_t *nat = get_native_data(env, object); - if (nat == NULL) { - goto done; - } - - dbus_error_init(&err); - - /* Compose the command */ - msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, - get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, "StartDiscovery"); - - if (msg == NULL) { - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - } - goto done; - } - - /* Send the command. */ - reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err); - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - ret = JNI_FALSE; - goto done; - } - - ret = JNI_TRUE; -done: - if (reply) dbus_message_unref(reply); - if (msg) dbus_message_unref(msg); - return ret; -#else - return JNI_FALSE; -#endif -} - -static jboolean stopDiscoveryNative(JNIEnv *env, jobject object) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - DBusMessage *msg = NULL; - DBusMessage *reply = NULL; - DBusError err; - const char *name; - native_data_t *nat; - jboolean ret = JNI_FALSE; - - dbus_error_init(&err); - - nat = get_native_data(env, object); - if (nat == NULL) { - goto done; - } - - /* Compose the command */ - msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, - get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, "StopDiscovery"); - if (msg == NULL) { - if (dbus_error_is_set(&err)) - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - goto done; - } - - /* Send the command. */ - reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err); - if (dbus_error_is_set(&err)) { - if(strncmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.NotAuthorized", - strlen(BLUEZ_DBUS_BASE_IFC ".Error.NotAuthorized")) == 0) { - // hcid sends this if there is no active discovery to cancel - ALOGV("%s: There was no active discovery to cancel", __FUNCTION__); - dbus_error_free(&err); - } else { - LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); - } - goto done; - } - - ret = JNI_TRUE; -done: - if (msg) dbus_message_unref(msg); - if (reply) dbus_message_unref(reply); - return ret; -#else - return JNI_FALSE; -#endif -} - -static jbyteArray readAdapterOutOfBandDataNative(JNIEnv *env, jobject object) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - DBusError err; - jbyte *hash, *randomizer; - jbyteArray byteArray = NULL; - int hash_len, r_len; - if (nat) { - DBusMessage *reply = dbus_func_args(env, nat->conn, - get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, "ReadLocalOutOfBandData", - DBUS_TYPE_INVALID); - if (!reply) return NULL; - - dbus_error_init(&err); - if (dbus_message_get_args(reply, &err, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, &hash_len, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, &r_len, - DBUS_TYPE_INVALID)) { - if (hash_len == 16 && r_len == 16) { - byteArray = env->NewByteArray(32); - if (byteArray) { - env->SetByteArrayRegion(byteArray, 0, 16, hash); - env->SetByteArrayRegion(byteArray, 16, 16, randomizer); - } - } else { - ALOGE("readAdapterOutOfBandDataNative: Hash len = %d, R len = %d", - hash_len, r_len); - } - } else { - LOG_AND_FREE_DBUS_ERROR(&err); - } - dbus_message_unref(reply); - return byteArray; - } -#endif - return NULL; -} - -static jboolean createPairedDeviceNative(JNIEnv *env, jobject object, - jstring address, jint timeout_ms) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - jobject eventLoop = env->GetObjectField(object, field_mEventLoop); - struct event_loop_native_data_t *eventLoopNat = - get_EventLoop_native_data(env, eventLoop); - - if (nat && eventLoopNat) { - const char *c_address = env->GetStringUTFChars(address, NULL); - ALOGV("... address = %s", c_address); - char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char)); - const char *capabilities = "DisplayYesNo"; - const char *agent_path = "/android/bluetooth/remote_device_agent"; - - strlcpy(context_address, c_address, BTADDR_SIZE); // for callback - bool ret = dbus_func_args_async(env, nat->conn, (int)timeout_ms, - onCreatePairedDeviceResult, // callback - context_address, - eventLoopNat, - get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, - "CreatePairedDevice", - DBUS_TYPE_STRING, &c_address, - DBUS_TYPE_OBJECT_PATH, &agent_path, - DBUS_TYPE_STRING, &capabilities, - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(address, c_address); - return ret ? JNI_TRUE : JNI_FALSE; - - } -#endif - return JNI_FALSE; -} - -static jboolean createPairedDeviceOutOfBandNative(JNIEnv *env, jobject object, - jstring address, jint timeout_ms) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - jobject eventLoop = env->GetObjectField(object, field_mEventLoop); - struct event_loop_native_data_t *eventLoopNat = - get_EventLoop_native_data(env, eventLoop); - - if (nat && eventLoopNat) { - const char *c_address = env->GetStringUTFChars(address, NULL); - ALOGV("... address = %s", c_address); - char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char)); - const char *capabilities = "DisplayYesNo"; - const char *agent_path = "/android/bluetooth/remote_device_agent"; - - strlcpy(context_address, c_address, BTADDR_SIZE); // for callback - bool ret = dbus_func_args_async(env, nat->conn, (int)timeout_ms, - onCreatePairedDeviceResult, // callback - context_address, - eventLoopNat, - get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, - "CreatePairedDeviceOutOfBand", - DBUS_TYPE_STRING, &c_address, - DBUS_TYPE_OBJECT_PATH, &agent_path, - DBUS_TYPE_STRING, &capabilities, - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(address, c_address); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jint getDeviceServiceChannelNative(JNIEnv *env, jobject object, - jstring path, - jstring pattern, jint attr_id) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - native_data_t *nat = get_native_data(env, object); - jobject eventLoop = env->GetObjectField(object, field_mEventLoop); - struct event_loop_native_data_t *eventLoopNat = - get_EventLoop_native_data(env, eventLoop); - if (nat && eventLoopNat) { - const char *c_pattern = env->GetStringUTFChars(pattern, NULL); - const char *c_path = env->GetStringUTFChars(path, NULL); - ALOGV("... pattern = %s", c_pattern); - ALOGV("... attr_id = %#X", attr_id); - DBusMessage *reply = - dbus_func_args(env, nat->conn, c_path, - DBUS_DEVICE_IFACE, "GetServiceAttributeValue", - DBUS_TYPE_STRING, &c_pattern, - DBUS_TYPE_UINT16, &attr_id, - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(pattern, c_pattern); - env->ReleaseStringUTFChars(path, c_path); - return reply ? dbus_returns_int32(env, reply) : -1; - } -#endif - return -1; -} - -static jboolean cancelDeviceCreationNative(JNIEnv *env, jobject object, - jstring address) { - ALOGV("%s", __FUNCTION__); - jboolean result = JNI_FALSE; -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - const char *c_address = env->GetStringUTFChars(address, NULL); - DBusError err; - dbus_error_init(&err); - ALOGV("... address = %s", c_address); - DBusMessage *reply = - dbus_func_args_timeout(env, nat->conn, -1, - get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, "CancelDeviceCreation", - DBUS_TYPE_STRING, &c_address, - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(address, c_address); - if (!reply) { - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } else - ALOGE("DBus reply is NULL in function %s", __FUNCTION__); - return JNI_FALSE; - } else { - result = JNI_TRUE; - } - dbus_message_unref(reply); - } -#endif - return JNI_FALSE; -} - -static jboolean removeDeviceNative(JNIEnv *env, jobject object, jstring object_path) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - const char *c_object_path = env->GetStringUTFChars(object_path, NULL); - bool ret = dbus_func_args_async(env, nat->conn, -1, - NULL, - NULL, - NULL, - get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, - "RemoveDevice", - DBUS_TYPE_OBJECT_PATH, &c_object_path, - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(object_path, c_object_path); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jint enableNative(JNIEnv *env, jobject object) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - return bt_enable(); -#endif - return -1; -} - -static jint disableNative(JNIEnv *env, jobject object) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - return bt_disable(); -#endif - return -1; -} - -static jint isEnabledNative(JNIEnv *env, jobject object) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - return bt_is_enabled(); -#endif - return -1; -} - -static jboolean setPairingConfirmationNative(JNIEnv *env, jobject object, - jstring address, bool confirm, - int nativeData) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - native_data_t *nat = get_native_data(env, object); - if (nat) { - DBusMessage *msg = (DBusMessage *)nativeData; - DBusMessage *reply; - if (confirm) { - reply = dbus_message_new_method_return(msg); - } else { - reply = dbus_message_new_error(msg, - "org.bluez.Error.Rejected", "User rejected confirmation"); - } - - if (!reply) { - ALOGE("%s: Cannot create message reply to RequestPasskeyConfirmation or" - "RequestPairingConsent to D-Bus\n", __FUNCTION__); - dbus_message_unref(msg); - return JNI_FALSE; - } - - dbus_connection_send(nat->conn, reply, NULL); - dbus_message_unref(msg); - dbus_message_unref(reply); - return JNI_TRUE; - } -#endif - return JNI_FALSE; -} - -static jboolean setPasskeyNative(JNIEnv *env, jobject object, jstring address, - int passkey, int nativeData) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - native_data_t *nat = get_native_data(env, object); - if (nat) { - DBusMessage *msg = (DBusMessage *)nativeData; - DBusMessage *reply = dbus_message_new_method_return(msg); - if (!reply) { - ALOGE("%s: Cannot create message reply to return Passkey code to " - "D-Bus\n", __FUNCTION__); - dbus_message_unref(msg); - return JNI_FALSE; - } - - dbus_message_append_args(reply, DBUS_TYPE_UINT32, (uint32_t *)&passkey, - DBUS_TYPE_INVALID); - - dbus_connection_send(nat->conn, reply, NULL); - dbus_message_unref(msg); - dbus_message_unref(reply); - return JNI_TRUE; - } -#endif - return JNI_FALSE; -} - -static jboolean setRemoteOutOfBandDataNative(JNIEnv *env, jobject object, jstring address, - jbyteArray hash, jbyteArray randomizer, int nativeData) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - native_data_t *nat = get_native_data(env, object); - if (nat) { - DBusMessage *msg = (DBusMessage *)nativeData; - DBusMessage *reply = dbus_message_new_method_return(msg); - jbyte *h_ptr = env->GetByteArrayElements(hash, NULL); - jbyte *r_ptr = env->GetByteArrayElements(randomizer, NULL); - if (!reply) { - ALOGE("%s: Cannot create message reply to return remote OOB data to " - "D-Bus\n", __FUNCTION__); - dbus_message_unref(msg); - return JNI_FALSE; - } - - dbus_message_append_args(reply, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &h_ptr, 16, - DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &r_ptr, 16, - DBUS_TYPE_INVALID); - - env->ReleaseByteArrayElements(hash, h_ptr, 0); - env->ReleaseByteArrayElements(randomizer, r_ptr, 0); - - dbus_connection_send(nat->conn, reply, NULL); - dbus_message_unref(msg); - dbus_message_unref(reply); - return JNI_TRUE; - } -#endif - return JNI_FALSE; -} - -static jboolean setAuthorizationNative(JNIEnv *env, jobject object, jstring address, - jboolean val, int nativeData) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - native_data_t *nat = get_native_data(env, object); - if (nat) { - DBusMessage *msg = (DBusMessage *)nativeData; - DBusMessage *reply; - if (val) { - reply = dbus_message_new_method_return(msg); - } else { - reply = dbus_message_new_error(msg, - "org.bluez.Error.Rejected", "Authorization rejected"); - } - if (!reply) { - ALOGE("%s: Cannot create message reply D-Bus\n", __FUNCTION__); - dbus_message_unref(msg); - return JNI_FALSE; - } - - dbus_connection_send(nat->conn, reply, NULL); - dbus_message_unref(msg); - dbus_message_unref(reply); - return JNI_TRUE; - } -#endif - return JNI_FALSE; -} - -static jboolean setPinNative(JNIEnv *env, jobject object, jstring address, - jstring pin, int nativeData) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - native_data_t *nat = get_native_data(env, object); - if (nat) { - DBusMessage *msg = (DBusMessage *)nativeData; - DBusMessage *reply = dbus_message_new_method_return(msg); - if (!reply) { - ALOGE("%s: Cannot create message reply to return PIN code to " - "D-Bus\n", __FUNCTION__); - dbus_message_unref(msg); - return JNI_FALSE; - } - - const char *c_pin = env->GetStringUTFChars(pin, NULL); - - dbus_message_append_args(reply, DBUS_TYPE_STRING, &c_pin, - DBUS_TYPE_INVALID); - - dbus_connection_send(nat->conn, reply, NULL); - dbus_message_unref(msg); - dbus_message_unref(reply); - env->ReleaseStringUTFChars(pin, c_pin); - return JNI_TRUE; - } -#endif - return JNI_FALSE; -} - -static jboolean cancelPairingUserInputNative(JNIEnv *env, jobject object, - jstring address, int nativeData) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - native_data_t *nat = get_native_data(env, object); - if (nat) { - DBusMessage *msg = (DBusMessage *)nativeData; - DBusMessage *reply = dbus_message_new_error(msg, - "org.bluez.Error.Canceled", "Pairing User Input was canceled"); - if (!reply) { - ALOGE("%s: Cannot create message reply to return cancelUserInput to" - "D-BUS\n", __FUNCTION__); - dbus_message_unref(msg); - return JNI_FALSE; - } - - dbus_connection_send(nat->conn, reply, NULL); - dbus_message_unref(msg); - dbus_message_unref(reply); - return JNI_TRUE; - } -#endif - return JNI_FALSE; -} - -static jobjectArray getDevicePropertiesNative(JNIEnv *env, jobject object, - jstring path) -{ -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - native_data_t *nat = get_native_data(env, object); - if (nat) { - DBusMessage *msg, *reply; - DBusError err; - dbus_error_init(&err); - - const char *c_path = env->GetStringUTFChars(path, NULL); - reply = dbus_func_args_timeout(env, - nat->conn, -1, c_path, - DBUS_DEVICE_IFACE, "GetProperties", - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(path, c_path); - - if (!reply) { - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } else - ALOGE("DBus reply is NULL in function %s", __FUNCTION__); - return NULL; - } - env->PushLocalFrame(PROPERTIES_NREFS); - - DBusMessageIter iter; - jobjectArray str_array = NULL; - if (dbus_message_iter_init(reply, &iter)) - str_array = parse_remote_device_properties(env, &iter); - dbus_message_unref(reply); - - return (jobjectArray) env->PopLocalFrame(str_array); - } -#endif - return NULL; -} - -static jobjectArray getAdapterPropertiesNative(JNIEnv *env, jobject object) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - native_data_t *nat = get_native_data(env, object); - if (nat) { - DBusMessage *msg, *reply; - DBusError err; - dbus_error_init(&err); - - reply = dbus_func_args_timeout(env, - nat->conn, -1, get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, "GetProperties", - DBUS_TYPE_INVALID); - if (!reply) { - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } else - ALOGE("DBus reply is NULL in function %s", __FUNCTION__); - return NULL; - } - env->PushLocalFrame(PROPERTIES_NREFS); - - DBusMessageIter iter; - jobjectArray str_array = NULL; - if (dbus_message_iter_init(reply, &iter)) - str_array = parse_adapter_properties(env, &iter); - dbus_message_unref(reply); - - return (jobjectArray) env->PopLocalFrame(str_array); - } -#endif - return NULL; -} - -static jboolean setAdapterPropertyNative(JNIEnv *env, jobject object, jstring key, - void *value, jint type) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - native_data_t *nat = get_native_data(env, object); - if (nat) { - DBusMessage *msg; - DBusMessageIter iter; - dbus_bool_t reply = JNI_FALSE; - const char *c_key = env->GetStringUTFChars(key, NULL); - - msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, - get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, "SetProperty"); - if (!msg) { - ALOGE("%s: Can't allocate new method call for GetProperties!", - __FUNCTION__); - env->ReleaseStringUTFChars(key, c_key); - return JNI_FALSE; - } - - dbus_message_append_args(msg, DBUS_TYPE_STRING, &c_key, DBUS_TYPE_INVALID); - dbus_message_iter_init_append(msg, &iter); - append_variant(&iter, type, value); - - // Asynchronous call - the callbacks come via propertyChange - reply = dbus_connection_send_with_reply(nat->conn, msg, NULL, -1); - dbus_message_unref(msg); - - env->ReleaseStringUTFChars(key, c_key); - return reply ? JNI_TRUE : JNI_FALSE; - - } -#endif - return JNI_FALSE; -} - -static jboolean setAdapterPropertyStringNative(JNIEnv *env, jobject object, jstring key, - jstring value) { -#ifdef HAVE_BLUETOOTH - const char *c_value = env->GetStringUTFChars(value, NULL); - jboolean ret = setAdapterPropertyNative(env, object, key, (void *)&c_value, DBUS_TYPE_STRING); - env->ReleaseStringUTFChars(value, (char *)c_value); - return ret; -#else - return JNI_FALSE; -#endif -} - -static jboolean setAdapterPropertyIntegerNative(JNIEnv *env, jobject object, jstring key, - jint value) { -#ifdef HAVE_BLUETOOTH - return setAdapterPropertyNative(env, object, key, (void *)&value, DBUS_TYPE_UINT32); -#else - return JNI_FALSE; -#endif -} - -static jboolean setAdapterPropertyBooleanNative(JNIEnv *env, jobject object, jstring key, - jint value) { -#ifdef HAVE_BLUETOOTH - return setAdapterPropertyNative(env, object, key, (void *)&value, DBUS_TYPE_BOOLEAN); -#else - return JNI_FALSE; -#endif -} - -static jboolean setDevicePropertyNative(JNIEnv *env, jobject object, jstring path, - jstring key, void *value, jint type) { -#ifdef HAVE_BLUETOOTH - ALOGV("%s", __FUNCTION__); - native_data_t *nat = get_native_data(env, object); - if (nat) { - DBusMessage *msg; - DBusMessageIter iter; - dbus_bool_t reply = JNI_FALSE; - - const char *c_key = env->GetStringUTFChars(key, NULL); - const char *c_path = env->GetStringUTFChars(path, NULL); - - msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, - c_path, DBUS_DEVICE_IFACE, "SetProperty"); - if (!msg) { - ALOGE("%s: Can't allocate new method call for device SetProperty!", __FUNCTION__); - env->ReleaseStringUTFChars(key, c_key); - env->ReleaseStringUTFChars(path, c_path); - return JNI_FALSE; - } - - dbus_message_append_args(msg, DBUS_TYPE_STRING, &c_key, DBUS_TYPE_INVALID); - dbus_message_iter_init_append(msg, &iter); - append_variant(&iter, type, value); - - // Asynchronous call - the callbacks come via Device propertyChange - reply = dbus_connection_send_with_reply(nat->conn, msg, NULL, -1); - dbus_message_unref(msg); - - env->ReleaseStringUTFChars(path, c_path); - env->ReleaseStringUTFChars(key, c_key); - - return reply ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean setDevicePropertyBooleanNative(JNIEnv *env, jobject object, - jstring path, jstring key, jint value) { -#ifdef HAVE_BLUETOOTH - return setDevicePropertyNative(env, object, path, key, - (void *)&value, DBUS_TYPE_BOOLEAN); -#else - return JNI_FALSE; -#endif -} - -static jboolean setDevicePropertyStringNative(JNIEnv *env, jobject object, - jstring path, jstring key, jstring value) { -#ifdef HAVE_BLUETOOTH - const char *c_value = env->GetStringUTFChars(value, NULL); - jboolean ret = setDevicePropertyNative(env, object, path, key, - (void *)&c_value, DBUS_TYPE_STRING); - env->ReleaseStringUTFChars(value, (char *)c_value); - return ret; -#else - return JNI_FALSE; -#endif -} - -static jboolean createDeviceNative(JNIEnv *env, jobject object, - jstring address) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - jobject eventLoop = env->GetObjectField(object, field_mEventLoop); - struct event_loop_native_data_t *eventLoopNat = - get_EventLoop_native_data(env, eventLoop); - - if (nat && eventLoopNat) { - const char *c_address = env->GetStringUTFChars(address, NULL); - ALOGV("... address = %s", c_address); - char *context_address = (char *)calloc(BTADDR_SIZE, sizeof(char)); - strlcpy(context_address, c_address, BTADDR_SIZE); // for callback - - bool ret = dbus_func_args_async(env, nat->conn, -1, - onCreateDeviceResult, - context_address, - eventLoopNat, - get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, - "CreateDevice", - DBUS_TYPE_STRING, &c_address, - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(address, c_address); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean discoverServicesNative(JNIEnv *env, jobject object, - jstring path, jstring pattern) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - jobject eventLoop = env->GetObjectField(object, field_mEventLoop); - struct event_loop_native_data_t *eventLoopNat = - get_EventLoop_native_data(env, eventLoop); - - if (nat && eventLoopNat) { - const char *c_path = env->GetStringUTFChars(path, NULL); - const char *c_pattern = env->GetStringUTFChars(pattern, NULL); - int len = env->GetStringLength(path) + 1; - char *context_path = (char *)calloc(len, sizeof(char)); - strlcpy(context_path, c_path, len); // for callback - - ALOGV("... Object Path = %s", c_path); - ALOGV("... Pattern = %s, strlen = %d", c_pattern, strlen(c_pattern)); - - bool ret = dbus_func_args_async(env, nat->conn, -1, - onDiscoverServicesResult, - context_path, - eventLoopNat, - c_path, - DBUS_DEVICE_IFACE, - "DiscoverServices", - DBUS_TYPE_STRING, &c_pattern, - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(path, c_path); - env->ReleaseStringUTFChars(pattern, c_pattern); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -#ifdef HAVE_BLUETOOTH -static jintArray extract_handles(JNIEnv *env, DBusMessage *reply) { - jint *handles; - jintArray handleArray = NULL; - int len; - - DBusError err; - dbus_error_init(&err); - - if (dbus_message_get_args(reply, &err, - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &handles, &len, - DBUS_TYPE_INVALID)) { - handleArray = env->NewIntArray(len); - if (handleArray) { - env->SetIntArrayRegion(handleArray, 0, len, handles); - } else { - ALOGE("Null array in extract_handles"); - } - } else { - LOG_AND_FREE_DBUS_ERROR(&err); - } - return handleArray; -} -#endif - -static jintArray addReservedServiceRecordsNative(JNIEnv *env, jobject object, - jintArray uuids) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - DBusMessage *reply = NULL; - - native_data_t *nat = get_native_data(env, object); - - jint* svc_classes = env->GetIntArrayElements(uuids, NULL); - if (!svc_classes) return NULL; - - int len = env->GetArrayLength(uuids); - reply = dbus_func_args(env, nat->conn, - get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, "AddReservedServiceRecords", - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, - &svc_classes, len, DBUS_TYPE_INVALID); - env->ReleaseIntArrayElements(uuids, svc_classes, 0); - return reply ? extract_handles(env, reply) : NULL; - -#endif - return NULL; -} - -static jboolean removeReservedServiceRecordsNative(JNIEnv *env, jobject object, - jintArray handles) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - jint *values = env->GetIntArrayElements(handles, NULL); - DBusMessage *msg = NULL; - DBusMessage *reply = NULL; - if (values == NULL) return JNI_FALSE; - - jsize len = env->GetArrayLength(handles); - - reply = dbus_func_args(env, nat->conn, - get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, "RemoveReservedServiceRecords", - DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, - &values, len, DBUS_TYPE_INVALID); - env->ReleaseIntArrayElements(handles, values, 0); - return reply ? JNI_TRUE : JNI_FALSE; -#endif - return JNI_FALSE; -} - -static jint addRfcommServiceRecordNative(JNIEnv *env, jobject object, - jstring name, jlong uuidMsb, jlong uuidLsb, jshort channel) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - const char *c_name = env->GetStringUTFChars(name, NULL); - ALOGV("... name = %s", c_name); - ALOGV("... uuid1 = %llX", uuidMsb); - ALOGV("... uuid2 = %llX", uuidLsb); - ALOGV("... channel = %d", channel); - DBusMessage *reply = dbus_func_args(env, nat->conn, - get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, "AddRfcommServiceRecord", - DBUS_TYPE_STRING, &c_name, - DBUS_TYPE_UINT64, &uuidMsb, - DBUS_TYPE_UINT64, &uuidLsb, - DBUS_TYPE_UINT16, &channel, - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(name, c_name); - return reply ? dbus_returns_uint32(env, reply) : -1; - } -#endif - return -1; -} - -static jboolean removeServiceRecordNative(JNIEnv *env, jobject object, jint handle) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - ALOGV("... handle = %X", handle); - DBusMessage *reply = dbus_func_args(env, nat->conn, - get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, "RemoveServiceRecord", - DBUS_TYPE_UINT32, &handle, - DBUS_TYPE_INVALID); - return reply ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean setLinkTimeoutNative(JNIEnv *env, jobject object, jstring object_path, - jint num_slots) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - const char *c_object_path = env->GetStringUTFChars(object_path, NULL); - DBusMessage *reply = dbus_func_args(env, nat->conn, - get_adapter_path(env, object), - DBUS_ADAPTER_IFACE, "SetLinkTimeout", - DBUS_TYPE_OBJECT_PATH, &c_object_path, - DBUS_TYPE_UINT32, &num_slots, - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(object_path, c_object_path); - return reply ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean connectInputDeviceNative(JNIEnv *env, jobject object, jstring path) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - jobject eventLoop = env->GetObjectField(object, field_mEventLoop); - struct event_loop_native_data_t *eventLoopNat = - get_EventLoop_native_data(env, eventLoop); - - if (nat && eventLoopNat) { - const char *c_path = env->GetStringUTFChars(path, NULL); - - int len = env->GetStringLength(path) + 1; - char *context_path = (char *)calloc(len, sizeof(char)); - strlcpy(context_path, c_path, len); // for callback - - bool ret = dbus_func_args_async(env, nat->conn, -1, onInputDeviceConnectionResult, - context_path, eventLoopNat, c_path, DBUS_INPUT_IFACE, - "Connect", - DBUS_TYPE_INVALID); - - env->ReleaseStringUTFChars(path, c_path); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean disconnectInputDeviceNative(JNIEnv *env, jobject object, - jstring path) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - jobject eventLoop = env->GetObjectField(object, field_mEventLoop); - struct event_loop_native_data_t *eventLoopNat = - get_EventLoop_native_data(env, eventLoop); - - if (nat && eventLoopNat) { - const char *c_path = env->GetStringUTFChars(path, NULL); - - int len = env->GetStringLength(path) + 1; - char *context_path = (char *)calloc(len, sizeof(char)); - strlcpy(context_path, c_path, len); // for callback - - bool ret = dbus_func_args_async(env, nat->conn, -1, onInputDeviceConnectionResult, - context_path, eventLoopNat, c_path, DBUS_INPUT_IFACE, - "Disconnect", - DBUS_TYPE_INVALID); - - env->ReleaseStringUTFChars(path, c_path); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean setBluetoothTetheringNative(JNIEnv *env, jobject object, jboolean value, - jstring src_role, jstring bridge) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - DBusMessage *reply; - const char *c_role = env->GetStringUTFChars(src_role, NULL); - const char *c_bridge = env->GetStringUTFChars(bridge, NULL); - if (value) { - ALOGE("setBluetoothTetheringNative true"); - reply = dbus_func_args(env, nat->conn, - get_adapter_path(env, object), - DBUS_NETWORKSERVER_IFACE, - "Register", - DBUS_TYPE_STRING, &c_role, - DBUS_TYPE_STRING, &c_bridge, - DBUS_TYPE_INVALID); - } else { - ALOGE("setBluetoothTetheringNative false"); - reply = dbus_func_args(env, nat->conn, - get_adapter_path(env, object), - DBUS_NETWORKSERVER_IFACE, - "Unregister", - DBUS_TYPE_STRING, &c_role, - DBUS_TYPE_INVALID); - } - env->ReleaseStringUTFChars(src_role, c_role); - env->ReleaseStringUTFChars(bridge, c_bridge); - return reply ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean connectPanDeviceNative(JNIEnv *env, jobject object, jstring path, - jstring dstRole) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - ALOGE("connectPanDeviceNative"); - native_data_t *nat = get_native_data(env, object); - jobject eventLoop = env->GetObjectField(object, field_mEventLoop); - struct event_loop_native_data_t *eventLoopNat = - get_EventLoop_native_data(env, eventLoop); - - if (nat && eventLoopNat) { - const char *c_path = env->GetStringUTFChars(path, NULL); - const char *dst = env->GetStringUTFChars(dstRole, NULL); - - int len = env->GetStringLength(path) + 1; - char *context_path = (char *)calloc(len, sizeof(char)); - strlcpy(context_path, c_path, len); // for callback - - bool ret = dbus_func_args_async(env, nat->conn, -1,onPanDeviceConnectionResult, - context_path, eventLoopNat, c_path, - DBUS_NETWORK_IFACE, "Connect", - DBUS_TYPE_STRING, &dst, - DBUS_TYPE_INVALID); - - env->ReleaseStringUTFChars(path, c_path); - env->ReleaseStringUTFChars(dstRole, dst); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean disconnectPanDeviceNative(JNIEnv *env, jobject object, - jstring path) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - ALOGE("disconnectPanDeviceNative"); - native_data_t *nat = get_native_data(env, object); - jobject eventLoop = env->GetObjectField(object, field_mEventLoop); - struct event_loop_native_data_t *eventLoopNat = - get_EventLoop_native_data(env, eventLoop); - - if (nat && eventLoopNat) { - const char *c_path = env->GetStringUTFChars(path, NULL); - - int len = env->GetStringLength(path) + 1; - char *context_path = (char *)calloc(len, sizeof(char)); - strlcpy(context_path, c_path, len); // for callback - - bool ret = dbus_func_args_async(env, nat->conn, -1,onPanDeviceConnectionResult, - context_path, eventLoopNat, c_path, - DBUS_NETWORK_IFACE, "Disconnect", - DBUS_TYPE_INVALID); - - env->ReleaseStringUTFChars(path, c_path); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean disconnectPanServerDeviceNative(JNIEnv *env, jobject object, - jstring path, jstring address, - jstring iface) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - ALOGE("disconnectPanServerDeviceNative"); - native_data_t *nat = get_native_data(env, object); - jobject eventLoop = env->GetObjectField(object, field_mEventLoop); - struct event_loop_native_data_t *eventLoopNat = - get_EventLoop_native_data(env, eventLoop); - - if (nat && eventLoopNat) { - const char *c_address = env->GetStringUTFChars(address, NULL); - const char *c_path = env->GetStringUTFChars(path, NULL); - const char *c_iface = env->GetStringUTFChars(iface, NULL); - - int len = env->GetStringLength(path) + 1; - char *context_path = (char *)calloc(len, sizeof(char)); - strlcpy(context_path, c_path, len); // for callback - - bool ret = dbus_func_args_async(env, nat->conn, -1, - onPanDeviceConnectionResult, - context_path, eventLoopNat, - get_adapter_path(env, object), - DBUS_NETWORKSERVER_IFACE, - "DisconnectDevice", - DBUS_TYPE_STRING, &c_address, - DBUS_TYPE_STRING, &c_iface, - DBUS_TYPE_INVALID); - - env->ReleaseStringUTFChars(address, c_address); - env->ReleaseStringUTFChars(iface, c_iface); - env->ReleaseStringUTFChars(path, c_path); - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jstring registerHealthApplicationNative(JNIEnv *env, jobject object, - jint dataType, jstring role, - jstring name, jstring channelType) { - ALOGV("%s", __FUNCTION__); - jstring path = NULL; -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - const char *c_role = env->GetStringUTFChars(role, NULL); - const char *c_name = env->GetStringUTFChars(name, NULL); - const char *c_channel_type = env->GetStringUTFChars(channelType, NULL); - char *c_path; - DBusMessage *msg, *reply; - DBusError err; - dbus_error_init(&err); - - msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, - DBUS_HEALTH_MANAGER_PATH, - DBUS_HEALTH_MANAGER_IFACE, - "CreateApplication"); - - if (msg == NULL) { - ALOGE("Could not allocate D-Bus message object!"); - return NULL; - } - - /* append arguments */ - append_dict_args(msg, - "DataType", DBUS_TYPE_UINT16, &dataType, - "Role", DBUS_TYPE_STRING, &c_role, - "Description", DBUS_TYPE_STRING, &c_name, - "ChannelType", DBUS_TYPE_STRING, &c_channel_type, - DBUS_TYPE_INVALID); - - - /* Make the call. */ - reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err); - - env->ReleaseStringUTFChars(role, c_role); - env->ReleaseStringUTFChars(name, c_name); - env->ReleaseStringUTFChars(channelType, c_channel_type); - - if (!reply) { - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - } else { - if (!dbus_message_get_args(reply, &err, - DBUS_TYPE_OBJECT_PATH, &c_path, - DBUS_TYPE_INVALID)) { - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - } else { - path = env->NewStringUTF(c_path); - } - dbus_message_unref(reply); - } - } -#endif - return path; -} - -static jstring registerSinkHealthApplicationNative(JNIEnv *env, jobject object, - jint dataType, jstring role, - jstring name) { - ALOGV("%s", __FUNCTION__); - jstring path = NULL; -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - const char *c_role = env->GetStringUTFChars(role, NULL); - const char *c_name = env->GetStringUTFChars(name, NULL); - char *c_path; - - DBusMessage *msg, *reply; - DBusError err; - dbus_error_init(&err); - - msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, - DBUS_HEALTH_MANAGER_PATH, - DBUS_HEALTH_MANAGER_IFACE, - "CreateApplication"); - - if (msg == NULL) { - ALOGE("Could not allocate D-Bus message object!"); - return NULL; - } - - /* append arguments */ - append_dict_args(msg, - "DataType", DBUS_TYPE_UINT16, &dataType, - "Role", DBUS_TYPE_STRING, &c_role, - "Description", DBUS_TYPE_STRING, &c_name, - DBUS_TYPE_INVALID); - - - /* Make the call. */ - reply = dbus_connection_send_with_reply_and_block(nat->conn, msg, -1, &err); - - env->ReleaseStringUTFChars(role, c_role); - env->ReleaseStringUTFChars(name, c_name); - - if (!reply) { - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - } else { - if (!dbus_message_get_args(reply, &err, - DBUS_TYPE_OBJECT_PATH, &c_path, - DBUS_TYPE_INVALID)) { - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - } else { - path = env->NewStringUTF(c_path); - } - dbus_message_unref(reply); - } - } -#endif - return path; -} - -static jboolean unregisterHealthApplicationNative(JNIEnv *env, jobject object, - jstring path) { - ALOGV("%s", __FUNCTION__); - jboolean result = JNI_FALSE; -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - const char *c_path = env->GetStringUTFChars(path, NULL); - DBusError err; - dbus_error_init(&err); - DBusMessage *reply = - dbus_func_args_timeout(env, nat->conn, -1, - DBUS_HEALTH_MANAGER_PATH, - DBUS_HEALTH_MANAGER_IFACE, "DestroyApplication", - DBUS_TYPE_OBJECT_PATH, &c_path, - DBUS_TYPE_INVALID); - - env->ReleaseStringUTFChars(path, c_path); - - if (!reply) { - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - } else { - result = JNI_TRUE; - } - } -#endif - return result; -} - -static jboolean createChannelNative(JNIEnv *env, jobject object, - jstring devicePath, jstring appPath, jstring config, - jint code) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - jobject eventLoop = env->GetObjectField(object, field_mEventLoop); - struct event_loop_native_data_t *eventLoopNat = - get_EventLoop_native_data(env, eventLoop); - - if (nat && eventLoopNat) { - const char *c_device_path = env->GetStringUTFChars(devicePath, NULL); - const char *c_app_path = env->GetStringUTFChars(appPath, NULL); - const char *c_config = env->GetStringUTFChars(config, NULL); - int *data = (int *) malloc(sizeof(int)); - if (data == NULL) return JNI_FALSE; - - *data = code; - bool ret = dbus_func_args_async(env, nat->conn, -1, onHealthDeviceConnectionResult, - data, eventLoopNat, c_device_path, - DBUS_HEALTH_DEVICE_IFACE, "CreateChannel", - DBUS_TYPE_OBJECT_PATH, &c_app_path, - DBUS_TYPE_STRING, &c_config, - DBUS_TYPE_INVALID); - - - env->ReleaseStringUTFChars(devicePath, c_device_path); - env->ReleaseStringUTFChars(appPath, c_app_path); - env->ReleaseStringUTFChars(config, c_config); - - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jboolean destroyChannelNative(JNIEnv *env, jobject object, jstring devicePath, - jstring channelPath, jint code) { - ALOGE("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - jobject eventLoop = env->GetObjectField(object, field_mEventLoop); - struct event_loop_native_data_t *eventLoopNat = - get_EventLoop_native_data(env, eventLoop); - - if (nat && eventLoopNat) { - const char *c_device_path = env->GetStringUTFChars(devicePath, NULL); - const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL); - int *data = (int *) malloc(sizeof(int)); - if (data == NULL) return JNI_FALSE; - - *data = code; - bool ret = dbus_func_args_async(env, nat->conn, -1, onHealthDeviceConnectionResult, - data, eventLoopNat, c_device_path, - DBUS_HEALTH_DEVICE_IFACE, "DestroyChannel", - DBUS_TYPE_OBJECT_PATH, &c_channel_path, - DBUS_TYPE_INVALID); - - env->ReleaseStringUTFChars(devicePath, c_device_path); - env->ReleaseStringUTFChars(channelPath, c_channel_path); - - return ret ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jstring getMainChannelNative(JNIEnv *env, jobject object, jstring devicePath) { - ALOGE("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - const char *c_device_path = env->GetStringUTFChars(devicePath, NULL); - DBusError err; - dbus_error_init(&err); - - DBusMessage *reply = dbus_func_args(env, nat->conn, - c_device_path, - DBUS_HEALTH_DEVICE_IFACE, "GetProperties", - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(devicePath, c_device_path); - - if (!reply) { - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - } else { - DBusMessageIter iter; - jobjectArray str_array = NULL; - if (dbus_message_iter_init(reply, &iter)) - str_array = parse_health_device_properties(env, &iter); - dbus_message_unref(reply); - jstring path = (jstring) env->GetObjectArrayElement(str_array, 1); - - return path; - } - } -#endif - return NULL; -} - -static jstring getChannelApplicationNative(JNIEnv *env, jobject object, jstring channelPath) { - ALOGE("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL); - DBusError err; - dbus_error_init(&err); - - DBusMessage *reply = dbus_func_args(env, nat->conn, - c_channel_path, - DBUS_HEALTH_CHANNEL_IFACE, "GetProperties", - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(channelPath, c_channel_path); - - if (!reply) { - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - } else { - DBusMessageIter iter; - jobjectArray str_array = NULL; - if (dbus_message_iter_init(reply, &iter)) - str_array = parse_health_channel_properties(env, &iter); - dbus_message_unref(reply); - - jint len = env->GetArrayLength(str_array); - - jstring name, path; - const char *c_name; - - for (int i = 0; i < len; i+=2) { - name = (jstring) env->GetObjectArrayElement(str_array, i); - c_name = env->GetStringUTFChars(name, NULL); - - if (!strcmp(c_name, "Application")) { - path = (jstring) env->GetObjectArrayElement(str_array, i+1); - env->ReleaseStringUTFChars(name, c_name); - return path; - } - env->ReleaseStringUTFChars(name, c_name); - } - } - } -#endif - return NULL; -} - -static jboolean releaseChannelFdNative(JNIEnv *env, jobject object, jstring channelPath) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL); - DBusError err; - dbus_error_init(&err); - - DBusMessage *reply = dbus_func_args(env, nat->conn, - c_channel_path, - DBUS_HEALTH_CHANNEL_IFACE, "Release", - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(channelPath, c_channel_path); - - return reply ? JNI_TRUE : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - -static jobject getChannelFdNative(JNIEnv *env, jobject object, jstring channelPath) { - ALOGV("%s", __FUNCTION__); -#ifdef HAVE_BLUETOOTH - native_data_t *nat = get_native_data(env, object); - if (nat) { - const char *c_channel_path = env->GetStringUTFChars(channelPath, NULL); - int32_t fd; - DBusError err; - dbus_error_init(&err); - - DBusMessage *reply = dbus_func_args(env, nat->conn, - c_channel_path, - DBUS_HEALTH_CHANNEL_IFACE, "Acquire", - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(channelPath, c_channel_path); - - if (!reply) { - if (dbus_error_is_set(&err)) { - LOG_AND_FREE_DBUS_ERROR(&err); - } - return NULL; - } - - fd = dbus_returns_unixfd(env, reply); - if (fd == -1) return NULL; - - int flags = fcntl(fd, F_GETFL); - if (flags < 0) { - ALOGE("Can't get flags with fcntl(): %s (%d)", - strerror(errno), errno); - releaseChannelFdNative(env, object, channelPath); - close(fd); - return NULL; - } - - flags &= ~O_NONBLOCK; - int status = fcntl(fd, F_SETFL, flags); - if (status < 0) { - ALOGE("Can't set flags with fcntl(): %s (%d)", - strerror(errno), errno); - releaseChannelFdNative(env, object, channelPath); - close(fd); - return NULL; - } - - // Create FileDescriptor object - jobject fileDesc = jniCreateFileDescriptor(env, fd); - if (fileDesc == NULL) { - // FileDescriptor constructor has thrown an exception - releaseChannelFdNative(env, object, channelPath); - close(fd); - return NULL; - } - - // Wrap it in a ParcelFileDescriptor - jobject parcelFileDesc = newParcelFileDescriptor(env, fileDesc); - if (parcelFileDesc == NULL) { - // ParcelFileDescriptor constructor has thrown an exception - releaseChannelFdNative(env, object, channelPath); - close(fd); - return NULL; - } - - return parcelFileDesc; - } -#endif - return NULL; -} - - - -static JNINativeMethod sMethods[] = { - /* name, signature, funcPtr */ - {"classInitNative", "()V", (void*)classInitNative}, - {"initializeNativeDataNative", "()V", (void *)initializeNativeDataNative}, - {"setupNativeDataNative", "()Z", (void *)setupNativeDataNative}, - {"tearDownNativeDataNative", "()Z", (void *)tearDownNativeDataNative}, - {"cleanupNativeDataNative", "()V", (void *)cleanupNativeDataNative}, - {"getAdapterPathNative", "()Ljava/lang/String;", (void*)getAdapterPathNative}, - - {"isEnabledNative", "()I", (void *)isEnabledNative}, - {"enableNative", "()I", (void *)enableNative}, - {"disableNative", "()I", (void *)disableNative}, - - {"getAdapterPropertiesNative", "()[Ljava/lang/Object;", (void *)getAdapterPropertiesNative}, - {"getDevicePropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;", - (void *)getDevicePropertiesNative}, - {"setAdapterPropertyStringNative", "(Ljava/lang/String;Ljava/lang/String;)Z", - (void *)setAdapterPropertyStringNative}, - {"setAdapterPropertyBooleanNative", "(Ljava/lang/String;I)Z", - (void *)setAdapterPropertyBooleanNative}, - {"setAdapterPropertyIntegerNative", "(Ljava/lang/String;I)Z", - (void *)setAdapterPropertyIntegerNative}, - - {"startDiscoveryNative", "()Z", (void*)startDiscoveryNative}, - {"stopDiscoveryNative", "()Z", (void *)stopDiscoveryNative}, - - {"readAdapterOutOfBandDataNative", "()[B", (void *)readAdapterOutOfBandDataNative}, - {"createPairedDeviceNative", "(Ljava/lang/String;I)Z", (void *)createPairedDeviceNative}, - {"createPairedDeviceOutOfBandNative", "(Ljava/lang/String;I)Z", - (void *)createPairedDeviceOutOfBandNative}, - {"cancelDeviceCreationNative", "(Ljava/lang/String;)Z", (void *)cancelDeviceCreationNative}, - {"removeDeviceNative", "(Ljava/lang/String;)Z", (void *)removeDeviceNative}, - {"getDeviceServiceChannelNative", "(Ljava/lang/String;Ljava/lang/String;I)I", - (void *)getDeviceServiceChannelNative}, - - {"setPairingConfirmationNative", "(Ljava/lang/String;ZI)Z", - (void *)setPairingConfirmationNative}, - {"setPasskeyNative", "(Ljava/lang/String;II)Z", (void *)setPasskeyNative}, - {"setRemoteOutOfBandDataNative", "(Ljava/lang/String;[B[BI)Z", (void *)setRemoteOutOfBandDataNative}, - {"setAuthorizationNative", "(Ljava/lang/String;ZI)Z", (void *)setAuthorizationNative}, - {"setPinNative", "(Ljava/lang/String;Ljava/lang/String;I)Z", (void *)setPinNative}, - {"cancelPairingUserInputNative", "(Ljava/lang/String;I)Z", - (void *)cancelPairingUserInputNative}, - {"setDevicePropertyBooleanNative", "(Ljava/lang/String;Ljava/lang/String;I)Z", - (void *)setDevicePropertyBooleanNative}, - {"setDevicePropertyStringNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z", - (void *)setDevicePropertyStringNative}, - {"createDeviceNative", "(Ljava/lang/String;)Z", (void *)createDeviceNative}, - {"discoverServicesNative", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *)discoverServicesNative}, - {"addRfcommServiceRecordNative", "(Ljava/lang/String;JJS)I", (void *)addRfcommServiceRecordNative}, - {"removeServiceRecordNative", "(I)Z", (void *)removeServiceRecordNative}, - {"addReservedServiceRecordsNative", "([I)[I", (void *) addReservedServiceRecordsNative}, - {"removeReservedServiceRecordsNative", "([I)Z", (void *) removeReservedServiceRecordsNative}, - {"setLinkTimeoutNative", "(Ljava/lang/String;I)Z", (void *)setLinkTimeoutNative}, - // HID functions - {"connectInputDeviceNative", "(Ljava/lang/String;)Z", (void *)connectInputDeviceNative}, - {"disconnectInputDeviceNative", "(Ljava/lang/String;)Z", (void *)disconnectInputDeviceNative}, - - {"setBluetoothTetheringNative", "(ZLjava/lang/String;Ljava/lang/String;)Z", - (void *)setBluetoothTetheringNative}, - {"connectPanDeviceNative", "(Ljava/lang/String;Ljava/lang/String;)Z", - (void *)connectPanDeviceNative}, - {"disconnectPanDeviceNative", "(Ljava/lang/String;)Z", (void *)disconnectPanDeviceNative}, - {"disconnectPanServerDeviceNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z", - (void *)disconnectPanServerDeviceNative}, - // Health function - {"registerHealthApplicationNative", - "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", - (void *)registerHealthApplicationNative}, - {"registerHealthApplicationNative", - "(ILjava/lang/String;Ljava/lang/String;)Ljava/lang/String;", - (void *)registerSinkHealthApplicationNative}, - - {"unregisterHealthApplicationNative", "(Ljava/lang/String;)Z", - (void *)unregisterHealthApplicationNative}, - {"createChannelNative", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)Z", - (void *)createChannelNative}, - {"destroyChannelNative", "(Ljava/lang/String;Ljava/lang/String;I)Z", - (void *)destroyChannelNative}, - {"getMainChannelNative", "(Ljava/lang/String;)Ljava/lang/String;", (void *)getMainChannelNative}, - {"getChannelApplicationNative", "(Ljava/lang/String;)Ljava/lang/String;", - (void *)getChannelApplicationNative}, - {"getChannelFdNative", "(Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;", (void *)getChannelFdNative}, - {"releaseChannelFdNative", "(Ljava/lang/String;)Z", (void *)releaseChannelFdNative}, -}; - - -int register_android_server_BluetoothService(JNIEnv *env) { - return AndroidRuntime::registerNativeMethods(env, - "android/server/BluetoothService", sMethods, NELEM(sMethods)); -} - -} /* namespace android */ |