Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a7c7e825 authored by William Escande's avatar William Escande
Browse files

Add synchronization for JNI object

Cleanup can put the callback object to NULL but a subsequent event can
still try to call JNI on it.
Adding check on the jni object + adding mutex to avoid multi-thread
issue

Bug: 281808930
Test: JNI is untested
Change-Id: I45919927b3cf6d5b7ab72e30040bb16492491b25
parent 0e41093c
Loading
Loading
Loading
Loading
+122 −1
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@
#include <sys/prctl.h>
#include <sys/stat.h>

#include <mutex>
#include <shared_mutex>

#include "com_android_bluetooth.h"
#include "hardware/bt_sock.h"
@@ -98,6 +98,7 @@ static bool sHaveCallbackThread;

static jobject sJniAdapterServiceObj;
static jobject sJniCallbacksObj;
static std::shared_timed_mutex jniObjMutex;
static jfieldID sJniCallbacksField;

const bt_interface_t* getBluetoothInterface() { return sBluetoothInterface; }
@@ -109,6 +110,12 @@ bool isCallbackThread() {
}

static void adapter_state_change_callback(bt_state_t status) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;
  ALOGV("%s: Status is: %d", __func__, status);
@@ -137,6 +144,12 @@ static int get_properties(int num_properties, bt_property_t* properties,

static void adapter_properties_callback(bt_status_t status, int num_properties,
                                        bt_property_t* properties) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

@@ -191,6 +204,12 @@ static void remote_device_properties_callback(bt_status_t status,
                                              RawAddress* bd_addr,
                                              int num_properties,
                                              bt_property_t* properties) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

@@ -253,6 +272,12 @@ static void remote_device_properties_callback(bt_status_t status,

static void device_found_callback(int num_properties,
                                  bt_property_t* properties) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

@@ -289,6 +314,12 @@ static void device_found_callback(int num_properties,
static void bond_state_changed_callback(bt_status_t status, RawAddress* bd_addr,
                                        bt_bond_state_t state,
                                        int fail_reason) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

@@ -313,6 +344,12 @@ static void bond_state_changed_callback(bt_status_t status, RawAddress* bd_addr,

static void address_consolidate_callback(RawAddress* main_bd_addr,
                                         RawAddress* secondary_bd_addr) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);

  ScopedLocalRef<jbyteArray> main_addr(
@@ -341,6 +378,12 @@ static void address_consolidate_callback(RawAddress* main_bd_addr,

static void le_address_associate_callback(RawAddress* main_bd_addr,
                                          RawAddress* secondary_bd_addr) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);

  ScopedLocalRef<jbyteArray> main_addr(
@@ -378,6 +421,12 @@ static void acl_state_changed_callback(bt_status_t status, RawAddress* bd_addr,
    return;
  }

  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

@@ -397,6 +446,12 @@ static void acl_state_changed_callback(bt_status_t status, RawAddress* bd_addr,
}

static void discovery_state_changed_callback(bt_discovery_state_t state) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

@@ -413,6 +468,12 @@ static void pin_request_callback(RawAddress* bd_addr, bt_bdname_t* bdname,
    return;
  }

  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

@@ -447,6 +508,13 @@ static void ssp_request_callback(RawAddress* bd_addr, bt_bdname_t* bdname,
    ALOGE("Address is null in %s", __func__);
    return;
  }

  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

@@ -593,6 +661,13 @@ static jobject createLeOobDataObject(JNIEnv* env, bt_oob_data_t oob_data) {
static void generate_local_oob_data_callback(tBT_TRANSPORT transport,
                                             bt_oob_data_t oob_data) {
  ALOGV("%s", __func__);

  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

@@ -623,6 +698,12 @@ static void link_quality_report_callback(
    uint64_t timestamp, int report_id, int rssi, int snr,
    int retransmission_count, int packets_not_receive_count,
    int negative_acknowledgement_count) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

@@ -638,6 +719,12 @@ static void link_quality_report_callback(
}

static void switch_buffer_size_callback(bool is_low_latency_buffer_size) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

@@ -650,6 +737,12 @@ static void switch_buffer_size_callback(bool is_low_latency_buffer_size) {
}

static void switch_codec_callback(bool is_low_latency_buffer_size) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniCallbacksObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

@@ -687,6 +780,12 @@ static void callback_thread_event(bt_cb_thread_evt event) {

static void energy_info_recv_callback(bt_activity_energy_info* p_energy_info,
                                      bt_uid_traffic_t* uid_data) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniAdapterServiceObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return;
  }

  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

@@ -789,6 +888,12 @@ class JNIThreadAttacher {

static bool set_wake_alarm_callout(uint64_t delay_millis, bool should_wake,
                                   alarm_cb cb, void* data) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniAdapterServiceObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return false;
  }

  JNIThreadAttacher attacher(vm);
  JNIEnv* env = attacher.getEnv();

@@ -813,6 +918,12 @@ static bool set_wake_alarm_callout(uint64_t delay_millis, bool should_wake,
}

static int acquire_wake_lock_callout(const char* lock_name) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniAdapterServiceObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return BT_STATUS_NOT_READY;
  }

  JNIThreadAttacher attacher(vm);
  JNIEnv* env = attacher.getEnv();

@@ -838,6 +949,12 @@ static int acquire_wake_lock_callout(const char* lock_name) {
}

static int release_wake_lock_callout(const char* lock_name) {
  std::shared_lock<std::shared_timed_mutex> lock(jniObjMutex);
  if (!sJniAdapterServiceObj) {
    ALOGE("%s, JNI obj is null. Failed to call JNI callback", __func__);
    return BT_STATUS_NOT_READY;
  }

  JNIThreadAttacher attacher(vm);
  JNIEnv* env = attacher.getEnv();

@@ -987,6 +1104,8 @@ static bool initNative(JNIEnv* env, jobject obj, jboolean isGuest,
                       jboolean isCommonCriteriaMode, int configCompareResult,
                       jobjectArray initFlags, jboolean isAtvDevice,
                       jstring userDataDirectory) {
  std::unique_lock<std::shared_timed_mutex> lock(jniObjMutex);

  ALOGV("%s", __func__);

  android_bluetooth_UidTraffic.clazz =
@@ -1054,6 +1173,8 @@ static bool initNative(JNIEnv* env, jobject obj, jboolean isGuest,
}

static bool cleanupNative(JNIEnv* env, jobject obj) {
  std::unique_lock<std::shared_timed_mutex> lock(jniObjMutex);

  ALOGV("%s", __func__);

  if (!sBluetoothInterface) return JNI_FALSE;