summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAyan Ghosh <abghosh@codeaurora.org>2016-01-13 17:20:47 +0530
committerRoman Birg <roman@cyngn.com>2016-04-25 10:24:31 -0700
commit2c9c5455f29312e4180181a72e145dd9e656e7c6 (patch)
tree0c99470c0d1ef751cd8192ff9f208c750b6dc7bc
parent197747b2c35ae1d9289042677202ef317a51c564 (diff)
downloadandroid_packages_apps_Bluetooth-2c9c5455f29312e4180181a72e145dd9e656e7c6.tar.gz
android_packages_apps_Bluetooth-2c9c5455f29312e4180181a72e145dd9e656e7c6.tar.bz2
android_packages_apps_Bluetooth-2c9c5455f29312e4180181a72e145dd9e656e7c6.zip
Ensure synchronized access of JNI callback object
Ensure synchronized access of JNI object using mutex as the same is accessed from both Application context during cleanup and from stack call back context during intimating Apps on stack event update. CRs-Fixed: 959400 Change-Id: I39f97f1b530086bc446941dde744e43c33b46f81
-rw-r--r--jni/com_android_bluetooth_a2dp.cpp81
1 files changed, 53 insertions, 28 deletions
diff --git a/jni/com_android_bluetooth_a2dp.cpp b/jni/com_android_bluetooth_a2dp.cpp
index df8fe9837..565cd99a9 100644
--- a/jni/com_android_bluetooth_a2dp.cpp
+++ b/jni/com_android_bluetooth_a2dp.cpp
@@ -27,6 +27,7 @@
#include "android_runtime/AndroidRuntime.h"
#include <string.h>
+#include <pthread.h>
namespace android {
static jmethodID method_onConnectionStateChanged;
@@ -39,6 +40,8 @@ static const btav_interface_t *sBluetoothA2dpInterface = NULL;
static jobject mCallbacksObj = NULL;
static JNIEnv *sCallbackEnv = NULL;
+static pthread_mutex_t mMutex = PTHREAD_MUTEX_INITIALIZER;
+
static bool checkCallbackThread() {
// Always fetch the latest callbackEnv from AdapterService.
// Caching this could cause this sCallbackEnv to go out-of-sync
@@ -58,10 +61,6 @@ static void bta2dp_connection_state_callback(btav_connection_state_t state, bt_b
ALOGI("%s", __FUNCTION__);
- if (mCallbacksObj == NULL) {
- ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
- return;
- }
if (!checkCallbackThread()) { \
ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
return; \
@@ -75,8 +74,16 @@ static void bta2dp_connection_state_callback(btav_connection_state_t state, bt_b
}
sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
- sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, (jint) state,
- addr);
+
+ pthread_mutex_lock(&mMutex);
+ if (mCallbacksObj != NULL) {
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged,
+ (jint) state, addr);
+ } else {
+ ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
+ }
+ pthread_mutex_unlock(&mMutex);
+
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
sCallbackEnv->DeleteLocalRef(addr);
}
@@ -86,10 +93,6 @@ static void bta2dp_audio_state_callback(btav_audio_state_t state, bt_bdaddr_t* b
ALOGI("%s", __FUNCTION__);
- if (mCallbacksObj == NULL) {
- ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
- return;
- }
if (!checkCallbackThread()) { \
ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
return; \
@@ -102,8 +105,16 @@ static void bta2dp_audio_state_callback(btav_audio_state_t state, bt_bdaddr_t* b
}
sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
- sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint) state,
- addr);
+
+ pthread_mutex_lock(&mMutex);
+ if (mCallbacksObj != NULL) {
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged,
+ (jint) state, addr);
+ } else {
+ ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
+ }
+ pthread_mutex_unlock(&mMutex);
+
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
sCallbackEnv->DeleteLocalRef(addr);
}
@@ -113,10 +124,6 @@ static void bta2dp_connection_priority_callback(bt_bdaddr_t* bd_addr) {
ALOGI("%s", __FUNCTION__);
- if (mCallbacksObj == NULL) {
- ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
- return;
- }
if (!checkCallbackThread()) { \
ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
return; \
@@ -129,7 +136,16 @@ static void bta2dp_connection_priority_callback(bt_bdaddr_t* bd_addr) {
}
sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
- sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCheckConnectionPriority, addr);
+
+ pthread_mutex_lock(&mMutex);
+ if (mCallbacksObj != NULL) {
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCheckConnectionPriority,
+ addr);
+ } else {
+ ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
+ }
+ pthread_mutex_unlock(&mMutex);
+
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
sCallbackEnv->DeleteLocalRef(addr);
}
@@ -138,16 +154,20 @@ static void bta2dp_multicast_enabled_callback(int state) {
ALOGI("%s", __FUNCTION__);
- if (mCallbacksObj == NULL) {
- ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
- return;
- }
if (!checkCallbackThread()) { \
ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
return; \
}
- sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMulticastStateChanged, state);
+ pthread_mutex_lock(&mMutex);
+ if (mCallbacksObj != NULL) {
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMulticastStateChanged,
+ state);
+ } else {
+ ALOGE("Callbacks Obj is no more valid: '%s", __FUNCTION__);
+ }
+ pthread_mutex_unlock(&mMutex);
+
checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
}
@@ -218,29 +238,32 @@ static void initNative(JNIEnv *env, jobject object, jint maxA2dpConnections,
sBluetoothA2dpInterface = NULL;
}
- if (mCallbacksObj != NULL) {
- ALOGW("Cleaning up A2DP callback object");
- env->DeleteGlobalRef(mCallbacksObj);
- mCallbacksObj = NULL;
- }
-
if ( (sBluetoothA2dpInterface = (btav_interface_t *)
btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID)) == NULL) {
ALOGE("Failed to get Bluetooth A2DP Interface");
return;
}
+ pthread_mutex_lock(&mMutex);
+ if (mCallbacksObj != NULL) {
+ ALOGW("Cleaning up A2DP callback object");
+ env->DeleteGlobalRef(mCallbacksObj);
+ mCallbacksObj = NULL;
+ }
mCallbacksObj = env->NewGlobalRef(object);
+ pthread_mutex_unlock(&mMutex);
if ( (status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks,
maxA2dpConnections, multiCastState)) != BT_STATUS_SUCCESS) {
ALOGE("Failed to initialize Bluetooth A2DP, status: %d", status);
sBluetoothA2dpInterface = NULL;
+ pthread_mutex_lock(&mMutex);
if (mCallbacksObj != NULL) {
ALOGW("Clean up A2DP callback object");
env->DeleteGlobalRef(mCallbacksObj);
mCallbacksObj = NULL;
}
+ pthread_mutex_unlock(&mMutex);
return;
}
@@ -260,10 +283,12 @@ static void cleanupNative(JNIEnv *env, jobject object) {
sBluetoothA2dpInterface = NULL;
}
+ pthread_mutex_lock(&mMutex);
if (mCallbacksObj != NULL) {
env->DeleteGlobalRef(mCallbacksObj);
mCallbacksObj = NULL;
}
+ pthread_mutex_unlock(&mMutex);
}
static jboolean connectA2dpNative(JNIEnv *env, jobject object, jbyteArray address) {