jni: Use RAII to manage callback environment

CallbackEnv is a new RAII object which:
 - Retrieves the callback environment when instantiated
 - Clears exceptions when it goes out of scope
 - Centralizes checks that we are in the correct environment

It can be used the same as a pointer to JNIEnv with the -> operator and
the JNIEnv pointer can be retrieved with get();

Test: basic functionality tests
Change-Id: I004f2655e2e02847782fec794faa62da85c85d49
diff --git a/jni/com_android_bluetooth.h b/jni/com_android_bluetooth.h
index 4f55c06..e63eba5 100644
--- a/jni/com_android_bluetooth.h
+++ b/jni/com_android_bluetooth.h
@@ -22,16 +22,54 @@
 #include "jni.h"
 #include "hardware/hardware.h"
 #include "hardware/bluetooth.h"
+#include "utils/Log.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/Log.h"
 
 namespace android {
 
-void checkAndClearExceptionFromCallback(JNIEnv* env,
-                                        const char* methodName);
+JNIEnv* getCallbackEnv();
+
+class CallbackEnv {
+public:
+    CallbackEnv(const char *methodName) : mName(methodName) {
+        mCallbackEnv = getCallbackEnv();
+    }
+
+    ~CallbackEnv() {
+      if (mCallbackEnv && mCallbackEnv->ExceptionCheck()) {
+          ALOGE("An exception was thrown by callback '%s'.", mName);
+          LOGE_EX(mCallbackEnv);
+          mCallbackEnv->ExceptionClear();
+      }
+    }
+
+    bool valid() const {
+      JNIEnv *env = AndroidRuntime::getJNIEnv();
+      if (!mCallbackEnv || (mCallbackEnv != env)) {
+          ALOGE("%s: Callback env fail: env: %p, callback: %p", mName, env, mCallbackEnv);
+          return false;
+      }
+      return true;
+    }
+
+    JNIEnv *operator-> () const {
+        return mCallbackEnv;
+    }
+
+    JNIEnv *get() const {
+        return mCallbackEnv;
+    }
+
+private:
+    JNIEnv *mCallbackEnv;
+    const char *mName;
+
+    DISALLOW_COPY_AND_ASSIGN(CallbackEnv);
+};
 
 const bt_interface_t* getBluetoothInterface();
 
-JNIEnv* getCallbackEnv();
-
 int register_com_android_bluetooth_hfp(JNIEnv* env);
 
 int register_com_android_bluetooth_hfpclient(JNIEnv* env);
diff --git a/jni/com_android_bluetooth_a2dp.cpp b/jni/com_android_bluetooth_a2dp.cpp
index 2b4cb56..26f0c56 100644
--- a/jni/com_android_bluetooth_a2dp.cpp
+++ b/jni/com_android_bluetooth_a2dp.cpp
@@ -31,65 +31,42 @@
 
 static const btav_interface_t *sBluetoothA2dpInterface = NULL;
 static jobject mCallbacksObj = NULL;
-static JNIEnv *sCallbackEnv = NULL;
-
-static bool checkCallbackThread() {
-    // Always fetch the latest callbackEnv from AdapterService.
-    // Caching this could cause this sCallbackEnv to go out-of-sync
-    // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event
-    // is received
-    //if (sCallbackEnv == NULL) {
-    sCallbackEnv = getCallbackEnv();
-    //}
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (sCallbackEnv != env || sCallbackEnv == NULL) return false;
-    return true;
-}
 
 static void bta2dp_connection_state_callback(btav_connection_state_t state, bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    ALOGI("%s", __FUNCTION__);
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    if (!checkCallbackThread()) {                                       \
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
-        return;                                                         \
-    }
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for connection state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, (jint) state,
                                  addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void bta2dp_audio_state_callback(btav_audio_state_t state, bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    ALOGI("%s", __FUNCTION__);
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    if (!checkCallbackThread()) {                                       \
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
-        return;                                                         \
-    }
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for connection state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint) state,
                                  addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
diff --git a/jni/com_android_bluetooth_a2dp_sink.cpp b/jni/com_android_bluetooth_a2dp_sink.cpp
index 82110d3..0c6a7a1 100644
--- a/jni/com_android_bluetooth_a2dp_sink.cpp
+++ b/jni/com_android_bluetooth_a2dp_sink.cpp
@@ -32,87 +32,60 @@
 
 static const btav_interface_t *sBluetoothA2dpInterface = NULL;
 static jobject mCallbacksObj = NULL;
-static JNIEnv *sCallbackEnv = NULL;
-
-static bool checkCallbackThread() {
-    // Always fetch the latest callbackEnv from AdapterService.
-    // Caching this could cause this sCallbackEnv to go out-of-sync
-    // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event
-    // is received
-    //if (sCallbackEnv == NULL) {
-    sCallbackEnv = getCallbackEnv();
-    //}
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (sCallbackEnv != env || sCallbackEnv == NULL) return false;
-    return true;
-}
 
 static void bta2dp_connection_state_callback(btav_connection_state_t state, bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    ALOGI("%s", __FUNCTION__);
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    if (!checkCallbackThread()) {                                       \
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
-        return;                                                         \
-    }
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for connection state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, (jint) state,
                                  addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void bta2dp_audio_state_callback(btav_audio_state_t state, bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    ALOGI("%s", __FUNCTION__);
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    if (!checkCallbackThread()) {                                       \
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
-        return;                                                         \
-    }
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for connection state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint) state,
                                  addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void bta2dp_audio_config_callback(bt_bdaddr_t *bd_addr, uint32_t sample_rate, uint8_t channel_count) {
     jbyteArray addr;
 
-    ALOGI("%s", __FUNCTION__);
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    if (!checkCallbackThread()) {                                       \
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
-        return;                                                         \
-    }
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for connection state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioConfigChanged, addr, (jint)sample_rate, (jint)channel_count);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
diff --git a/jni/com_android_bluetooth_avrcp.cpp b/jni/com_android_bluetooth_avrcp.cpp
index 7fda163..7dd5ffc 100644
--- a/jni/com_android_bluetooth_avrcp.cpp
+++ b/jni/com_android_bluetooth_avrcp.cpp
@@ -25,15 +25,6 @@
 
 #include <string.h>
 
-#define CHECK_CALLBACK_ENV()\
-do { \
-   if (!checkCallbackThread()) { \
-       ALOGE("Callback: '%s' is not called on the correct thread", __func__); \
-       return; \
-   } \
-} while (0)
-
-
 namespace android {
 static jmethodID method_getRcFeatures;
 static jmethodID method_getPlayStatus;
@@ -54,7 +45,6 @@
 
 static const btrc_interface_t *sBluetoothAvrcpInterface = NULL;
 static jobject mCallbacksObj = NULL;
-static JNIEnv *sCallbackEnv = NULL;
 
 /* Function declarations */
 static bool copy_item_attributes(JNIEnv *env, jobject object, btrc_folder_items_t *pitem,
@@ -64,28 +54,17 @@
 
 static void cleanup_items(btrc_folder_items_t* p_items, int numItems);
 
-static bool checkCallbackThread() {
-    // Always fetch the latest callbackEnv from AdapterService.
-    // Caching this could cause this sCallbackEnv to go out-of-sync
-    // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event
-    // is received
-    sCallbackEnv = getCallbackEnv();
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (sCallbackEnv != env || sCallbackEnv == NULL) return false;
-    return true;
-}
-
 static void btavrcp_remote_features_callback(bt_bdaddr_t* bd_addr,
         btrc_remote_features_t features) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV();
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Unable to allocate byte array for bd_addr");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
 
@@ -96,23 +75,21 @@
         ALOGE("%s: mCallbacksObj is null", __func__);
     }
 
-
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 
 /** Callback for play status request */
 static void btavrcp_get_play_status_callback(bt_bdaddr_t* bd_addr) {
-    ALOGI("%s", __func__);
 
     jbyteArray addr;
-    CHECK_CALLBACK_ENV();
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for get_play_status command");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
 
@@ -122,7 +99,6 @@
     } else {
         ALOGE("%s: mCallbacksObj is null", __func__);
     }
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
@@ -131,19 +107,19 @@
     jbyteArray addr;
     jintArray attrs;
 
-    CHECK_CALLBACK_ENV();
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for get_element_attr command");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
 
     attrs = (jintArray)sCallbackEnv->NewIntArray(num_attr);
     if (!attrs) {
         ALOGE("Fail to new jintArray for attrs");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         sCallbackEnv->DeleteLocalRef(addr);
         return;
     }
@@ -158,7 +134,6 @@
         ALOGE("%s: mCallbacksObj is null", __func__);
     }
 
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
     sCallbackEnv->DeleteLocalRef(attrs);
     sCallbackEnv->DeleteLocalRef(addr);
 }
@@ -167,12 +142,13 @@
     bt_bdaddr_t *bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV();
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for register_notification command");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
 
@@ -184,7 +160,6 @@
         ALOGE("%s: mCallbacksObj is null", __func__);
     }
 
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
@@ -193,12 +168,13 @@
     bt_bdaddr_t *bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV();
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for volume_change command");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
@@ -211,19 +187,19 @@
     }
 
     sCallbackEnv->DeleteLocalRef(addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
 }
 
 static void btavrcp_passthrough_command_callback(int id, int pressed,
     bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV();
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for passthrough_command command");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
@@ -235,7 +211,6 @@
         ALOGE("%s: mCallbacksObj is null", __func__);
     }
 
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
@@ -243,12 +218,14 @@
     bt_bdaddr_t *bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV();
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for set_addressed_player command");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
 
@@ -260,19 +237,20 @@
         ALOGE("%s: mCallbacksObj is null", __func__);
     }
 
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void btavrcp_set_browsed_player_callback(uint16_t player_id, bt_bdaddr_t *bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV();
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for set_browsed_player command");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
@@ -284,7 +262,6 @@
         ALOGE("%s: mCallbacksObj is null", __func__);
     }
 
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
@@ -294,12 +271,14 @@
     jintArray attr_ids = NULL;
     uint32_t *puiAttr = (uint32_t *)p_attr_ids;
 
-    CHECK_CALLBACK_ENV();
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for get_folder_items command");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
 
@@ -313,7 +292,6 @@
             attr_ids = (jintArray)sCallbackEnv->NewIntArray(num_attr);
             if (!attr_ids) {
                 ALOGE("Fail to allocate new jintArray for attrs");
-                checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
                 sCallbackEnv->DeleteLocalRef(addr);
                 return;
             }
@@ -327,7 +305,6 @@
     }
 
     if (attr_ids != NULL) sCallbackEnv->DeleteLocalRef(attr_ids);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
@@ -337,19 +314,20 @@
     jbyteArray addr;
     jbyteArray attrs;;
 
-    CHECK_CALLBACK_ENV();
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
 
     attrs = sCallbackEnv->NewByteArray(BTRC_UID_SIZE);
     if (!attrs) {
         ALOGE("Fail to new jintArray for attrs");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for change_path command");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         sCallbackEnv->DeleteLocalRef(attrs);
         return;
     }
@@ -364,7 +342,6 @@
         ALOGE("%s: mCallbacksObj is null", __func__);
     }
 
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
     sCallbackEnv->DeleteLocalRef(attrs);
     sCallbackEnv->DeleteLocalRef(addr);
 }
@@ -376,19 +353,20 @@
     jintArray attrs;
     jbyteArray attr_uid;
 
-    CHECK_CALLBACK_ENV();
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
 
     attr_uid = sCallbackEnv->NewByteArray(BTRC_UID_SIZE);
     if (!attr_uid) {
         ALOGE("Fail to new jintArray for attr_uid");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for get_item_attr command");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         sCallbackEnv->DeleteLocalRef(attr_uid);
         return;
     }
@@ -396,7 +374,6 @@
     attrs = (jintArray)sCallbackEnv->NewIntArray(num_attr);
     if (!attrs) {
         ALOGE("Fail to new jintArray for attrs");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         sCallbackEnv->DeleteLocalRef(attr_uid);
         sCallbackEnv->DeleteLocalRef(addr);
         return;
@@ -413,7 +390,6 @@
         ALOGE("%s: mCallbacksObj is null", __func__);
     }
 
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
     sCallbackEnv->DeleteLocalRef(attr_uid);
     sCallbackEnv->DeleteLocalRef(attrs);
     sCallbackEnv->DeleteLocalRef(addr);
@@ -425,19 +401,19 @@
     jbyteArray addr;
     jbyteArray attrs;
 
-    CHECK_CALLBACK_ENV();
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
 
     attrs = sCallbackEnv->NewByteArray(BTRC_UID_SIZE);
     if (!attrs) {
         ALOGE("%s:Fail to new jByteArray attrs for play_item command", __func__);
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for play_item command");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         sCallbackEnv->DeleteLocalRef(attrs);
         return;
     }
@@ -451,7 +427,6 @@
         ALOGE("%s: mCallbacksObj is null", __func__);
     }
 
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
     sCallbackEnv->DeleteLocalRef(attrs);
     sCallbackEnv->DeleteLocalRef(addr);
 }
@@ -460,12 +435,13 @@
 
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV();
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for get_total_num_items command");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
 
@@ -477,7 +453,6 @@
         ALOGE("%s: mCallbacksObj is null", __func__);
     }
 
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
@@ -487,19 +462,19 @@
     jbyteArray addr;
     jbyteArray attrs;
 
-    CHECK_CALLBACK_ENV();
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
 
     attrs = sCallbackEnv->NewByteArray(str_len);
     if (!attrs) {
         ALOGE("Fail to new jintArray for attrs");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for search command");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         sCallbackEnv->DeleteLocalRef(attrs);
         return;
     }
@@ -514,7 +489,6 @@
         ALOGE("%s: mCallbacksObj is null", __func__);
     }
 
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
     sCallbackEnv->DeleteLocalRef(attrs);
     sCallbackEnv->DeleteLocalRef(addr);
 }
@@ -524,19 +498,19 @@
     jbyteArray attrs;
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV();
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for add_to_play_list command");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
 
     attrs = sCallbackEnv->NewByteArray(BTRC_UID_SIZE);
     if (!attrs) {
         ALOGE("Fail to new jByteArray for attrs");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         sCallbackEnv->DeleteLocalRef(addr);
         return;
     }
@@ -550,7 +524,6 @@
         ALOGE("%s: mCallbacksObj is null", __func__);
     }
 
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
     sCallbackEnv->DeleteLocalRef(attrs);
     sCallbackEnv->DeleteLocalRef(addr);
 }
diff --git a/jni/com_android_bluetooth_avrcp_controller.cpp b/jni/com_android_bluetooth_avrcp_controller.cpp
index 457b771..41ab260 100644
--- a/jni/com_android_bluetooth_avrcp_controller.cpp
+++ b/jni/com_android_bluetooth_avrcp_controller.cpp
@@ -51,35 +51,17 @@
 
 static const btrc_ctrl_interface_t *sBluetoothAvrcpInterface = NULL;
 static jobject sCallbacksObj = NULL;
-static JNIEnv *sCallbackEnv = NULL;
-static JNIEnv *sEnv = NULL;
-
-static bool checkCallbackThread() {
-    // Always fetch the latest callbackEnv from AdapterService.
-    // Caching this could cause this sCallbackEnv to go out-of-sync
-    // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event
-    // is received
-    sCallbackEnv = getCallbackEnv();
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (sCallbackEnv != env || sCallbackEnv == NULL) return false;
-    return true;
-}
 
 static void btavrcp_passthrough_response_callback(bt_bdaddr_t* bd_addr, int id, int pressed)  {
     jbyteArray addr;
 
-    ALOGI("%s", __func__);
-    ALOGI("id: %d, pressed: %d", id, pressed);
+    ALOGI("%s: id: %d, pressed: %d", __func__, id, pressed);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    if (!checkCallbackThread()) {
-        ALOGE("Callback: '%s' is not called on the correct thread", __func__);
-        return;
-    }
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for passthrough response");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
         return;
     }
 
@@ -88,70 +70,53 @@
     sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handlePassthroughRsp, (jint)id,
                                                                              (jint)pressed,
                                                                              addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
-
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void btavrcp_groupnavigation_response_callback(int id, int pressed) {
-    ALOGV("%s", __FUNCTION__);
-
-    if (!checkCallbackThread()) {
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
-        return;
-    }
+    ALOGV("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleGroupNavigationRsp, (jint)id,
                                                                              (jint)pressed);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static void btavrcp_connection_state_callback(
         bool rc_connect, bool br_connect, bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    ALOGV("%s", __FUNCTION__);
-    ALOGI("%s conn state rc: %d br: %d", __FUNCTION__, rc_connect, br_connect);
-
-    if (!checkCallbackThread()) {                                       \
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
-        return;                                                         \
-    }
+    ALOGI("%s: conn state: rc: %d br: %d", __func__, rc_connect, br_connect);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for connection state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
     sCallbackEnv->CallVoidMethod(sCallbacksObj, method_onConnectionStateChanged,
                                  (jboolean) rc_connect, (jboolean) br_connect, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void btavrcp_get_rcfeatures_callback(bt_bdaddr_t *bd_addr, int features) {
     jbyteArray addr;
 
-    ALOGV("%s", __FUNCTION__);
-
-    if (!checkCallbackThread()) {                                       \
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
-        return;                                                         \
-    }
+    ALOGV("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr ");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
     sCallbackEnv->CallVoidMethod(sCallbacksObj, method_getRcFeatures, addr, (jint)features);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
@@ -159,44 +124,36 @@
                                                                     uint8_t accepted) {
     jbyteArray addr;
 
-    ALOGV("%s", __FUNCTION__);
-
-    if (!checkCallbackThread()) {                                       \
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
-        return;                                                         \
-    }
+    ALOGV("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr ");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
     sCallbackEnv->CallVoidMethod(sCallbacksObj, method_setplayerappsettingrsp, addr, (jint)accepted);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void btavrcp_playerapplicationsetting_callback(bt_bdaddr_t *bd_addr, uint8_t num_attr,
         btrc_player_app_attr_t *app_attrs, uint8_t num_ext_attr,
         btrc_player_app_ext_attr_t *ext_attrs) {
-    ALOGV("%s", __FUNCTION__);
     jbyteArray addr;
     jbyteArray playerattribs;
     jint arraylen;
     int i,k;
 
-    if (!checkCallbackThread()) {                                       \
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
-        return;                                                         \
-    }
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr ");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
@@ -214,7 +171,6 @@
     if(!playerattribs)
     {
         ALOGE("Fail to new jbyteArray playerattribs ");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         sCallbackEnv->DeleteLocalRef(addr);
         return;
     }
@@ -231,7 +187,6 @@
     }
     sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleplayerappsetting, addr,
             playerattribs, (jint)arraylen);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
     sCallbackEnv->DeleteLocalRef(playerattribs);
 }
@@ -242,17 +197,14 @@
     jbyteArray addr;
     jbyteArray playerattribs;
     int i, k, arraylen;
-    ALOGI("%s", __FUNCTION__);
 
-    if (!checkCallbackThread()) {                                       \
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
-        return;                                                         \
-    }
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if ((!addr)) {
         ALOGE("Fail to get new array ");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
@@ -261,7 +213,6 @@
     if(!playerattribs)
     {
         ALOGE("Fail to new jbyteArray playerattribs ");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         sCallbackEnv->DeleteLocalRef(addr);
         return;
     }
@@ -278,57 +229,46 @@
     }
     sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleplayerappsettingchanged, addr,
             playerattribs, (jint)arraylen);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
     sCallbackEnv->DeleteLocalRef(playerattribs);
 }
 
 static void btavrcp_set_abs_vol_cmd_callback(bt_bdaddr_t *bd_addr, uint8_t abs_vol,
         uint8_t label) {
-
     jbyteArray addr;
-    ALOGI("%s", __FUNCTION__);
 
-    if (!checkCallbackThread()) {                                       \
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
-        return;                                                         \
-    }
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if ((!addr)) {
         ALOGE("Fail to get new array ");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
     sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleSetAbsVolume, addr, (jbyte)abs_vol,
                                  (jbyte)label);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void btavrcp_register_notification_absvol_callback(bt_bdaddr_t *bd_addr, uint8_t label) {
     jbyteArray addr;
 
-    ALOGI("%s", __FUNCTION__);
-
-    if (!checkCallbackThread()) {                                       \
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
-        return;                                                         \
-    }
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if ((!addr)) {
         ALOGE("Fail to get new array ");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
     sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleRegisterNotificationAbsVol, addr,
                                  (jbyte)label);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
@@ -344,22 +284,18 @@
     jstring str;
     jclass strclazz;
     jint i;
-    ALOGI("%s", __FUNCTION__);
-    if (!checkCallbackThread()) {                                       \
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__); \
-        return;                                                         \
-    }
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if ((!addr)) {
         ALOGE("Fail to get new array ");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
     attribIds = sCallbackEnv->NewIntArray(num_attr);
     if(!attribIds) {
         ALOGE(" failed to set new array for attribIds");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         sCallbackEnv->DeleteLocalRef(addr);
         return;
     }
@@ -369,7 +305,6 @@
     stringArray = sCallbackEnv->NewObjectArray((jint)num_attr, strclazz, 0);
     if(!stringArray) {
         ALOGE(" failed to get String array");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         sCallbackEnv->DeleteLocalRef(addr);
         sCallbackEnv->DeleteLocalRef(attribIds);
         return;
@@ -379,7 +314,6 @@
         str = sCallbackEnv->NewStringUTF((char*)(p_attrs[i].text));
         if(!str) {
             ALOGE(" Unable to get str ");
-            checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
             sCallbackEnv->DeleteLocalRef(addr);
             sCallbackEnv->DeleteLocalRef(attribIds);
             sCallbackEnv->DeleteLocalRef(stringArray);
@@ -392,7 +326,6 @@
 
     sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handletrackchanged, addr,
          (jbyte)(num_attr), attribIds, stringArray);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
     sCallbackEnv->DeleteLocalRef(attribIds);
     /* TODO check do we need to delete str seperately or not */
@@ -404,12 +337,13 @@
         uint32_t song_pos) {
 
     jbyteArray addr;
-    ALOGI("%s", __FUNCTION__);
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
-    if ((!addr)) {
+    if (!addr) {
         ALOGE("Fail to get new array ");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
@@ -421,12 +355,13 @@
 static void btavrcp_play_status_changed_callback(bt_bdaddr_t *bd_addr,
         btrc_play_status_t play_status) {
     jbyteArray addr;
-    ALOGI("%s", __FUNCTION__);
+    ALOGI("%s", __func__);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
-    if ((!addr)) {
+    if (!addr) {
         ALOGE("Fail to get new array ");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
@@ -441,12 +376,9 @@
      * BTRC_ITEM_MEDIA, BTRC_ITEM_FOLDER. Here we translate them to their java
      * counterparts by calling the java constructor for each of the items.
      */
-    ALOGV("%s count %d", __FUNCTION__, count);
-
-    if (!checkCallbackThread()) {
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
-        return;
-    }
+    ALOGV("%s count %d", __func__, count);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     // Inspect if the first element is a folder/item or player listing. They are
     // always exclusive.
@@ -459,7 +391,6 @@
         playerItemArray = sCallbackEnv->NewObjectArray((jint) count, class_AvrcpPlayer, 0);
         if (!playerItemArray) {
             ALOGE("%s playerItemArray allocation failed.", __FUNCTION__);
-            checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
             return;
         }
     } else {
@@ -467,7 +398,6 @@
             (jint) count, class_MediaBrowser_MediaItem, 0);
         if (!folderItemArray) {
             ALOGE("%s folderItemArray is empty.", __FUNCTION__);
-            checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
             return;
         }
     }
@@ -558,7 +488,6 @@
                     ALOGE("%s failed to allocate featureBitArray", __FUNCTION__);
                     sCallbackEnv->DeleteLocalRef(playerItemArray);
                     sCallbackEnv->DeleteLocalRef(folderItemArray);
-                    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
                     return;
                 }
                 sCallbackEnv->SetByteArrayRegion(
@@ -597,24 +526,18 @@
 }
 
 static void btavrcp_change_path_callback(bt_bdaddr_t *bd_addr, uint8_t count) {
-    ALOGI("%s count %d", __FUNCTION__, count);
-
-    if (!checkCallbackThread()) {
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
-        return;
-    }
+    ALOGI("%s count %d", __func__, count);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     sCallbackEnv->CallVoidMethod(sCallbacksObj, method_handleChangeFolderRsp, (jint) count);
 }
 
 static void btavrcp_set_browsed_player_callback(
         bt_bdaddr_t *bd_addr, uint8_t num_items, uint8_t depth) {
-    ALOGI("%s items %d depth %d", __FUNCTION__, num_items, depth);
-
-    if (!checkCallbackThread()) {
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
-        return;
-    }
+    ALOGI("%s items %d depth %d", __func__, num_items, depth);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     sCallbackEnv->CallVoidMethod(
         sCallbacksObj, method_handleSetBrowsedPlayerRsp, (jint) num_items, (jint) depth);
@@ -701,7 +624,6 @@
 static void initNative(JNIEnv *env, jobject object) {
     const bt_interface_t* btInf;
     bt_status_t status;
-    sEnv = env;
 
     jclass tmpMediaItem = env->FindClass("android/media/browse/MediaBrowser$MediaItem");
     class_MediaBrowser_MediaItem = (jclass) env->NewGlobalRef(tmpMediaItem);
diff --git a/jni/com_android_bluetooth_btservice_AdapterService.cpp b/jni/com_android_bluetooth_btservice_AdapterService.cpp
index bba1ba4..c6c803d 100755
--- a/jni/com_android_bluetooth_btservice_AdapterService.cpp
+++ b/jni/com_android_bluetooth_btservice_AdapterService.cpp
@@ -63,7 +63,6 @@
 static jobject sJniCallbacksObj;
 static jfieldID sJniCallbacksField;
 
-
 const bt_interface_t* getBluetoothInterface() {
     return sBluetoothInterface;
 }
@@ -72,34 +71,12 @@
     return callbackEnv;
 }
 
-void checkAndClearExceptionFromCallback(JNIEnv* env,
-                                               const char* methodName) {
-    if (env->ExceptionCheck()) {
-        ALOGE("An exception was thrown by callback '%s'.", methodName);
-        LOGE_EX(env);
-        env->ExceptionClear();
-    }
-}
-
-static bool checkCallbackThread() {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (callbackEnv != env || callbackEnv == NULL) {
-        ALOGE("Callback env check fail: env: %p, callback: %p", env, callbackEnv);
-        return false;
-    }
-    return true;
-}
-
 static void adapter_state_change_callback(bt_state_t status) {
-    if (!checkCallbackThread()) {
-       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
-       return;
-    }
-    ALOGV("%s: Status is: %d", __FUNCTION__, status);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+    ALOGV("%s: Status is: %d", __func__, status);
 
-    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status);
-
-    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
+    sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status);
 }
 
 static int get_properties(int num_properties, bt_property_t *properties, jintArray *types,
@@ -130,10 +107,8 @@
     jbyteArray val;
     jclass mclass;
 
-    if (!checkCallbackThread()) {
-       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
-       return;
-    }
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
 
@@ -142,55 +117,50 @@
         return;
     }
 
-    val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
+    val = (jbyteArray) sCallbackEnv->NewByteArray(num_properties);
     if (val == NULL) {
         ALOGE("%s: Error allocating byteArray", __FUNCTION__);
         return;
     }
 
-    mclass = callbackEnv->GetObjectClass(val);
+    mclass = sCallbackEnv->GetObjectClass(val);
 
     /* (BT) Initialize the jobjectArray and jintArray here itself and send the
      initialized array pointers alone to get_properties */
 
-    props = callbackEnv->NewObjectArray(num_properties, mclass,
+    props = sCallbackEnv->NewObjectArray(num_properties, mclass,
                                              NULL);
     if (props == NULL) {
         ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
         return;
     }
 
-    types = (jintArray)callbackEnv->NewIntArray(num_properties);
+    types = (jintArray)sCallbackEnv->NewIntArray(num_properties);
 
     if (types == NULL) {
         ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
         return;
     }
     // Delete the reference to val and mclass
-    callbackEnv->DeleteLocalRef(mclass);
-    callbackEnv->DeleteLocalRef(val);
+    sCallbackEnv->DeleteLocalRef(mclass);
+    sCallbackEnv->DeleteLocalRef(val);
 
     if (get_properties(num_properties, properties, &types, &props) < 0) {
-        if (props) callbackEnv->DeleteLocalRef(props);
-        if (types) callbackEnv->DeleteLocalRef(types);
+        if (props) sCallbackEnv->DeleteLocalRef(props);
+        if (types) sCallbackEnv->DeleteLocalRef(types);
         return;
     }
 
-    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_adapterPropertyChangedCallback, types,
+    sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_adapterPropertyChangedCallback, types,
                                 props);
-    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
-    callbackEnv->DeleteLocalRef(props);
-    callbackEnv->DeleteLocalRef(types);
-    return;
-
+    sCallbackEnv->DeleteLocalRef(props);
+    sCallbackEnv->DeleteLocalRef(types);
 }
 
 static void remote_device_properties_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
                                               int num_properties, bt_property_t *properties) {
-    if (!checkCallbackThread()) {
-       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
-       return;
-    }
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
 
@@ -199,7 +169,7 @@
         return;
     }
 
-    callbackEnv->PushLocalFrame(ADDITIONAL_NREFS);
+    sCallbackEnv->PushLocalFrame(ADDITIONAL_NREFS);
 
     jobjectArray props;
     jbyteArray addr;
@@ -207,68 +177,69 @@
     jbyteArray val;
     jclass mclass;
 
-    val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
+    val = (jbyteArray) sCallbackEnv->NewByteArray(num_properties);
     if (val == NULL) {
         ALOGE("%s: Error allocating byteArray", __FUNCTION__);
         return;
     }
 
-    mclass = callbackEnv->GetObjectClass(val);
+    mclass = sCallbackEnv->GetObjectClass(val);
 
     /* Initialize the jobjectArray and jintArray here itself and send the
      initialized array pointers alone to get_properties */
 
-    props = callbackEnv->NewObjectArray(num_properties, mclass,
+    props = sCallbackEnv->NewObjectArray(num_properties, mclass,
                                              NULL);
     if (props == NULL) {
         ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
         return;
     }
 
-    types = (jintArray)callbackEnv->NewIntArray(num_properties);
+    types = (jintArray)sCallbackEnv->NewIntArray(num_properties);
 
     if (types == NULL) {
         ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
         return;
     }
     // Delete the reference to val and mclass
-    callbackEnv->DeleteLocalRef(mclass);
-    callbackEnv->DeleteLocalRef(val);
+    sCallbackEnv->DeleteLocalRef(mclass);
+    sCallbackEnv->DeleteLocalRef(val);
 
-    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
-    if (addr == NULL) goto Fail;
-    if (addr) callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
+    addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
+    if (addr == NULL) {
+      ALOGE("Error while allocation byte array in %s", __FUNCTION__);
+      return;
+    }
+
+    sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
 
     if (get_properties(num_properties, properties, &types, &props) < 0) {
-        if (props) callbackEnv->DeleteLocalRef(props);
-        if (types) callbackEnv->DeleteLocalRef(types);
-        callbackEnv->PopLocalFrame(NULL);
+        if (props) sCallbackEnv->DeleteLocalRef(props);
+        if (types) sCallbackEnv->DeleteLocalRef(types);
+        sCallbackEnv->PopLocalFrame(NULL);
         return;
     }
 
-    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_devicePropertyChangedCallback, addr,
+    sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_devicePropertyChangedCallback, addr,
                                 types, props);
-    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
-    callbackEnv->DeleteLocalRef(props);
-    callbackEnv->DeleteLocalRef(types);
-    callbackEnv->DeleteLocalRef(addr);
-    callbackEnv->PopLocalFrame(NULL);
-    return;
-
-Fail:
-    ALOGE("Error while allocation byte array in %s", __FUNCTION__);
+    sCallbackEnv->DeleteLocalRef(props);
+    sCallbackEnv->DeleteLocalRef(types);
+    sCallbackEnv->DeleteLocalRef(addr);
+    sCallbackEnv->PopLocalFrame(NULL);
 }
 
 
 static void device_found_callback(int num_properties, bt_property_t *properties) {
     jbyteArray addr = NULL;
     int addr_index;
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     for (int i = 0; i < num_properties; i++) {
         if (properties[i].type == BT_PROPERTY_BDADDR) {
-            addr = callbackEnv->NewByteArray(properties[i].len);
+            addr = sCallbackEnv->NewByteArray(properties[i].len);
             if (addr) {
-                callbackEnv->SetByteArrayRegion(addr, 0, properties[i].len,
+                sCallbackEnv->SetByteArrayRegion(addr, 0, properties[i].len,
                                                 (jbyte*)properties[i].val);
                 addr_index = i;
             } else {
@@ -288,142 +259,129 @@
     remote_device_properties_callback(BT_STATUS_SUCCESS, (bt_bdaddr_t *)properties[addr_index].val,
                                       num_properties, properties);
 
-    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr);
-    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
-    callbackEnv->DeleteLocalRef(addr);
+    sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr);
+    sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void bond_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
                                         bt_bond_state_t state) {
     jbyteArray addr;
-    if (!checkCallbackThread()) {
-       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
-       return;
-    }
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
     if (!bd_addr) {
         ALOGE("Address is null in %s", __FUNCTION__);
         return;
     }
-    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
+    addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (addr == NULL) {
        ALOGE("Address allocation failed in %s", __FUNCTION__);
        return;
     }
-    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
+    sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
 
-    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback, (jint) status,
+    sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback, (jint) status,
                                 addr, (jint)state);
-    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
-    callbackEnv->DeleteLocalRef(addr);
+    sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void acl_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
                                        bt_acl_state_t state)
 {
     jbyteArray addr;
-    if (!checkCallbackThread()) {
-       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
-       return;
-    }
+
     if (!bd_addr) {
         ALOGE("Address is null in %s", __FUNCTION__);
         return;
     }
-    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
+
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
+    addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (addr == NULL) {
        ALOGE("Address allocation failed in %s", __FUNCTION__);
        return;
     }
-    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
+    sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
 
-    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_aclStateChangeCallback, (jint) status,
+    sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_aclStateChangeCallback, (jint) status,
                                 addr, (jint)state);
-    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
-    callbackEnv->DeleteLocalRef(addr);
+    sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void discovery_state_changed_callback(bt_discovery_state_t state) {
-    if (!checkCallbackThread()) {
-       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
-       return;
-    }
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     ALOGV("%s: DiscoveryState:%d ", __FUNCTION__, state);
 
-    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback,
+    sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback,
                                 (jint)state);
-
-    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
 }
 
 static void pin_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
         bool min_16_digits) {
     jbyteArray addr = NULL;
     jbyteArray devname = NULL;
-    if (!checkCallbackThread()) {
-       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
-       return;
-    }
     if (!bd_addr) {
         ALOGE("Address is null in %s", __FUNCTION__);
         return;
     }
 
-    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
-    if (addr == NULL) goto Fail;
-    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
+    addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
+    if (addr == NULL) goto Fail;
+    sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
+
+    devname = sCallbackEnv->NewByteArray(sizeof(bt_bdname_t));
     if (devname == NULL) goto Fail;
 
-    callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
+    sCallbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
 
-    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_pinRequestCallback, addr, devname, cod,
+    sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_pinRequestCallback, addr, devname, cod,
             min_16_digits);
-
-    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
-    callbackEnv->DeleteLocalRef(addr);
-    callbackEnv->DeleteLocalRef(devname);
+    sCallbackEnv->DeleteLocalRef(addr);
+    sCallbackEnv->DeleteLocalRef(devname);
     return;
 
 Fail:
-    if (addr) callbackEnv->DeleteLocalRef(addr);
-    if (devname) callbackEnv->DeleteLocalRef(devname);
-    ALOGE("Error while allocating in: %s", __FUNCTION__);
+    if (addr) sCallbackEnv->DeleteLocalRef(addr);
+    if (devname) sCallbackEnv->DeleteLocalRef(devname);
+    ALOGE("Error while allocating in: %s", __func__);
 }
 
 static void ssp_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
                                  bt_ssp_variant_t pairing_variant, uint32_t pass_key) {
     jbyteArray addr = NULL;
     jbyteArray devname = NULL;
-    if (!checkCallbackThread()) {
-       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
-       return;
-    }
     if (!bd_addr) {
         ALOGE("Address is null in %s", __FUNCTION__);
         return;
     }
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
+    addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (addr == NULL) goto Fail;
-    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
+    sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
 
-    devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
+    devname = sCallbackEnv->NewByteArray(sizeof(bt_bdname_t));
     if (devname == NULL) goto Fail;
-    callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
+    sCallbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
 
-    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod,
+    sCallbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod,
                                 (jint) pairing_variant, pass_key);
 
-    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
-    callbackEnv->DeleteLocalRef(addr);
-    callbackEnv->DeleteLocalRef(devname);
+    sCallbackEnv->DeleteLocalRef(addr);
+    sCallbackEnv->DeleteLocalRef(devname);
     return;
 
 Fail:
-    if (addr) callbackEnv->DeleteLocalRef(addr);
-    if (devname) callbackEnv->DeleteLocalRef(devname);
+    if (addr) sCallbackEnv->DeleteLocalRef(addr);
+    if (devname) sCallbackEnv->DeleteLocalRef(devname);
 
     ALOGE("Error while allocating in: %s", __FUNCTION__);
 }
@@ -439,7 +397,7 @@
         vm->AttachCurrentThread(&callbackEnv, &args);
         ALOGV("Callback thread attached: %p", callbackEnv);
     } else if (event == DISASSOCIATE_JVM) {
-        if (!checkCallbackThread()) {
+        if (callbackEnv != AndroidRuntime::getJNIEnv()) {
             ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
             return;
         }
@@ -456,35 +414,31 @@
 }
 
 static void energy_info_recv_callback(bt_activity_energy_info *p_energy_info,
-                                      bt_uid_traffic_t* uid_data)
-{
-    if (!checkCallbackThread()) {
-       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
-       return;
-    }
+                                      bt_uid_traffic_t* uid_data) {
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     jsize len = 0;
     for (bt_uid_traffic_t* data = uid_data; data->app_uid != -1; data++) {
         len++;
     }
 
-    jobjectArray array = callbackEnv->NewObjectArray(len, android_bluetooth_UidTraffic.clazz, NULL);
+    jobjectArray array = sCallbackEnv->NewObjectArray(len, android_bluetooth_UidTraffic.clazz, NULL);
     jsize i = 0;
     for (bt_uid_traffic_t* data = uid_data; data->app_uid != -1; data++) {
-        jobject uidObj = callbackEnv->NewObject(android_bluetooth_UidTraffic.clazz,
+        jobject uidObj = sCallbackEnv->NewObject(android_bluetooth_UidTraffic.clazz,
                                                 android_bluetooth_UidTraffic.constructor,
                                                 (jint) data->app_uid, (jlong) data->rx_bytes,
                                                 (jlong) data->tx_bytes);
-        callbackEnv->SetObjectArrayElement(array, i++, uidObj);
-        callbackEnv->DeleteLocalRef(uidObj);
+        sCallbackEnv->SetObjectArrayElement(array, i++, uidObj);
+        sCallbackEnv->DeleteLocalRef(uidObj);
     }
 
-    callbackEnv->CallVoidMethod(sJniAdapterServiceObj, method_energyInfo, p_energy_info->status,
+    sCallbackEnv->CallVoidMethod(sJniAdapterServiceObj, method_energyInfo, p_energy_info->status,
         p_energy_info->ctrl_state, p_energy_info->tx_time, p_energy_info->rx_time,
         p_energy_info->idle_time, p_energy_info->energy_used, array);
 
-    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
-    callbackEnv->DeleteLocalRef(array);
+    sCallbackEnv->DeleteLocalRef(array);
 }
 
 static bt_callbacks_t sBluetoothCallbacks = {
diff --git a/jni/com_android_bluetooth_gatt.cpp b/jni/com_android_bluetooth_gatt.cpp
index 70dcfea..06c7939 100644
--- a/jni/com_android_bluetooth_gatt.cpp
+++ b/jni/com_android_bluetooth_gatt.cpp
@@ -19,12 +19,6 @@
 
 #define LOG_NDEBUG 0
 
-#define CHECK_CALLBACK_ENV                                                      \
-   if (!checkCallbackThread()) {                                                \
-       error("Callback: '%s' is not called on the correct thread", __FUNCTION__);\
-       return;                                                                  \
-   }
-
 #include "com_android_bluetooth.h"
 #include "hardware/bt_gatt.h"
 #include "utils/Log.h"
@@ -198,15 +192,6 @@
 
 static const btgatt_interface_t *sGattIf = NULL;
 static jobject mCallbacksObj = NULL;
-static JNIEnv *sCallbackEnv = NULL;
-
-static bool checkCallbackThread() {
-    sCallbackEnv = getCallbackEnv();
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (sCallbackEnv != env || sCallbackEnv == NULL) return false;
-    return true;
-}
 
 /**
  * BTA client callbacks
@@ -214,17 +199,18 @@
 
 void btgattc_register_app_cb(int status, int clientIf, bt_uuid_t *app_uuid)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClientRegistered, status,
         clientIf, UUID_PARAMS(app_uuid));
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_scan_result_cb(bt_bdaddr_t* bda, int rssi, vector<uint8_t> adv_data)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    jstring address = bdaddr2newjstr(sCallbackEnv, bda);
+    jstring address = bdaddr2newjstr(sCallbackEnv.get(), bda);
     jbyteArray jb = sCallbackEnv->NewByteArray(62);
     sCallbackEnv->SetByteArrayRegion(jb, 0, 62, (jbyte *) adv_data.data());
 
@@ -233,52 +219,54 @@
 
     sCallbackEnv->DeleteLocalRef(address);
     sCallbackEnv->DeleteLocalRef(jb);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_open_cb(int conn_id, int status, int clientIf, bt_bdaddr_t* bda)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    jstring address = bdaddr2newjstr(sCallbackEnv, bda);
+    jstring address = bdaddr2newjstr(sCallbackEnv.get(), bda);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnected,
         clientIf, conn_id, status, address);
     sCallbackEnv->DeleteLocalRef(address);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_close_cb(int conn_id, int status, int clientIf, bt_bdaddr_t* bda)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    jstring address = bdaddr2newjstr(sCallbackEnv, bda);
+    jstring address = bdaddr2newjstr(sCallbackEnv.get(), bda);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onDisconnected,
         clientIf, conn_id, status, address);
     sCallbackEnv->DeleteLocalRef(address);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_search_complete_cb(int conn_id, int status)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSearchCompleted,
                                  conn_id, status);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_register_for_notification_cb(int conn_id, int registered, int status, uint16_t handle)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRegisterForNotifications,
         conn_id, status, registered, handle);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_notify_cb(int conn_id, btgatt_notify_params_t *p_data)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    jstring address = bdaddr2newjstr(sCallbackEnv, &p_data->bda);
+    jstring address = bdaddr2newjstr(sCallbackEnv.get(), &p_data->bda);
     jbyteArray jb = sCallbackEnv->NewByteArray(p_data->len);
     sCallbackEnv->SetByteArrayRegion(jb, 0, p_data->len, (jbyte *) p_data->value);
 
@@ -287,12 +275,12 @@
 
     sCallbackEnv->DeleteLocalRef(address);
     sCallbackEnv->DeleteLocalRef(jb);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_read_characteristic_cb(int conn_id, int status, btgatt_read_params_t *p_data)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     jbyteArray jb;
     if ( status == 0 )      //successful
@@ -309,28 +297,30 @@
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onReadCharacteristic,
         conn_id, status, p_data->handle, jb);
     sCallbackEnv->DeleteLocalRef(jb);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_write_characteristic_cb(int conn_id, int status, uint16_t handle)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWriteCharacteristic
         , conn_id, status, handle);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_execute_write_cb(int conn_id, int status)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExecuteCompleted
         , conn_id, status);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_read_descriptor_cb(int conn_id, int status, btgatt_read_params_t *p_data)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     jbyteArray jb;
     if ( p_data->value.len != 0 )
@@ -346,117 +336,118 @@
         conn_id, status, p_data->handle, jb);
 
     sCallbackEnv->DeleteLocalRef(jb);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_write_descriptor_cb(int conn_id, int status, uint16_t handle)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
+
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWriteDescriptor
         , conn_id, status, handle);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_remote_rssi_cb(int client_if,bt_bdaddr_t* bda, int rssi, int status)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    jstring address = bdaddr2newjstr(sCallbackEnv, bda);
+    jstring address = bdaddr2newjstr(sCallbackEnv.get(), bda);
 
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onReadRemoteRssi,
        client_if, address, rssi, status);
     sCallbackEnv->DeleteLocalRef(address);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_advertise_cb(int status, int client_if)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAdvertiseCallback, status, client_if);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_configure_mtu_cb(int conn_id, int status, int mtu)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConfigureMTU,
                                  conn_id, status, mtu);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_scan_filter_cfg_cb(int action, int client_if, int status, int filt_type,
                                 int avbl_space)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onScanFilterConfig,
                                  action, status, client_if, filt_type, avbl_space);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_scan_filter_param_cb(int action, int client_if, int status, int avbl_space)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onScanFilterParamsConfigured,
             action, status, client_if, avbl_space);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_scan_filter_status_cb(int action, int client_if, int status)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onScanFilterEnableDisabled,
             action, status, client_if);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_congestion_cb(int conn_id, bool congested)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClientCongestion, conn_id, congested);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_batchscan_cfg_storage_cb(int client_if, int status)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onBatchScanStorageConfigured, status, client_if);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_batchscan_startstop_cb(int startstop_action, int client_if, int status)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onBatchScanStartStopped, startstop_action,
                                  status, client_if);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_batchscan_reports_cb(int client_if, int status, int report_format,
                         int num_records, std::vector<uint8_t> data)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     jbyteArray jb = sCallbackEnv->NewByteArray(data.size());
     sCallbackEnv->SetByteArrayRegion(jb, 0, data.size(), (jbyte *) data.data());
 
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onBatchScanReports, status, client_if,
                                 report_format, num_records, jb);
     sCallbackEnv->DeleteLocalRef(jb);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_batchscan_threshold_cb(int client_if)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onBatchScanThresholdCrossed, client_if);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_track_adv_event_cb(btgatt_track_adv_info_t *p_adv_track_info)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     jobject trackadv_obj = NULL;
 
-    jstring address = bdaddr2newjstr(sCallbackEnv, &p_adv_track_info->bd_addr);
+    jstring address = bdaddr2newjstr(sCallbackEnv.get(), &p_adv_track_info->bd_addr);
 
     jbyteArray jb_adv_pkt = sCallbackEnv->NewByteArray(p_adv_track_info->adv_pkt_len);
     jbyteArray jb_scan_rsp = sCallbackEnv->NewByteArray(p_adv_track_info->scan_rsp_len);
@@ -482,14 +473,13 @@
     sCallbackEnv->DeleteLocalRef(jb_adv_pkt);
     sCallbackEnv->DeleteLocalRef(jb_scan_rsp);
 
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgattc_scan_parameter_setup_completed_cb(int client_if, btgattc_error_t status)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onScanParamSetupCompleted, status, client_if);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __func__);
 }
 
 void fillGattDbElementArray(JNIEnv *env, jobject *array, const btgatt_db_element_t *db, int count) {
@@ -550,17 +540,17 @@
 
 void btgattc_get_gatt_db_cb(int conn_id, btgatt_db_element_t *db, int count)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     jclass arrayListclazz = sCallbackEnv->FindClass("java/util/ArrayList");
     jobject array = sCallbackEnv->NewObject(arrayListclazz, sCallbackEnv->GetMethodID(arrayListclazz, "<init>", "()V"));
 
-    fillGattDbElementArray(sCallbackEnv, &array, db, count);
+    fillGattDbElementArray(sCallbackEnv.get(), &array, db, count);
 
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGetGattDb, conn_id, array);
     sCallbackEnv->DeleteLocalRef(array);
 
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static const btgatt_client_callbacks_t sGattClientCallbacks = {
@@ -599,31 +589,31 @@
  */
 void ble_advertiser_register_cb(bt_uuid_t uuid, uint8_t advertiser_id, uint8_t status)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAdvertiserRegistered,
                                  status, advertiser_id, UUID_PARAMS(&uuid));
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void ble_advertiser_set_params_cb(uint8_t advertiser_id, uint8_t status)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMultiAdvSetParams, status, advertiser_id);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void ble_advertiser_setadv_data_cb(uint8_t advertiser_id, uint8_t status)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMultiAdvSetAdvData, status, advertiser_id);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void ble_advertiser_enable_cb(bool enable, uint8_t advertiser_id, uint8_t status)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onMultiAdvEnable, status, advertiser_id, enable);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 /**
@@ -632,79 +622,79 @@
 
 void btgatts_register_app_cb(int status, int server_if, bt_uuid_t *uuid)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServerRegistered
         , status, server_if, UUID_PARAMS(uuid));
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgatts_connection_cb(int conn_id, int server_if, int connected, bt_bdaddr_t *bda)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    jstring address = bdaddr2newjstr(sCallbackEnv, bda);
+    jstring address = bdaddr2newjstr(sCallbackEnv.get(), bda);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClientConnected,
                                  address, connected, conn_id, server_if);
     sCallbackEnv->DeleteLocalRef(address);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgatts_service_added_cb(int status, int server_if,
                               vector<btgatt_db_element_t> service)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     jclass arrayListclazz = sCallbackEnv->FindClass("java/util/ArrayList");
     jobject array = sCallbackEnv->NewObject(arrayListclazz,
         sCallbackEnv->GetMethodID(arrayListclazz, "<init>", "()V"));
-    fillGattDbElementArray(sCallbackEnv, &array, service.data(), service.size());
+    fillGattDbElementArray(sCallbackEnv.get(), &array, service.data(), service.size());
 
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServiceAdded, status,
                                  server_if, array);
     sCallbackEnv->DeleteLocalRef(array);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgatts_service_stopped_cb(int status, int server_if, int srvc_handle)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServiceStopped, status,
                                  server_if, srvc_handle);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgatts_service_deleted_cb(int status, int server_if, int srvc_handle)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServiceDeleted, status,
                                  server_if, srvc_handle);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgatts_request_read_characteristic_cb(int conn_id, int trans_id, bt_bdaddr_t *bda,
                              int attr_handle, int offset, bool is_long)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    jstring address = bdaddr2newjstr(sCallbackEnv, bda);
+    jstring address = bdaddr2newjstr(sCallbackEnv.get(), bda);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServerReadCharacteristic,
                                  address, conn_id, trans_id, attr_handle,
                                  offset, is_long);
     sCallbackEnv->DeleteLocalRef(address);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgatts_request_read_descriptor_cb(int conn_id, int trans_id, bt_bdaddr_t *bda,
                              int attr_handle, int offset, bool is_long)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    jstring address = bdaddr2newjstr(sCallbackEnv, bda);
+    jstring address = bdaddr2newjstr(sCallbackEnv.get(), bda);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServerReadDescriptor,
                                  address, conn_id, trans_id, attr_handle,
                                  offset, is_long);
     sCallbackEnv->DeleteLocalRef(address);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgatts_request_write_characteristic_cb(int conn_id, int trans_id,
@@ -712,9 +702,10 @@
                               int offset, bool need_rsp, bool is_prep,
                               vector<uint8_t> value)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    jstring address = bdaddr2newjstr(sCallbackEnv, bda);
+    jstring address = bdaddr2newjstr(sCallbackEnv.get(), bda);
     jbyteArray val = sCallbackEnv->NewByteArray(value.size());
     if (val) sCallbackEnv->SetByteArrayRegion(val, 0, value.size(), (jbyte*)value.data());
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServerWriteCharacteristic,
@@ -722,7 +713,6 @@
                                  offset, value.size(), need_rsp, is_prep, val);
     sCallbackEnv->DeleteLocalRef(address);
     sCallbackEnv->DeleteLocalRef(val);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgatts_request_write_descriptor_cb(int conn_id, int trans_id,
@@ -730,9 +720,10 @@
                               int offset, bool need_rsp, bool is_prep,
                               vector<uint8_t> value)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    jstring address = bdaddr2newjstr(sCallbackEnv, bda);
+    jstring address = bdaddr2newjstr(sCallbackEnv.get(), bda);
     jbyteArray val = sCallbackEnv->NewByteArray(value.size());
     if (val) sCallbackEnv->SetByteArrayRegion(val, 0, value.size(), (jbyte*)value.data());
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServerWriteDescriptor,
@@ -740,50 +731,49 @@
                                  offset, value.size(), need_rsp, is_prep, val);
     sCallbackEnv->DeleteLocalRef(address);
     sCallbackEnv->DeleteLocalRef(val);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 
 void btgatts_request_exec_write_cb(int conn_id, int trans_id,
                                    bt_bdaddr_t *bda, int exec_write)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
-    jstring address = bdaddr2newjstr(sCallbackEnv, bda);
+    jstring address = bdaddr2newjstr(sCallbackEnv.get(), bda);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onExecuteWrite,
                                  address, conn_id, trans_id, exec_write);
     sCallbackEnv->DeleteLocalRef(address);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgatts_response_confirmation_cb(int status, int handle)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onResponseSendCompleted,
                                  status, handle);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgatts_indication_sent_cb(int conn_id, int status)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNotificationSent,
                                  conn_id, status);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgatts_congestion_cb(int conn_id, bool congested)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServerCongestion, conn_id, congested);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 void btgatts_mtu_changed_cb(int conn_id, int mtu)
 {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServerMtuChanged, conn_id, mtu);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static const btgatt_server_callbacks_t sGattServerCallbacks = {
diff --git a/jni/com_android_bluetooth_hdp.cpp b/jni/com_android_bluetooth_hdp.cpp
index edbbec8..f511439 100644
--- a/jni/com_android_bluetooth_hdp.cpp
+++ b/jni/com_android_bluetooth_hdp.cpp
@@ -18,12 +18,6 @@
 
 #define LOG_NDEBUG 0
 
-#define CHECK_CALLBACK_ENV                                                      \
-   if (!checkCallbackThread()) {                                                \
-       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);\
-       return;                                                                  \
-   }
-
 #include "com_android_bluetooth.h"
 #include "hardware/bt_hl.h"
 #include "utils/Log.h"
@@ -38,25 +32,13 @@
 
 static const bthl_interface_t *sBluetoothHdpInterface = NULL;
 static jobject mCallbacksObj = NULL;
-static JNIEnv *sCallbackEnv = NULL;
-
-static bool checkCallbackThread() {
-    sCallbackEnv = getCallbackEnv();
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (sCallbackEnv != env || sCallbackEnv == NULL) {
-        ALOGE("Callback env check fail: env: %p, callback: %p", env, sCallbackEnv);
-        return false;
-    }
-    return true;
-}
 
 // Define callback functions
 static void app_registration_state_callback(int app_id, bthl_app_reg_state_t state) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAppRegistrationState, app_id,
                                  (jint) state);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static void channel_state_callback(int app_id, bt_bdaddr_t *bd_addr, int mdep_cfg_index,
@@ -64,17 +46,17 @@
     jbyteArray addr;
     jobject fileDescriptor = NULL;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for channel state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     // TODO(BT) check if fd is only valid for BTHH_CONN_STATE_CONNECTED state
     if (state == BTHL_CONN_STATE_CONNECTED) {
-        fileDescriptor = jniCreateFileDescriptor(sCallbackEnv, fd);
+        fileDescriptor = jniCreateFileDescriptor(sCallbackEnv.get(), fd);
         if (!fileDescriptor) {
             ALOGE("Failed to convert file descriptor, fd: %d", fd);
             sCallbackEnv->DeleteLocalRef(addr);
@@ -85,7 +67,6 @@
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onChannelStateChanged, app_id, addr,
                                  mdep_cfg_index, channel_id, (jint) state, fileDescriptor);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
diff --git a/jni/com_android_bluetooth_hfp.cpp b/jni/com_android_bluetooth_hfp.cpp
index 3b6c2ce..4a7ac52 100644
--- a/jni/com_android_bluetooth_hfp.cpp
+++ b/jni/com_android_bluetooth_hfp.cpp
@@ -18,12 +18,6 @@
 
 #define LOG_NDEBUG 0
 
-#define CHECK_CALLBACK_ENV                                                      \
-   if (!checkCallbackThread()) {                                                \
-       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);\
-       return;                                                                  \
-   }
-
 #include "com_android_bluetooth.h"
 #include "hardware/bt_hf.h"
 #include "utils/Log.h"
@@ -55,28 +49,16 @@
 
 static const bthf_interface_t *sBluetoothHfpInterface = NULL;
 static jobject mCallbacksObj = NULL;
-static JNIEnv *sCallbackEnv = NULL;
-
-static bool checkCallbackThread() {
-    // Always fetch the latest callbackEnv from AdapterService.
-    // Caching this could cause this sCallbackEnv to go out-of-sync
-    // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event
-    // is received
-    //if (sCallbackEnv == NULL) {
-    sCallbackEnv = getCallbackEnv();
-    //}
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (sCallbackEnv != env || sCallbackEnv == NULL) return false;
-    return true;
-}
 
 static jbyteArray marshall_bda(bt_bdaddr_t* bd_addr)
 {
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return NULL;
+
     jbyteArray addr;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return NULL;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
@@ -88,115 +70,109 @@
 
     ALOGI("%s", __FUNCTION__);
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for connection state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged,
                                  (jint) state, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void audio_state_callback(bthf_audio_state_t state, bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint) state, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void voice_recognition_callback(bthf_vr_state_t state, bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVrStateChanged, (jint) state, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void answer_call_callback(bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAnswerCall, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void hangup_call_callback(bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onHangupCall, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void volume_control_callback(bthf_volume_type_t type, int volume, bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeChanged, (jint) type,
                                                   (jint) volume, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void dial_call_callback(char *number, bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
@@ -204,7 +180,6 @@
     jstring js_number = sCallbackEnv->NewStringUTF(number);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onDialCall,
                                  js_number, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(js_number);
     sCallbackEnv->DeleteLocalRef(addr);
 }
@@ -212,144 +187,137 @@
 static void dtmf_cmd_callback(char dtmf, bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     // TBD dtmf has changed from int to char
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSendDtmf, dtmf, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void noice_reduction_callback(bthf_nrec_t nrec, bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNoiceReductionEnable,
                                  nrec == BTHF_NREC_START, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void wbs_callback(bthf_wbs_config_t wbs_config, bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     if ((addr = marshall_bda(bd_addr)) == NULL)
         return;
 
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWBS, wbs_config, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void at_chld_callback(bthf_chld_type_t chld, bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtChld, chld, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void at_cnum_callback(bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtCnum, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void at_cind_callback(bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtCind, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void at_cops_callback(bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtCops, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void at_clcc_callback(bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtClcc, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void unknown_at_callback(char *at_string, bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
@@ -357,7 +325,6 @@
     jstring js_at_string = sCallbackEnv->NewStringUTF(at_string);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onUnknownAt,
                                  js_at_string, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(js_at_string);
     sCallbackEnv->DeleteLocalRef(addr);
 }
@@ -365,22 +332,22 @@
 static void key_pressed_callback(bt_bdaddr_t* bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onKeyPressed, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void at_bind_callback(char *at_string, bt_bdaddr_t *bd_addr) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     jbyteArray addr = marshall_bda(bd_addr);
     if (addr == NULL)
@@ -389,21 +356,20 @@
     jstring js_at_string = sCallbackEnv->NewStringUTF(at_string);
 
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtBind, js_at_string, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 
     sCallbackEnv->DeleteLocalRef(js_at_string);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void at_biev_callback(bthf_hf_ind_type_t ind_id, int ind_value, bt_bdaddr_t *bd_addr) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     jbyteArray addr = marshall_bda(bd_addr);
     if (addr == NULL)
         return;
 
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtBiev, ind_id, (jint)ind_value, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
diff --git a/jni/com_android_bluetooth_hfpclient.cpp b/jni/com_android_bluetooth_hfpclient.cpp
index 333035c..09af35f 100644
--- a/jni/com_android_bluetooth_hfpclient.cpp
+++ b/jni/com_android_bluetooth_hfpclient.cpp
@@ -23,17 +23,10 @@
 #include "utils/Log.h"
 #include "android_runtime/AndroidRuntime.h"
 
-#define CHECK_CALLBACK_ENV                                                      \
-   if (!checkCallbackThread()) {                                                \
-       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);\
-       return;                                                                  \
-   }
-
 namespace android {
 
 static bthf_client_interface_t *sBluetoothHfpClientInterface = NULL;
 static jobject mCallbacksObj = NULL;
-static JNIEnv *sCallbackEnv = NULL;
 
 static jmethodID method_onConnectionStateChanged;
 static jmethodID method_onAudioStateChanged;
@@ -57,137 +50,124 @@
 static jmethodID method_onLastVoiceTagNumber;
 static jmethodID method_onRingIndication;
 
-static bool checkCallbackThread() {
-    // Always fetch the latest callbackEnv from AdapterService.
-    // Caching this could cause this sCallbackEnv to go out-of-sync
-    // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event
-    // is received
-    sCallbackEnv = getCallbackEnv();
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (sCallbackEnv != env || sCallbackEnv == NULL) return false;
-    return true;
-}
-
 static void connection_state_cb(bthf_client_connection_state_t state, unsigned int peer_feat, unsigned int chld_feat, bt_bdaddr_t *bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for connection state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, (jint) state, (jint) peer_feat, (jint) chld_feat, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void audio_state_cb(bthf_client_audio_state_t state, bt_bdaddr_t *bd_addr) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for audio state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint) state, addr);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void vr_cmd_cb(bthf_client_vr_state_t state) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVrStateChanged, (jint) state);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static void network_state_cb (bthf_client_network_state_t state) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNetworkState, (jint) state);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static void network_roaming_cb (bthf_client_service_type_t type) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNetworkRoaming, (jint) type);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static void network_signal_cb (int signal) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNetworkSignal, (jint) signal);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static void battery_level_cb (int level) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onBatteryLevel, (jint) level);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static void current_operator_cb (const char *name) {
     jstring js_name;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     js_name = sCallbackEnv->NewStringUTF(name);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCurrentOperator, js_name);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(js_name);
 }
 
 static void call_cb (bthf_client_call_t call) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCall, (jint) call);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static void callsetup_cb (bthf_client_callsetup_t callsetup) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallSetup, (jint) callsetup);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static void callheld_cb (bthf_client_callheld_t callheld) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallHeld, (jint) callheld);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static void resp_and_hold_cb (bthf_client_resp_and_hold_t resp_and_hold) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRespAndHold, (jint) resp_and_hold);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static void clip_cb (const char *number) {
     jstring js_number;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     js_number = sCallbackEnv->NewStringUTF(number);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClip, js_number);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(js_number);
 }
 
 static void call_waiting_cb (const char *number) {
     jstring js_number;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     js_number = sCallbackEnv->NewStringUTF(number);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallWaiting, js_number);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(js_number);
 }
 
@@ -197,58 +177,58 @@
                                             const char *number) {
     jstring js_number;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     js_number = sCallbackEnv->NewStringUTF(number);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCurrentCalls, index, dir, state, mpty, js_number);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(js_number);
 }
 
 static void volume_change_cb (bthf_client_volume_type_t type, int volume) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeChange, (jint) type, (jint) volume);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static void cmd_complete_cb (bthf_client_cmd_complete_t type, int cme) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCmdResult, (jint) type, (jint) cme);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static void subscriber_info_cb (const char *name, bthf_client_subscriber_service_type_t type) {
     jstring js_name;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     js_name = sCallbackEnv->NewStringUTF(name);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSubscriberInfo, js_name, (jint) type);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(js_name);
 }
 
 static void in_band_ring_cb (bthf_client_in_band_ring_state_t in_band) {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onInBandRing, (jint) in_band);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static void last_voice_tag_number_cb (const char *number) {
     jstring js_number;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     js_number = sCallbackEnv->NewStringUTF(number);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onLastVoiceTagNumber, js_number);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(js_number);
 }
 
 static void ring_indication_cb () {
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRingIndication);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static bthf_client_callbacks_t sBluetoothHfpClientCallbacks = {
diff --git a/jni/com_android_bluetooth_hid.cpp b/jni/com_android_bluetooth_hid.cpp
index 88f73fc..7fd47d7 100644
--- a/jni/com_android_bluetooth_hid.cpp
+++ b/jni/com_android_bluetooth_hid.cpp
@@ -18,12 +18,6 @@
 
 #define LOG_NDEBUG 1
 
-#define CHECK_CALLBACK_ENV                                                      \
-   if (!checkCallbackThread()) {                                                \
-       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);\
-       return;                                                                  \
-   }
-
 #include "com_android_bluetooth.h"
 #include "hardware/bt_hh.h"
 #include "utils/Log.h"
@@ -41,59 +35,41 @@
 
 static const bthh_interface_t *sBluetoothHidInterface = NULL;
 static jobject mCallbacksObj = NULL;
-static JNIEnv *sCallbackEnv = NULL;
-
-static bool checkCallbackThread() {
-
-    // Always fetch the latest callbackEnv from AdapterService.
-    // Caching this could cause this sCallbackEnv to go out-of-sync
-    // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event
-    // is received
-
-    sCallbackEnv = getCallbackEnv();
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (sCallbackEnv != env || sCallbackEnv == NULL) return false;
-    return true;
-}
 
 static void connection_state_callback(bt_bdaddr_t *bd_addr, bthh_connection_state_t state) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for HID channel state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
 
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectStateChanged, addr, (jint) state);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
 static void get_protocol_mode_callback(bt_bdaddr_t *bd_addr, bthh_status_t hh_status,bthh_protocol_mode_t mode) {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     if (hh_status != BTHH_OK) {
         ALOGE("BTHH Status is not OK!");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for get protocal mode callback");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
 
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGetProtocolMode, addr, (jint) mode);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
@@ -101,23 +77,21 @@
     jbyteArray addr;
     jbyteArray data;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     if (hh_status != BTHH_OK) {
         ALOGE("BTHH Status is not OK!");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for get report callback");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
     data = sCallbackEnv->NewByteArray(rpt_size);
     if (!data) {
         ALOGE("Fail to new jbyteArray data for get report callback");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         sCallbackEnv->DeleteLocalRef(addr);
         return;
     }
@@ -126,7 +100,6 @@
     sCallbackEnv->SetByteArrayRegion(data, 0, rpt_size, (jbyte *) rpt_data);
 
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGetReport, addr, data, (jint) rpt_size);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
     sCallbackEnv->DeleteLocalRef(data);
 }
@@ -135,32 +108,30 @@
     ALOGV("call to virtual_unplug_callback");
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for HID channel state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
 
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVirtualUnplug, addr, (jint) hh_status);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 
     /*jbyteArray addr;
     jint status = hh_status;
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for HID report");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
 
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVirtualUnplug, addr, status);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);*/
 }
 
@@ -168,17 +139,16 @@
 {
     jbyteArray addr;
 
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         ALOGE("Fail to new jbyteArray bd addr for handshake callback");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onHandshake, addr, (jint) hh_status);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
diff --git a/jni/com_android_bluetooth_pan.cpp b/jni/com_android_bluetooth_pan.cpp
index 3a2bb8b..6ab097c 100644
--- a/jni/com_android_bluetooth_pan.cpp
+++ b/jni/com_android_bluetooth_pan.cpp
@@ -18,12 +18,6 @@
 
 #define LOG_NDEBUG 0
 
-#define CHECK_CALLBACK_ENV                                                      \
-   if (!checkCallbackThread()) {                                                \
-       error("Callback: '%s' is not called on the correct thread", __FUNCTION__);\
-       return;                                                                  \
-   }
-
 #include "com_android_bluetooth.h"
 #include "hardware/bt_pan.h"
 #include "utils/Log.h"
@@ -46,15 +40,6 @@
 
 static const btpan_interface_t *sPanIf = NULL;
 static jobject mCallbacksObj = NULL;
-static JNIEnv *sCallbackEnv = NULL;
-
-static bool checkCallbackThread() {
-    sCallbackEnv = getCallbackEnv();
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (sCallbackEnv != env || sCallbackEnv == NULL) return false;
-    return true;
-}
 
 static void control_state_callback(btpan_control_state_t state, int local_role, bt_status_t error,
                 const char* ifname) {
@@ -63,7 +48,8 @@
         error("Callbacks Obj is NULL: '%s", __FUNCTION__);
         return;
     }
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     jstring js_ifname = sCallbackEnv->NewStringUTF(ifname);
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onControlStateChanged, (jint)local_role, (jint)state,
                                 (jint)error, js_ifname);
@@ -78,18 +64,17 @@
         error("Callbacks Obj is NULL: '%s", __FUNCTION__);
         return;
     }
-    CHECK_CALLBACK_ENV
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (!addr) {
         error("Fail to new jbyteArray bd addr for PAN channel state");
-        checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
         return;
     }
     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
 
     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectStateChanged, addr, (jint) state,
                                     (jint)error, (jint)local_role, (jint)remote_role);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
     sCallbackEnv->DeleteLocalRef(addr);
 }
 
diff --git a/jni/com_android_bluetooth_sdp.cpp b/jni/com_android_bluetooth_sdp.cpp
index 889ab7b..1dbe957 100644
--- a/jni/com_android_bluetooth_sdp.cpp
+++ b/jni/com_android_bluetooth_sdp.cpp
@@ -44,7 +44,6 @@
 #define UUID_MAX_LENGTH 16
 #define IS_UUID(u1,u2)  !memcmp(u1,u2,UUID_MAX_LENGTH)
 
-
 namespace android {
 static jmethodID method_sdpRecordFoundCallback;
 static jmethodID method_sdpMasRecordFoundCallback;
@@ -64,18 +63,6 @@
 };
 
 static jobject sCallbacksObj = NULL;
-static JNIEnv *sCallbackEnv = NULL;
-
-static bool checkCallbackThread() {
-    sCallbackEnv = getCallbackEnv();
-
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (sCallbackEnv != env || sCallbackEnv == NULL) {
-        ALOGE("Callback env check fail: env: %p, callback: %p", env, sCallbackEnv);
-        return false;
-    }
-    return true;
-}
 
 static void initializeNative(JNIEnv *env, jobject object) {
     const bt_interface_t* btInf;
@@ -175,10 +162,8 @@
     int i = 0;
     bluetooth_sdp_record* record;
 
-    if (!checkCallbackThread()) {
-        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
-        goto clean;
-    }
+    CallbackEnv sCallbackEnv(__func__);
+    if (!sCallbackEnv.valid()) return;
 
     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
     if (addr == NULL) goto clean;
@@ -301,7 +286,6 @@
         sCallbackEnv->DeleteLocalRef(service_name);
     if (addr != NULL) sCallbackEnv->DeleteLocalRef(addr);
     if (uuid != NULL) sCallbackEnv->DeleteLocalRef(uuid);
-    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
 }
 
 static jint sdpCreateMapMasRecordNative(JNIEnv *env, jobject obj, jstring name_str, jint mas_id,