• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "BluetoothQualityReportJni"
18 
19 #include <bluetooth/log.h>
20 #include <jni.h>
21 #include <nativehelper/scoped_local_ref.h>
22 
23 #include <cstdint>
24 #include <cstring>
25 #include <mutex>
26 #include <shared_mutex>
27 #include <vector>
28 
29 #include "com_android_bluetooth.h"
30 #include "hardware/bluetooth.h"
31 #include "hardware/bt_bqr.h"
32 #include "types/raw_address.h"
33 
34 using bluetooth::bqr::BluetoothQualityReportInterface;
35 
36 namespace android {
37 static jmethodID method_bqrDeliver;
38 
39 static BluetoothQualityReportInterface* sBluetoothQualityReportInterface = nullptr;
40 static std::shared_timed_mutex interface_mutex;
41 
42 static jobject mCallbacksObj = nullptr;
43 static std::shared_timed_mutex callbacks_mutex;
44 
45 class BluetoothQualityReportCallbacksImpl : public bluetooth::bqr::BluetoothQualityReportCallbacks {
46 public:
47   ~BluetoothQualityReportCallbacksImpl() = default;
48 
bqr_delivery_callback(const RawAddress bd_addr,uint8_t lmp_ver,uint16_t lmp_subver,uint16_t manufacturer_id,std::vector<uint8_t> bqr_raw_data)49   void bqr_delivery_callback(const RawAddress bd_addr, uint8_t lmp_ver, uint16_t lmp_subver,
50                              uint16_t manufacturer_id, std::vector<uint8_t> bqr_raw_data) override {
51     log::info("");
52     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
53 
54     CallbackEnv sCallbackEnv(__func__);
55     if (!sCallbackEnv.valid()) {
56       return;
57     }
58     if (method_bqrDeliver == NULL) {
59       return;
60     }
61     if (mCallbacksObj == nullptr) {
62       return;
63     }
64 
65     ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(),
66                                     sCallbackEnv->NewByteArray(sizeof(RawAddress)));
67     if (!addr.get()) {
68       log::error("Error while allocation byte array for addr");
69       return;
70     }
71 
72     sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)bd_addr.address);
73 
74     ScopedLocalRef<jbyteArray> raw_data(sCallbackEnv.get(),
75                                         sCallbackEnv->NewByteArray(bqr_raw_data.size()));
76     if (!raw_data.get()) {
77       log::error("Error while allocation byte array for bqr raw data");
78       return;
79     }
80     sCallbackEnv->SetByteArrayRegion(raw_data.get(), 0, bqr_raw_data.size(),
81                                      (jbyte*)bqr_raw_data.data());
82 
83     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_bqrDeliver, addr.get(), (jint)lmp_ver,
84                                  (jint)lmp_subver, (jint)manufacturer_id, raw_data.get());
85   }
86 };
87 
88 static BluetoothQualityReportCallbacksImpl sBluetoothQualityReportCallbacks;
89 
initNative(JNIEnv * env,jobject object)90 static void initNative(JNIEnv* env, jobject object) {
91   std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex);
92   std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex);
93 
94   const bt_interface_t* btInf = getBluetoothInterface();
95   if (btInf == nullptr) {
96     log::error("Bluetooth module is not loaded");
97     return;
98   }
99 
100   if (sBluetoothQualityReportInterface != nullptr) {
101     log::info("Cleaning up BluetoothQualityReport Interface before initializing...");
102     sBluetoothQualityReportInterface = nullptr;
103   }
104 
105   if (mCallbacksObj != nullptr) {
106     log::info("Cleaning up BluetoothQualityReport callback object");
107     env->DeleteGlobalRef(mCallbacksObj);
108     mCallbacksObj = nullptr;
109   }
110 
111   if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) {
112     log::error("Failed to allocate Global Ref for BluetoothQualityReport Callbacks");
113     return;
114   }
115 
116   sBluetoothQualityReportInterface =
117           (BluetoothQualityReportInterface*)btInf->get_profile_interface(BT_BQR_ID);
118   if (sBluetoothQualityReportInterface == nullptr) {
119     log::error("Failed to get BluetoothQualityReport Interface");
120     return;
121   }
122 
123   sBluetoothQualityReportInterface->init(&sBluetoothQualityReportCallbacks);
124 }
125 
cleanupNative(JNIEnv * env,jobject)126 static void cleanupNative(JNIEnv* env, jobject /* object */) {
127   std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex);
128   std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex);
129 
130   const bt_interface_t* btInf = getBluetoothInterface();
131   if (btInf == nullptr) {
132     log::error("Bluetooth module is not loaded");
133     return;
134   }
135 
136   if (sBluetoothQualityReportInterface != nullptr) {
137     sBluetoothQualityReportInterface = nullptr;
138   }
139 
140   if (mCallbacksObj != nullptr) {
141     env->DeleteGlobalRef(mCallbacksObj);
142     mCallbacksObj = nullptr;
143   }
144 }
145 
register_com_android_bluetooth_btservice_BluetoothQualityReport(JNIEnv * env)146 int register_com_android_bluetooth_btservice_BluetoothQualityReport(JNIEnv* env) {
147   const JNINativeMethod methods[] = {
148           {"initNative", "()V", (void*)initNative},
149           {"cleanupNative", "()V", (void*)cleanupNative},
150   };
151   const int result = REGISTER_NATIVE_METHODS(
152           env, "com/android/bluetooth/btservice/BluetoothQualityReportNativeInterface", methods);
153   if (result != 0) {
154     return result;
155   }
156 
157   const JNIJavaMethod javaMethods[] = {
158           {"bqrDeliver", "([BIII[B)V", &method_bqrDeliver},
159   };
160   GET_JAVA_METHODS(env, "com/android/bluetooth/btservice/BluetoothQualityReportNativeInterface",
161                    javaMethods);
162 
163   return 0;
164 }
165 }  // namespace android
166