• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*   Copyright 2019 HIMSA II K/S - www.himsa.com
2  * Represented by EHIMA - www.ehima.com
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 "BluetoothLeAudioServiceJni"
18 
19 #include <hardware/bluetooth.h>
20 
21 #include <array>
22 #include <optional>
23 #include <shared_mutex>
24 
25 #include "com_android_bluetooth.h"
26 #include "hardware/bt_le_audio.h"
27 
28 using bluetooth::le_audio::BroadcastId;
29 using bluetooth::le_audio::BroadcastState;
30 using bluetooth::le_audio::btle_audio_codec_config_t;
31 using bluetooth::le_audio::btle_audio_codec_index_t;
32 using bluetooth::le_audio::ConnectionState;
33 using bluetooth::le_audio::GroupNodeStatus;
34 using bluetooth::le_audio::GroupStatus;
35 using bluetooth::le_audio::LeAudioBroadcasterCallbacks;
36 using bluetooth::le_audio::LeAudioBroadcasterInterface;
37 using bluetooth::le_audio::LeAudioClientCallbacks;
38 using bluetooth::le_audio::LeAudioClientInterface;
39 
40 namespace android {
41 static jmethodID method_onInitialized;
42 static jmethodID method_onConnectionStateChanged;
43 static jmethodID method_onGroupStatus;
44 static jmethodID method_onGroupNodeStatus;
45 static jmethodID method_onAudioConf;
46 static jmethodID method_onSinkAudioLocationAvailable;
47 static jmethodID method_onAudioLocalCodecCapabilities;
48 static jmethodID method_onAudioGroupCodecConf;
49 
50 static struct {
51   jclass clazz;
52   jmethodID constructor;
53   jmethodID getCodecType;
54 } android_bluetooth_BluetoothLeAudioCodecConfig;
55 
56 static struct {
57   jclass clazz;
58   jmethodID constructor;
59 } android_bluetooth_BluetoothLeAudioCodecConfigMetadata;
60 
61 static struct {
62   jclass clazz;
63   jmethodID constructor;
64   jmethodID add;
65 } java_util_ArrayList;
66 
67 static struct {
68   jclass clazz;
69   jmethodID constructor;
70 } android_bluetooth_BluetoothLeBroadcastChannel;
71 
72 static struct {
73   jclass clazz;
74   jmethodID constructor;
75 } android_bluetooth_BluetoothLeBroadcastSubgroup;
76 
77 static struct {
78   jclass clazz;
79   jmethodID constructor;
80 } android_bluetooth_BluetoothLeAudioContentMetadata;
81 
82 static struct {
83   jclass clazz;
84   jmethodID constructor;
85 } android_bluetooth_BluetoothLeBroadcastMetadata;
86 
87 static struct {
88   jclass clazz;
89   jmethodID constructor;
90 } android_bluetooth_BluetoothDevice;
91 
92 static LeAudioClientInterface* sLeAudioClientInterface = nullptr;
93 static std::shared_timed_mutex interface_mutex;
94 
95 static jobject mCallbacksObj = nullptr;
96 static std::shared_timed_mutex callbacks_mutex;
97 
prepareCodecConfigObj(JNIEnv * env,btle_audio_codec_config_t codecConfig)98 jobject prepareCodecConfigObj(JNIEnv* env,
99                               btle_audio_codec_config_t codecConfig) {
100   jobject codecConfigObj =
101       env->NewObject(android_bluetooth_BluetoothLeAudioCodecConfig.clazz,
102                      android_bluetooth_BluetoothLeAudioCodecConfig.constructor,
103                      (jint)codecConfig.codec_type, 0, 0, 0, 0, 0, 0, 0, 0);
104   return codecConfigObj;
105 }
106 
prepareArrayOfCodecConfigs(JNIEnv * env,std::vector<btle_audio_codec_config_t> codecConfigs)107 jobjectArray prepareArrayOfCodecConfigs(
108     JNIEnv* env, std::vector<btle_audio_codec_config_t> codecConfigs) {
109   jsize i = 0;
110   jobjectArray CodecConfigArray = env->NewObjectArray(
111       (jsize)codecConfigs.size(),
112       android_bluetooth_BluetoothLeAudioCodecConfig.clazz, nullptr);
113 
114   for (auto const& cap : codecConfigs) {
115     jobject Obj = prepareCodecConfigObj(env, cap);
116 
117     env->SetObjectArrayElement(CodecConfigArray, i++, Obj);
118     env->DeleteLocalRef(Obj);
119   }
120 
121   return CodecConfigArray;
122 }
123 
124 class LeAudioClientCallbacksImpl : public LeAudioClientCallbacks {
125  public:
126   ~LeAudioClientCallbacksImpl() = default;
127 
OnInitialized(void)128   void OnInitialized(void) override {
129     LOG(INFO) << __func__;
130     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
131     CallbackEnv sCallbackEnv(__func__);
132     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;
133     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onInitialized);
134   }
135 
OnConnectionState(ConnectionState state,const RawAddress & bd_addr)136   void OnConnectionState(ConnectionState state,
137                          const RawAddress& bd_addr) override {
138     LOG(INFO) << __func__ << ", state:" << int(state);
139 
140     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
141     CallbackEnv sCallbackEnv(__func__);
142     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;
143 
144     ScopedLocalRef<jbyteArray> addr(
145         sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
146     if (!addr.get()) {
147       LOG(ERROR) << "Failed to new jbyteArray bd addr for connection state";
148       return;
149     }
150 
151     sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
152                                      (jbyte*)&bd_addr);
153     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged,
154                                  (jint)state, addr.get());
155   }
156 
OnGroupStatus(int group_id,GroupStatus group_status)157   void OnGroupStatus(int group_id, GroupStatus group_status) override {
158     LOG(INFO) << __func__;
159 
160     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
161     CallbackEnv sCallbackEnv(__func__);
162     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;
163 
164     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGroupStatus,
165                                  (jint)group_id, (jint)group_status);
166   }
167 
OnGroupNodeStatus(const RawAddress & bd_addr,int group_id,GroupNodeStatus node_status)168   void OnGroupNodeStatus(const RawAddress& bd_addr, int group_id,
169                          GroupNodeStatus node_status) override {
170     LOG(INFO) << __func__;
171 
172     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
173     CallbackEnv sCallbackEnv(__func__);
174     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;
175 
176     ScopedLocalRef<jbyteArray> addr(
177         sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
178     if (!addr.get()) {
179       LOG(ERROR) << "Failed to new jbyteArray bd addr for group status";
180       return;
181     }
182 
183     sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
184                                      (jbyte*)&bd_addr);
185     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGroupNodeStatus,
186                                  addr.get(), (jint)group_id, (jint)node_status);
187   }
188 
OnAudioConf(uint8_t direction,int group_id,uint32_t sink_audio_location,uint32_t source_audio_location,uint16_t avail_cont)189   void OnAudioConf(uint8_t direction, int group_id,
190                    uint32_t sink_audio_location, uint32_t source_audio_location,
191                    uint16_t avail_cont) override {
192     LOG(INFO) << __func__;
193 
194     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
195     CallbackEnv sCallbackEnv(__func__);
196     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;
197 
198     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioConf,
199                                  (jint)direction, (jint)group_id,
200                                  (jint)sink_audio_location,
201                                  (jint)source_audio_location, (jint)avail_cont);
202   }
203 
OnSinkAudioLocationAvailable(const RawAddress & bd_addr,uint32_t sink_audio_location)204   void OnSinkAudioLocationAvailable(const RawAddress& bd_addr,
205                                     uint32_t sink_audio_location) override {
206     LOG(INFO) << __func__;
207 
208     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
209     CallbackEnv sCallbackEnv(__func__);
210     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;
211 
212     ScopedLocalRef<jbyteArray> addr(
213         sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
214     if (!addr.get()) {
215       LOG(ERROR) << "Failed to new jbyteArray bd addr for group status";
216       return;
217     }
218 
219     sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
220                                      (jbyte*)&bd_addr);
221     sCallbackEnv->CallVoidMethod(mCallbacksObj,
222                                  method_onSinkAudioLocationAvailable,
223                                  addr.get(), (jint)sink_audio_location);
224   }
225 
OnAudioLocalCodecCapabilities(std::vector<btle_audio_codec_config_t> local_input_capa_codec_conf,std::vector<btle_audio_codec_config_t> local_output_capa_codec_conf)226   void OnAudioLocalCodecCapabilities(
227       std::vector<btle_audio_codec_config_t> local_input_capa_codec_conf,
228       std::vector<btle_audio_codec_config_t> local_output_capa_codec_conf)
229       override {
230     LOG(INFO) << __func__;
231 
232     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
233     CallbackEnv sCallbackEnv(__func__);
234     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;
235 
236     jobject localInputCapCodecConfigArray = prepareArrayOfCodecConfigs(
237         sCallbackEnv.get(), local_input_capa_codec_conf);
238 
239     jobject localOutputCapCodecConfigArray = prepareArrayOfCodecConfigs(
240         sCallbackEnv.get(), local_output_capa_codec_conf);
241 
242     sCallbackEnv->CallVoidMethod(
243         mCallbacksObj, method_onAudioLocalCodecCapabilities,
244         localInputCapCodecConfigArray, localOutputCapCodecConfigArray);
245   }
246 
OnAudioGroupCodecConf(int group_id,btle_audio_codec_config_t input_codec_conf,btle_audio_codec_config_t output_codec_conf,std::vector<btle_audio_codec_config_t> input_selectable_codec_conf,std::vector<btle_audio_codec_config_t> output_selectable_codec_conf)247   void OnAudioGroupCodecConf(
248       int group_id, btle_audio_codec_config_t input_codec_conf,
249       btle_audio_codec_config_t output_codec_conf,
250       std::vector<btle_audio_codec_config_t> input_selectable_codec_conf,
251       std::vector<btle_audio_codec_config_t> output_selectable_codec_conf)
252       override {
253     LOG(INFO) << __func__;
254 
255     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
256     CallbackEnv sCallbackEnv(__func__);
257     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return;
258 
259     jobject inputCodecConfigObj =
260         prepareCodecConfigObj(sCallbackEnv.get(), input_codec_conf);
261     jobject outputCodecConfigObj =
262         prepareCodecConfigObj(sCallbackEnv.get(), input_codec_conf);
263     jobject inputSelectableCodecConfigArray = prepareArrayOfCodecConfigs(
264         sCallbackEnv.get(), input_selectable_codec_conf);
265     jobject outputSelectableCodecConfigArray = prepareArrayOfCodecConfigs(
266         sCallbackEnv.get(), output_selectable_codec_conf);
267 
268     sCallbackEnv->CallVoidMethod(
269         mCallbacksObj, method_onAudioGroupCodecConf, (jint)group_id,
270         inputCodecConfigObj, outputCodecConfigObj,
271         inputSelectableCodecConfigArray, outputSelectableCodecConfigArray);
272   }
273 };
274 
275 static LeAudioClientCallbacksImpl sLeAudioClientCallbacks;
276 
classInitNative(JNIEnv * env,jclass clazz)277 static void classInitNative(JNIEnv* env, jclass clazz) {
278   jclass jniBluetoothLeAudioCodecConfigClass =
279       env->FindClass("android/bluetooth/BluetoothLeAudioCodecConfig");
280   android_bluetooth_BluetoothLeAudioCodecConfig.constructor = env->GetMethodID(
281       jniBluetoothLeAudioCodecConfigClass, "<init>", "(IIIIIIIII)V");
282   android_bluetooth_BluetoothLeAudioCodecConfig.getCodecType = env->GetMethodID(
283       jniBluetoothLeAudioCodecConfigClass, "getCodecType", "()I");
284 
285   method_onGroupStatus = env->GetMethodID(clazz, "onGroupStatus", "(II)V");
286   method_onGroupNodeStatus =
287       env->GetMethodID(clazz, "onGroupNodeStatus", "([BII)V");
288   method_onAudioConf = env->GetMethodID(clazz, "onAudioConf", "(IIIII)V");
289   method_onSinkAudioLocationAvailable =
290       env->GetMethodID(clazz, "onSinkAudioLocationAvailable", "([BI)V");
291   method_onInitialized = env->GetMethodID(clazz, "onInitialized", "()V");
292   method_onConnectionStateChanged =
293       env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V");
294   method_onAudioLocalCodecCapabilities =
295       env->GetMethodID(clazz, "onAudioLocalCodecCapabilities",
296                        "([Landroid/bluetooth/BluetoothLeAudioCodecConfig;"
297                        "[Landroid/bluetooth/BluetoothLeAudioCodecConfig;)V");
298   method_onAudioGroupCodecConf =
299       env->GetMethodID(clazz, "onAudioGroupCodecConf",
300                        "(ILandroid/bluetooth/BluetoothLeAudioCodecConfig;"
301                        "Landroid/bluetooth/BluetoothLeAudioCodecConfig;"
302                        "[Landroid/bluetooth/BluetoothLeAudioCodecConfig;"
303                        "[Landroid/bluetooth/BluetoothLeAudioCodecConfig;)V");
304 }
305 
prepareCodecPreferences(JNIEnv * env,jobject object,jobjectArray codecConfigArray)306 std::vector<btle_audio_codec_config_t> prepareCodecPreferences(
307     JNIEnv* env, jobject object, jobjectArray codecConfigArray) {
308   std::vector<btle_audio_codec_config_t> codec_preferences;
309 
310   int numConfigs = env->GetArrayLength(codecConfigArray);
311   for (int i = 0; i < numConfigs; i++) {
312     jobject jcodecConfig = env->GetObjectArrayElement(codecConfigArray, i);
313     if (jcodecConfig == nullptr) continue;
314     if (!env->IsInstanceOf(
315             jcodecConfig,
316             android_bluetooth_BluetoothLeAudioCodecConfig.clazz)) {
317       ALOGE("%s: Invalid BluetoothLeAudioCodecConfig instance", __func__);
318       continue;
319     }
320     jint codecType = env->CallIntMethod(
321         jcodecConfig,
322         android_bluetooth_BluetoothLeAudioCodecConfig.getCodecType);
323 
324     btle_audio_codec_config_t codec_config = {
325         .codec_type = static_cast<btle_audio_codec_index_t>(codecType)};
326 
327     codec_preferences.push_back(codec_config);
328   }
329   return codec_preferences;
330 }
331 
initNative(JNIEnv * env,jobject object,jobjectArray codecOffloadingArray)332 static void initNative(JNIEnv* env, jobject object,
333                        jobjectArray codecOffloadingArray) {
334   std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex);
335   std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex);
336 
337   const bt_interface_t* btInf = getBluetoothInterface();
338   if (btInf == nullptr) {
339     LOG(ERROR) << "Bluetooth module is not loaded";
340     return;
341   }
342 
343   if (mCallbacksObj != nullptr) {
344     LOG(INFO) << "Cleaning up LeAudio callback object";
345     env->DeleteGlobalRef(mCallbacksObj);
346     mCallbacksObj = nullptr;
347   }
348 
349   if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) {
350     LOG(ERROR) << "Failed to allocate Global Ref for LeAudio Callbacks";
351     return;
352   }
353 
354   android_bluetooth_BluetoothLeAudioCodecConfig.clazz =
355       (jclass)env->NewGlobalRef(
356           env->FindClass("android/bluetooth/BluetoothLeAudioCodecConfig"));
357   if (android_bluetooth_BluetoothLeAudioCodecConfig.clazz == nullptr) {
358     LOG(ERROR) << "Failed to allocate Global Ref for "
359                   "BluetoothLeAudioCodecConfig class";
360     return;
361   }
362 
363   sLeAudioClientInterface =
364       (LeAudioClientInterface*)btInf->get_profile_interface(
365           BT_PROFILE_LE_AUDIO_ID);
366   if (sLeAudioClientInterface == nullptr) {
367     LOG(ERROR) << "Failed to get Bluetooth LeAudio Interface";
368     return;
369   }
370 
371   std::vector<btle_audio_codec_config_t> codec_offloading =
372       prepareCodecPreferences(env, object, codecOffloadingArray);
373 
374   sLeAudioClientInterface->Initialize(&sLeAudioClientCallbacks,
375                                       codec_offloading);
376 }
377 
cleanupNative(JNIEnv * env,jobject object)378 static void cleanupNative(JNIEnv* env, jobject object) {
379   std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex);
380   std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex);
381 
382   const bt_interface_t* btInf = getBluetoothInterface();
383   if (btInf == nullptr) {
384     LOG(ERROR) << "Bluetooth module is not loaded";
385     return;
386   }
387 
388   if (sLeAudioClientInterface != nullptr) {
389     sLeAudioClientInterface->Cleanup();
390     sLeAudioClientInterface = nullptr;
391   }
392 
393   env->DeleteGlobalRef(android_bluetooth_BluetoothLeAudioCodecConfig.clazz);
394   android_bluetooth_BluetoothLeAudioCodecConfig.clazz = nullptr;
395 
396   if (mCallbacksObj != nullptr) {
397     env->DeleteGlobalRef(mCallbacksObj);
398     mCallbacksObj = nullptr;
399   }
400 }
401 
connectLeAudioNative(JNIEnv * env,jobject object,jbyteArray address)402 static jboolean connectLeAudioNative(JNIEnv* env, jobject object,
403                                      jbyteArray address) {
404   LOG(INFO) << __func__;
405   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
406   if (!sLeAudioClientInterface) return JNI_FALSE;
407 
408   jbyte* addr = env->GetByteArrayElements(address, nullptr);
409   if (!addr) {
410     jniThrowIOException(env, EINVAL);
411     return JNI_FALSE;
412   }
413 
414   RawAddress* tmpraw = (RawAddress*)addr;
415   sLeAudioClientInterface->Connect(*tmpraw);
416   env->ReleaseByteArrayElements(address, addr, 0);
417   return JNI_TRUE;
418 }
419 
disconnectLeAudioNative(JNIEnv * env,jobject object,jbyteArray address)420 static jboolean disconnectLeAudioNative(JNIEnv* env, jobject object,
421                                         jbyteArray address) {
422   LOG(INFO) << __func__;
423   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
424   if (!sLeAudioClientInterface) return JNI_FALSE;
425 
426   jbyte* addr = env->GetByteArrayElements(address, nullptr);
427   if (!addr) {
428     jniThrowIOException(env, EINVAL);
429     return JNI_FALSE;
430   }
431 
432   RawAddress* tmpraw = (RawAddress*)addr;
433   sLeAudioClientInterface->Disconnect(*tmpraw);
434   env->ReleaseByteArrayElements(address, addr, 0);
435   return JNI_TRUE;
436 }
437 
groupAddNodeNative(JNIEnv * env,jobject object,jint group_id,jbyteArray address)438 static jboolean groupAddNodeNative(JNIEnv* env, jobject object, jint group_id,
439                                    jbyteArray address) {
440   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
441   jbyte* addr = env->GetByteArrayElements(address, nullptr);
442 
443   if (!sLeAudioClientInterface) {
444     LOG(ERROR) << __func__ << ": Failed to get the Bluetooth LeAudio Interface";
445     return JNI_FALSE;
446   }
447 
448   if (!addr) {
449     jniThrowIOException(env, EINVAL);
450     return JNI_FALSE;
451   }
452 
453   RawAddress* tmpraw = (RawAddress*)addr;
454   sLeAudioClientInterface->GroupAddNode(group_id, *tmpraw);
455   env->ReleaseByteArrayElements(address, addr, 0);
456 
457   return JNI_TRUE;
458 }
459 
groupRemoveNodeNative(JNIEnv * env,jobject object,jint group_id,jbyteArray address)460 static jboolean groupRemoveNodeNative(JNIEnv* env, jobject object,
461                                       jint group_id, jbyteArray address) {
462   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
463   if (!sLeAudioClientInterface) {
464     LOG(ERROR) << __func__ << ": Failed to get the Bluetooth LeAudio Interface";
465     return JNI_FALSE;
466   }
467 
468   jbyte* addr = env->GetByteArrayElements(address, nullptr);
469   if (!addr) {
470     jniThrowIOException(env, EINVAL);
471     return JNI_FALSE;
472   }
473 
474   RawAddress* tmpraw = (RawAddress*)addr;
475   sLeAudioClientInterface->GroupRemoveNode(group_id, *tmpraw);
476   env->ReleaseByteArrayElements(address, addr, 0);
477   return JNI_TRUE;
478 }
479 
groupSetActiveNative(JNIEnv * env,jobject object,jint group_id)480 static void groupSetActiveNative(JNIEnv* env, jobject object, jint group_id) {
481   LOG(INFO) << __func__;
482   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
483 
484   if (!sLeAudioClientInterface) {
485     LOG(ERROR) << __func__ << ": Failed to get the Bluetooth LeAudio Interface";
486     return;
487   }
488 
489   sLeAudioClientInterface->GroupSetActive(group_id);
490 }
491 
setCodecConfigPreferenceNative(JNIEnv * env,jobject object,jint group_id,jobject inputCodecConfig,jobject outputCodecConfig)492 static void setCodecConfigPreferenceNative(JNIEnv* env, jobject object,
493                                            jint group_id,
494                                            jobject inputCodecConfig,
495                                            jobject outputCodecConfig) {
496   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
497 
498   if (!env->IsInstanceOf(inputCodecConfig,
499                          android_bluetooth_BluetoothLeAudioCodecConfig.clazz) ||
500       !env->IsInstanceOf(outputCodecConfig,
501                          android_bluetooth_BluetoothLeAudioCodecConfig.clazz)) {
502     ALOGE("%s: Invalid BluetoothLeAudioCodecConfig instance", __func__);
503     return;
504   }
505 
506   jint inputCodecType = env->CallIntMethod(
507       inputCodecConfig,
508       android_bluetooth_BluetoothLeAudioCodecConfig.getCodecType);
509 
510   btle_audio_codec_config_t input_codec_config = {
511       .codec_type = static_cast<btle_audio_codec_index_t>(inputCodecType)};
512 
513   jint outputCodecType = env->CallIntMethod(
514       outputCodecConfig,
515       android_bluetooth_BluetoothLeAudioCodecConfig.getCodecType);
516 
517   btle_audio_codec_config_t output_codec_config = {
518       .codec_type = static_cast<btle_audio_codec_index_t>(outputCodecType)};
519 
520   sLeAudioClientInterface->SetCodecConfigPreference(
521       group_id, input_codec_config, output_codec_config);
522 }
523 
setCcidInformationNative(JNIEnv * env,jobject object,jint ccid,jint contextType)524 static void setCcidInformationNative(JNIEnv* env, jobject object, jint ccid,
525                                      jint contextType) {
526   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
527   if (!sLeAudioClientInterface) {
528     LOG(ERROR) << __func__ << ": Failed to get the Bluetooth LeAudio Interface";
529     return;
530   }
531 
532   sLeAudioClientInterface->SetCcidInformation(ccid, contextType);
533 }
534 
setInCallNative(JNIEnv * env,jobject object,jboolean inCall)535 static void setInCallNative(JNIEnv* env, jobject object, jboolean inCall) {
536   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
537   if (!sLeAudioClientInterface) {
538     LOG(ERROR) << __func__ << ": Failed to get the Bluetooth LeAudio Interface";
539     return;
540   }
541 
542   sLeAudioClientInterface->SetInCall(inCall);
543 }
544 
545 static JNINativeMethod sMethods[] = {
546     {"classInitNative", "()V", (void*)classInitNative},
547     {"initNative", "([Landroid/bluetooth/BluetoothLeAudioCodecConfig;)V",
548      (void*)initNative},
549     {"cleanupNative", "()V", (void*)cleanupNative},
550     {"connectLeAudioNative", "([B)Z", (void*)connectLeAudioNative},
551     {"disconnectLeAudioNative", "([B)Z", (void*)disconnectLeAudioNative},
552     {"groupAddNodeNative", "(I[B)Z", (void*)groupAddNodeNative},
553     {"groupRemoveNodeNative", "(I[B)Z", (void*)groupRemoveNodeNative},
554     {"groupSetActiveNative", "(I)V", (void*)groupSetActiveNative},
555     {"setCodecConfigPreferenceNative",
556      "(ILandroid/bluetooth/BluetoothLeAudioCodecConfig;Landroid/bluetooth/"
557      "BluetoothLeAudioCodecConfig;)V",
558      (void*)setCodecConfigPreferenceNative},
559     {"setCcidInformationNative", "(II)V", (void*)setCcidInformationNative},
560     {"setInCallNative", "(Z)V", (void*)setInCallNative},
561 };
562 
563 /* Le Audio Broadcaster */
564 static jmethodID method_onBroadcastCreated;
565 static jmethodID method_onBroadcastDestroyed;
566 static jmethodID method_onBroadcastStateChanged;
567 static jmethodID method_onBroadcastMetadataChanged;
568 
569 static LeAudioBroadcasterInterface* sLeAudioBroadcasterInterface = nullptr;
570 static std::shared_timed_mutex sBroadcasterInterfaceMutex;
571 
572 static jobject sBroadcasterCallbacksObj = nullptr;
573 static std::shared_timed_mutex sBroadcasterCallbacksMutex;
574 
575 #define VEC_UINT8_TO_UINT32(vec)                                          \
576   ((vec.data()[3] << 24) + (vec.data()[2] << 16) + (vec.data()[1] << 8) + \
577    vec.data()[0])
578 
RawPacketSize(const std::map<uint8_t,std::vector<uint8_t>> & values)579 size_t RawPacketSize(const std::map<uint8_t, std::vector<uint8_t>>& values) {
580   size_t bytes = 0;
581   for (auto const& value : values) {
582     bytes += (/* ltv_len + ltv_type */ 2 + value.second.size());
583   }
584   return bytes;
585 }
586 
prepareRawLtvArray(JNIEnv * env,const std::map<uint8_t,std::vector<uint8_t>> & metadata)587 jbyteArray prepareRawLtvArray(
588     JNIEnv* env, const std::map<uint8_t, std::vector<uint8_t>>& metadata) {
589   auto raw_meta_size = RawPacketSize(metadata);
590 
591   jbyteArray raw_metadata = env->NewByteArray(raw_meta_size);
592   if (!raw_metadata) {
593     LOG(ERROR) << "Failed to create new jbyteArray for raw LTV";
594     return nullptr;
595   }
596 
597   jsize offset = 0;
598   for (auto const& kv_pair : metadata) {
599     // Length
600     const jbyte ltv_sz = kv_pair.second.size() + 1;
601     env->SetByteArrayRegion(raw_metadata, offset, 1, &ltv_sz);
602     offset += 1;
603     // Type
604     env->SetByteArrayRegion(raw_metadata, offset, 1,
605                             (const jbyte*)&kv_pair.first);
606     offset += 1;
607     // Value
608     env->SetByteArrayRegion(raw_metadata, offset, kv_pair.second.size(),
609                             (const jbyte*)kv_pair.second.data());
610     offset += kv_pair.second.size();
611   }
612 
613   return raw_metadata;
614 }
615 
getAudioLocationOrDefault(const std::map<uint8_t,std::vector<uint8_t>> & metadata,jlong default_location)616 static jlong getAudioLocationOrDefault(
617     const std::map<uint8_t, std::vector<uint8_t>>& metadata,
618     jlong default_location) {
619   if (metadata.count(
620           bluetooth::le_audio::kLeAudioCodecLC3TypeAudioChannelAllocation) == 0)
621     return default_location;
622 
623   auto& vec = metadata.at(
624       bluetooth::le_audio::kLeAudioCodecLC3TypeAudioChannelAllocation);
625   return VEC_UINT8_TO_UINT32(vec);
626 }
627 
prepareLeAudioCodecConfigMetadataObject(JNIEnv * env,const std::map<uint8_t,std::vector<uint8_t>> & metadata)628 jobject prepareLeAudioCodecConfigMetadataObject(
629     JNIEnv* env, const std::map<uint8_t, std::vector<uint8_t>>& metadata) {
630   jlong audio_location = getAudioLocationOrDefault(metadata, -1);
631   ScopedLocalRef<jbyteArray> raw_metadata(env,
632                                           prepareRawLtvArray(env, metadata));
633   if (!raw_metadata.get()) {
634     LOG(ERROR) << "Failed to create raw metadata jbyteArray";
635     return nullptr;
636   }
637 
638   jobject obj = env->NewObject(
639       android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz,
640       android_bluetooth_BluetoothLeAudioCodecConfigMetadata.constructor,
641       audio_location, raw_metadata.get());
642 
643   return obj;
644 }
645 
prepareLeBroadcastChannelObject(JNIEnv * env,const bluetooth::le_audio::BasicAudioAnnouncementBisConfig & bis_config)646 jobject prepareLeBroadcastChannelObject(
647     JNIEnv* env,
648     const bluetooth::le_audio::BasicAudioAnnouncementBisConfig& bis_config) {
649   ScopedLocalRef<jobject> meta_object(
650       env, prepareLeAudioCodecConfigMetadataObject(
651                env, bis_config.codec_specific_params));
652   if (!meta_object.get()) {
653     LOG(ERROR) << "Failed to create new metadata object for bis config";
654     return nullptr;
655   }
656 
657   jobject obj =
658       env->NewObject(android_bluetooth_BluetoothLeBroadcastChannel.clazz,
659                      android_bluetooth_BluetoothLeBroadcastChannel.constructor,
660                      false, bis_config.bis_index, meta_object.get());
661 
662   return obj;
663 }
664 
prepareLeAudioContentMetadataObject(JNIEnv * env,const std::map<uint8_t,std::vector<uint8_t>> & metadata)665 jobject prepareLeAudioContentMetadataObject(
666     JNIEnv* env, const std::map<uint8_t, std::vector<uint8_t>>& metadata) {
667   jstring program_info_str = nullptr;
668   if (metadata.count(bluetooth::le_audio::kLeAudioMetadataTypeProgramInfo)) {
669     program_info_str = env->NewStringUTF(
670         (const char*)(metadata
671                           .at(bluetooth::le_audio::
672                                   kLeAudioMetadataTypeProgramInfo)
673                           .data()));
674     if (!program_info_str) {
675       LOG(ERROR) << "Failed to create new preset name String for preset name";
676       return nullptr;
677     }
678   }
679 
680   jstring language_str = nullptr;
681   if (metadata.count(bluetooth::le_audio::kLeAudioMetadataTypeLanguage)) {
682     language_str = env->NewStringUTF(
683         (const char*)(metadata
684                           .at(bluetooth::le_audio::kLeAudioMetadataTypeLanguage)
685                           .data()));
686     if (!language_str) {
687       LOG(ERROR) << "Failed to create new preset name String for language";
688       return nullptr;
689     }
690   }
691 
692   // This can be nullptr
693   ScopedLocalRef<jbyteArray> raw_metadata(env,
694                                           prepareRawLtvArray(env, metadata));
695   if (!raw_metadata.get()) {
696     LOG(ERROR) << "Failed to create raw_metadata jbyteArray";
697     return nullptr;
698   }
699 
700   jobject obj = env->NewObject(
701       android_bluetooth_BluetoothLeAudioContentMetadata.clazz,
702       android_bluetooth_BluetoothLeAudioContentMetadata.constructor,
703       program_info_str, language_str, raw_metadata.get());
704 
705   if (program_info_str) {
706     env->DeleteLocalRef(program_info_str);
707   }
708 
709   if (language_str) {
710     env->DeleteLocalRef(language_str);
711   }
712 
713   return obj;
714 }
715 
prepareLeBroadcastChannelListObject(JNIEnv * env,const std::vector<bluetooth::le_audio::BasicAudioAnnouncementBisConfig> & bis_configs)716 jobject prepareLeBroadcastChannelListObject(
717     JNIEnv* env,
718     const std::vector<bluetooth::le_audio::BasicAudioAnnouncementBisConfig>&
719         bis_configs) {
720   jobject array = env->NewObject(java_util_ArrayList.clazz,
721                                  java_util_ArrayList.constructor);
722   if (!array) {
723     LOG(ERROR) << "Failed to create array for subgroups";
724     return nullptr;
725   }
726 
727   for (const auto& el : bis_configs) {
728     ScopedLocalRef<jobject> channel_obj(
729         env, prepareLeBroadcastChannelObject(env, el));
730     if (!channel_obj.get()) {
731       LOG(ERROR) << "Failed to create new channel object";
732       return nullptr;
733     }
734 
735     env->CallBooleanMethod(array, java_util_ArrayList.add, channel_obj.get());
736   }
737   return array;
738 }
739 
prepareLeBroadcastSubgroupObject(JNIEnv * env,const bluetooth::le_audio::BasicAudioAnnouncementSubgroup & subgroup)740 jobject prepareLeBroadcastSubgroupObject(
741     JNIEnv* env,
742     const bluetooth::le_audio::BasicAudioAnnouncementSubgroup& subgroup) {
743   // Serialize codec ID
744   jlong jlong_codec_id =
745       subgroup.codec_config.codec_id |
746       ((jlong)subgroup.codec_config.vendor_company_id << 16) |
747       ((jlong)subgroup.codec_config.vendor_codec_id << 32);
748 
749   ScopedLocalRef<jobject> codec_config_meta_obj(
750       env, prepareLeAudioCodecConfigMetadataObject(
751                env, subgroup.codec_config.codec_specific_params));
752   if (!codec_config_meta_obj.get()) {
753     LOG(ERROR) << "Failed to create new codec config metadata";
754     return nullptr;
755   }
756 
757   ScopedLocalRef<jobject> content_meta_obj(
758       env, prepareLeAudioContentMetadataObject(env, subgroup.metadata));
759   if (!content_meta_obj.get()) {
760     LOG(ERROR) << "Failed to create new codec config metadata";
761     return nullptr;
762   }
763 
764   ScopedLocalRef<jobject> channel_list_obj(
765       env, prepareLeBroadcastChannelListObject(env, subgroup.bis_configs));
766   if (!channel_list_obj.get()) {
767     LOG(ERROR) << "Failed to create new codec config metadata";
768     return nullptr;
769   }
770 
771   // Create the subgroup
772   return env->NewObject(
773       android_bluetooth_BluetoothLeBroadcastSubgroup.clazz,
774       android_bluetooth_BluetoothLeBroadcastSubgroup.constructor,
775       jlong_codec_id, codec_config_meta_obj.get(), content_meta_obj.get(),
776       channel_list_obj.get());
777 }
778 
prepareLeBroadcastSubgroupListObject(JNIEnv * env,const std::vector<bluetooth::le_audio::BasicAudioAnnouncementSubgroup> & subgroup_configs)779 jobject prepareLeBroadcastSubgroupListObject(
780     JNIEnv* env,
781     const std::vector<bluetooth::le_audio::BasicAudioAnnouncementSubgroup>&
782         subgroup_configs) {
783   jobject array = env->NewObject(java_util_ArrayList.clazz,
784                                  java_util_ArrayList.constructor);
785   if (!array) {
786     LOG(ERROR) << "Failed to create array for subgroups";
787     return nullptr;
788   }
789 
790   for (const auto& el : subgroup_configs) {
791     ScopedLocalRef<jobject> subgroup_obj(
792         env, prepareLeBroadcastSubgroupObject(env, el));
793     if (!subgroup_obj.get()) {
794       LOG(ERROR) << "Failed to create new subgroup object";
795       return nullptr;
796     }
797 
798     env->CallBooleanMethod(array, java_util_ArrayList.add, subgroup_obj.get());
799   }
800   return array;
801 }
802 
prepareBluetoothDeviceObject(JNIEnv * env,const RawAddress & addr,int addr_type)803 jobject prepareBluetoothDeviceObject(JNIEnv* env, const RawAddress& addr,
804                                      int addr_type) {
805   // The address string has to be uppercase or the BluetoothDevice constructor
806   // will treat it as invalid.
807   auto addr_str = addr.ToString();
808   std::transform(addr_str.begin(), addr_str.end(), addr_str.begin(),
809                  [](unsigned char c) { return std::toupper(c); });
810 
811   ScopedLocalRef<jstring> addr_jstr(env, env->NewStringUTF(addr_str.c_str()));
812   if (!addr_jstr.get()) {
813     LOG(ERROR) << "Failed to create new preset name String for preset name";
814     return nullptr;
815   }
816 
817   return env->NewObject(android_bluetooth_BluetoothDevice.clazz,
818                         android_bluetooth_BluetoothDevice.constructor,
819                         addr_jstr.get(), (jint)addr_type);
820 }
821 
prepareBluetoothLeBroadcastMetadataObject(JNIEnv * env,const bluetooth::le_audio::BroadcastMetadata & broadcast_metadata)822 jobject prepareBluetoothLeBroadcastMetadataObject(
823     JNIEnv* env,
824     const bluetooth::le_audio::BroadcastMetadata& broadcast_metadata) {
825   ScopedLocalRef<jobject> device_obj(
826       env, prepareBluetoothDeviceObject(env, broadcast_metadata.addr,
827                                         broadcast_metadata.addr_type));
828   if (!device_obj.get()) {
829     LOG(ERROR) << "Failed to create new BluetoothDevice";
830     return nullptr;
831   }
832 
833   ScopedLocalRef<jobject> subgroup_list_obj(
834       env,
835       prepareLeBroadcastSubgroupListObject(
836           env, broadcast_metadata.basic_audio_announcement.subgroup_configs));
837   if (!subgroup_list_obj.get()) {
838     LOG(ERROR) << "Failed to create new Subgroup array";
839     return nullptr;
840   }
841 
842   // Skip the leading null char bytes
843   int nativeCodeSize = 16;
844   int nativeCodeLeadingZeros = 0;
845   if (broadcast_metadata.broadcast_code) {
846     auto& nativeCode = broadcast_metadata.broadcast_code.value();
847     nativeCodeLeadingZeros =
848         std::find_if(nativeCode.cbegin(), nativeCode.cend(),
849                      [](int x) { return x != 0x00; }) -
850         nativeCode.cbegin();
851     nativeCodeSize = nativeCode.size() - nativeCodeLeadingZeros;
852   }
853 
854   ScopedLocalRef<jbyteArray> code(env, env->NewByteArray(nativeCodeSize));
855   if (!code.get()) {
856     LOG(ERROR) << "Failed to create new jbyteArray for the broadcast code";
857     return nullptr;
858   }
859 
860   if (broadcast_metadata.broadcast_code) {
861     env->SetByteArrayRegion(
862         code.get(), 0, nativeCodeSize,
863         (const jbyte*)broadcast_metadata.broadcast_code->data() +
864             nativeCodeLeadingZeros);
865     CHECK(!env->ExceptionCheck());
866   }
867 
868   return env->NewObject(
869       android_bluetooth_BluetoothLeBroadcastMetadata.clazz,
870       android_bluetooth_BluetoothLeBroadcastMetadata.constructor,
871       (jint)broadcast_metadata.addr_type, device_obj.get(),
872       (jint)broadcast_metadata.adv_sid, (jint)broadcast_metadata.broadcast_id,
873       (jint)broadcast_metadata.pa_interval,
874       broadcast_metadata.broadcast_code ? true : false,
875       broadcast_metadata.broadcast_code ? code.get() : nullptr,
876       (jint)broadcast_metadata.basic_audio_announcement.presentation_delay,
877       subgroup_list_obj.get());
878 }
879 
880 class LeAudioBroadcasterCallbacksImpl : public LeAudioBroadcasterCallbacks {
881  public:
882   ~LeAudioBroadcasterCallbacksImpl() = default;
883 
OnBroadcastCreated(uint32_t broadcast_id,bool success)884   void OnBroadcastCreated(uint32_t broadcast_id, bool success) override {
885     LOG(INFO) << __func__;
886 
887     std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
888     CallbackEnv sCallbackEnv(__func__);
889 
890     if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
891     sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj,
892                                  method_onBroadcastCreated, (jint)broadcast_id,
893                                  success ? JNI_TRUE : JNI_FALSE);
894   }
895 
OnBroadcastDestroyed(uint32_t broadcast_id)896   void OnBroadcastDestroyed(uint32_t broadcast_id) override {
897     LOG(INFO) << __func__;
898 
899     std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
900     CallbackEnv sCallbackEnv(__func__);
901 
902     if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
903     sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj,
904                                  method_onBroadcastDestroyed,
905                                  (jint)broadcast_id);
906   }
907 
OnBroadcastStateChanged(uint32_t broadcast_id,BroadcastState state)908   void OnBroadcastStateChanged(uint32_t broadcast_id,
909                                BroadcastState state) override {
910     LOG(INFO) << __func__;
911 
912     std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
913     CallbackEnv sCallbackEnv(__func__);
914 
915     if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
916     sCallbackEnv->CallVoidMethod(
917         sBroadcasterCallbacksObj, method_onBroadcastStateChanged,
918         (jint)broadcast_id,
919         (jint) static_cast<std::underlying_type<BroadcastState>::type>(state));
920   }
921 
OnBroadcastMetadataChanged(uint32_t broadcast_id,const bluetooth::le_audio::BroadcastMetadata & broadcast_metadata)922   void OnBroadcastMetadataChanged(uint32_t broadcast_id,
923                                   const bluetooth::le_audio::BroadcastMetadata&
924                                       broadcast_metadata) override {
925     LOG(INFO) << __func__;
926 
927     std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
928     CallbackEnv sCallbackEnv(__func__);
929 
930     ScopedLocalRef<jobject> metadata_obj(
931         sCallbackEnv.get(), prepareBluetoothLeBroadcastMetadataObject(
932                                 sCallbackEnv.get(), broadcast_metadata));
933 
934     if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) return;
935     sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj,
936                                  method_onBroadcastMetadataChanged,
937                                  (jint)broadcast_id, metadata_obj.get());
938   }
939 };
940 
941 static LeAudioBroadcasterCallbacksImpl sLeAudioBroadcasterCallbacks;
942 
BroadcasterClassInitNative(JNIEnv * env,jclass clazz)943 static void BroadcasterClassInitNative(JNIEnv* env, jclass clazz) {
944   method_onBroadcastCreated =
945       env->GetMethodID(clazz, "onBroadcastCreated", "(IZ)V");
946   method_onBroadcastDestroyed =
947       env->GetMethodID(clazz, "onBroadcastDestroyed", "(I)V");
948   method_onBroadcastStateChanged =
949       env->GetMethodID(clazz, "onBroadcastStateChanged", "(II)V");
950   method_onBroadcastMetadataChanged =
951       env->GetMethodID(clazz, "onBroadcastMetadataChanged",
952                        "(ILandroid/bluetooth/BluetoothLeBroadcastMetadata;)V");
953 
954   jclass jniArrayListClass = env->FindClass("java/util/ArrayList");
955   java_util_ArrayList.constructor =
956       env->GetMethodID(jniArrayListClass, "<init>", "()V");
957   java_util_ArrayList.add =
958       env->GetMethodID(jniArrayListClass, "add", "(Ljava/lang/Object;)Z");
959 
960   jclass jniBluetoothLeAudioCodecConfigMetadataClass =
961       env->FindClass("android/bluetooth/BluetoothLeAudioCodecConfigMetadata");
962   android_bluetooth_BluetoothLeAudioCodecConfigMetadata.constructor =
963       env->GetMethodID(jniBluetoothLeAudioCodecConfigMetadataClass, "<init>",
964                        "(J[B)V");
965 
966   jclass jniBluetoothLeAudioContentMetadataClass =
967       env->FindClass("android/bluetooth/BluetoothLeAudioContentMetadata");
968   android_bluetooth_BluetoothLeAudioContentMetadata.constructor =
969       env->GetMethodID(jniBluetoothLeAudioContentMetadataClass, "<init>",
970                        "(Ljava/lang/String;Ljava/lang/String;[B)V");
971 
972   jclass jniBluetoothLeBroadcastChannelClass =
973       env->FindClass("android/bluetooth/BluetoothLeBroadcastChannel");
974   android_bluetooth_BluetoothLeBroadcastChannel.constructor = env->GetMethodID(
975       jniBluetoothLeBroadcastChannelClass, "<init>",
976       "(ZILandroid/bluetooth/BluetoothLeAudioCodecConfigMetadata;)V");
977 
978   jclass jniBluetoothLeBroadcastSubgroupClass =
979       env->FindClass("android/bluetooth/BluetoothLeBroadcastSubgroup");
980   android_bluetooth_BluetoothLeBroadcastSubgroup.constructor = env->GetMethodID(
981       jniBluetoothLeBroadcastSubgroupClass, "<init>",
982       "(JLandroid/bluetooth/BluetoothLeAudioCodecConfigMetadata;"
983       "Landroid/bluetooth/BluetoothLeAudioContentMetadata;"
984       "Ljava/util/List;)V");
985 
986   jclass jniBluetoothDeviceClass =
987       env->FindClass("android/bluetooth/BluetoothDevice");
988   android_bluetooth_BluetoothDevice.constructor = env->GetMethodID(
989       jniBluetoothDeviceClass, "<init>", "(Ljava/lang/String;I)V");
990 
991   jclass jniBluetoothLeBroadcastMetadataClass =
992       env->FindClass("android/bluetooth/BluetoothLeBroadcastMetadata");
993   android_bluetooth_BluetoothLeBroadcastMetadata.constructor = env->GetMethodID(
994       jniBluetoothLeBroadcastMetadataClass, "<init>",
995       "(ILandroid/bluetooth/BluetoothDevice;IIIZ[BILjava/util/List;)V");
996 }
997 
BroadcasterInitNative(JNIEnv * env,jobject object)998 static void BroadcasterInitNative(JNIEnv* env, jobject object) {
999   std::unique_lock<std::shared_timed_mutex> interface_lock(
1000       sBroadcasterInterfaceMutex);
1001   std::unique_lock<std::shared_timed_mutex> callbacks_lock(
1002       sBroadcasterCallbacksMutex);
1003 
1004   const bt_interface_t* btInf = getBluetoothInterface();
1005   if (btInf == nullptr) {
1006     LOG(ERROR) << "Bluetooth module is not loaded";
1007     return;
1008   }
1009 
1010   android_bluetooth_BluetoothDevice.clazz = (jclass)env->NewGlobalRef(
1011       env->FindClass("android/bluetooth/BluetoothDevice"));
1012   if (android_bluetooth_BluetoothDevice.clazz == nullptr) {
1013     LOG(ERROR) << "Failed to allocate Global Ref for BluetoothDevice class";
1014     return;
1015   }
1016 
1017   java_util_ArrayList.clazz =
1018       (jclass)env->NewGlobalRef(env->FindClass("java/util/ArrayList"));
1019   if (java_util_ArrayList.clazz == nullptr) {
1020     LOG(ERROR) << "Failed to allocate Global Ref for ArrayList class";
1021     return;
1022   }
1023 
1024   android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz =
1025       (jclass)env->NewGlobalRef(env->FindClass(
1026           "android/bluetooth/BluetoothLeAudioCodecConfigMetadata"));
1027   if (android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz == nullptr) {
1028     LOG(ERROR) << "Failed to allocate Global Ref for "
1029                   "BluetoothLeAudioCodecConfigMetadata class";
1030     return;
1031   }
1032 
1033   android_bluetooth_BluetoothLeAudioContentMetadata.clazz =
1034       (jclass)env->NewGlobalRef(
1035           env->FindClass("android/bluetooth/BluetoothLeAudioContentMetadata"));
1036   if (android_bluetooth_BluetoothLeAudioContentMetadata.clazz == nullptr) {
1037     LOG(ERROR) << "Failed to allocate Global Ref for "
1038                   "BluetoothLeAudioContentMetadata class";
1039     return;
1040   }
1041 
1042   android_bluetooth_BluetoothLeBroadcastSubgroup.clazz =
1043       (jclass)env->NewGlobalRef(
1044           env->FindClass("android/bluetooth/BluetoothLeBroadcastSubgroup"));
1045   if (android_bluetooth_BluetoothLeBroadcastSubgroup.clazz == nullptr) {
1046     LOG(ERROR) << "Failed to allocate Global Ref for "
1047                   "BluetoothLeBroadcastSubgroup class";
1048     return;
1049   }
1050 
1051   android_bluetooth_BluetoothLeBroadcastChannel.clazz =
1052       (jclass)env->NewGlobalRef(
1053           env->FindClass("android/bluetooth/BluetoothLeBroadcastChannel"));
1054   if (android_bluetooth_BluetoothLeBroadcastChannel.clazz == nullptr) {
1055     LOG(ERROR) << "Failed to allocate Global Ref for "
1056                   "BluetoothLeBroadcastChannel class";
1057     return;
1058   }
1059 
1060   android_bluetooth_BluetoothLeBroadcastMetadata.clazz =
1061       (jclass)env->NewGlobalRef(
1062           env->FindClass("android/bluetooth/BluetoothLeBroadcastMetadata"));
1063   if (android_bluetooth_BluetoothLeBroadcastMetadata.clazz == nullptr) {
1064     LOG(ERROR) << "Failed to allocate Global Ref for "
1065                   "BluetoothLeBroadcastMetadata class";
1066     return;
1067   }
1068 
1069   if (sBroadcasterCallbacksObj != nullptr) {
1070     LOG(INFO) << "Cleaning up LeAudio Broadcaster callback object";
1071     env->DeleteGlobalRef(sBroadcasterCallbacksObj);
1072     sBroadcasterCallbacksObj = nullptr;
1073   }
1074 
1075   if ((sBroadcasterCallbacksObj = env->NewGlobalRef(object)) == nullptr) {
1076     LOG(ERROR)
1077         << "Failed to allocate Global Ref for LeAudio Broadcaster Callbacks";
1078     return;
1079   }
1080 
1081   sLeAudioBroadcasterInterface =
1082       (LeAudioBroadcasterInterface*)btInf->get_profile_interface(
1083           BT_PROFILE_LE_AUDIO_BROADCASTER_ID);
1084   if (sLeAudioBroadcasterInterface == nullptr) {
1085     LOG(ERROR) << "Failed to get Bluetooth LeAudio Broadcaster Interface";
1086     return;
1087   }
1088 
1089   sLeAudioBroadcasterInterface->Initialize(&sLeAudioBroadcasterCallbacks);
1090 }
1091 
BroadcasterStopNative(JNIEnv * env,jobject object)1092 static void BroadcasterStopNative(JNIEnv* env, jobject object) {
1093   std::unique_lock<std::shared_timed_mutex> interface_lock(
1094       sBroadcasterInterfaceMutex);
1095 
1096   const bt_interface_t* btInf = getBluetoothInterface();
1097   if (btInf == nullptr) {
1098     LOG(ERROR) << "Bluetooth module is not loaded";
1099     return;
1100   }
1101 
1102   if (sLeAudioBroadcasterInterface != nullptr)
1103     sLeAudioBroadcasterInterface->Stop();
1104 }
1105 
BroadcasterCleanupNative(JNIEnv * env,jobject object)1106 static void BroadcasterCleanupNative(JNIEnv* env, jobject object) {
1107   std::unique_lock<std::shared_timed_mutex> interface_lock(
1108       sBroadcasterInterfaceMutex);
1109   std::unique_lock<std::shared_timed_mutex> callbacks_lock(
1110       sBroadcasterCallbacksMutex);
1111 
1112   const bt_interface_t* btInf = getBluetoothInterface();
1113   if (btInf == nullptr) {
1114     LOG(ERROR) << "Bluetooth module is not loaded";
1115     return;
1116   }
1117 
1118   env->DeleteGlobalRef(java_util_ArrayList.clazz);
1119   java_util_ArrayList.clazz = nullptr;
1120 
1121   env->DeleteGlobalRef(android_bluetooth_BluetoothDevice.clazz);
1122   android_bluetooth_BluetoothDevice.clazz = nullptr;
1123 
1124   env->DeleteGlobalRef(
1125       android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz);
1126   android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz = nullptr;
1127 
1128   env->DeleteGlobalRef(android_bluetooth_BluetoothLeAudioContentMetadata.clazz);
1129   android_bluetooth_BluetoothLeAudioContentMetadata.clazz = nullptr;
1130 
1131   env->DeleteGlobalRef(android_bluetooth_BluetoothLeBroadcastSubgroup.clazz);
1132   android_bluetooth_BluetoothLeBroadcastSubgroup.clazz = nullptr;
1133 
1134   env->DeleteGlobalRef(android_bluetooth_BluetoothLeBroadcastChannel.clazz);
1135   android_bluetooth_BluetoothLeBroadcastChannel.clazz = nullptr;
1136 
1137   env->DeleteGlobalRef(android_bluetooth_BluetoothLeBroadcastMetadata.clazz);
1138   android_bluetooth_BluetoothLeBroadcastMetadata.clazz = nullptr;
1139 
1140   if (sLeAudioBroadcasterInterface != nullptr) {
1141     sLeAudioBroadcasterInterface->Cleanup();
1142     sLeAudioBroadcasterInterface = nullptr;
1143   }
1144 
1145   if (sBroadcasterCallbacksObj != nullptr) {
1146     env->DeleteGlobalRef(sBroadcasterCallbacksObj);
1147     sBroadcasterCallbacksObj = nullptr;
1148   }
1149 }
1150 
CreateBroadcastNative(JNIEnv * env,jobject object,jbyteArray metadata,jbyteArray broadcast_code)1151 static void CreateBroadcastNative(JNIEnv* env, jobject object,
1152                                   jbyteArray metadata,
1153                                   jbyteArray broadcast_code) {
1154   LOG(INFO) << __func__;
1155   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1156   if (!sLeAudioBroadcasterInterface) return;
1157 
1158   std::array<uint8_t, 16> code_array{0};
1159   if (broadcast_code) {
1160     jsize size = env->GetArrayLength(broadcast_code);
1161     if (size > 16) {
1162       ALOGE("%s: broadcast code to long", __func__);
1163       return;
1164     }
1165 
1166     // Padding with zeros on LSB positions if code is shorter than 16 octets
1167     env->GetByteArrayRegion(
1168         broadcast_code, 0, size,
1169         (jbyte*)code_array.data() + code_array.size() - size);
1170   }
1171 
1172   jbyte* meta = env->GetByteArrayElements(metadata, nullptr);
1173   sLeAudioBroadcasterInterface->CreateBroadcast(
1174       std::vector<uint8_t>(meta, meta + env->GetArrayLength(metadata)),
1175       broadcast_code ? std::optional<std::array<uint8_t, 16>>(code_array)
1176                      : std::nullopt);
1177   env->ReleaseByteArrayElements(metadata, meta, 0);
1178 }
1179 
UpdateMetadataNative(JNIEnv * env,jobject object,jint broadcast_id,jbyteArray metadata)1180 static void UpdateMetadataNative(JNIEnv* env, jobject object, jint broadcast_id,
1181                                  jbyteArray metadata) {
1182   jbyte* meta = env->GetByteArrayElements(metadata, nullptr);
1183   sLeAudioBroadcasterInterface->UpdateMetadata(
1184       broadcast_id,
1185       std::vector<uint8_t>(meta, meta + env->GetArrayLength(metadata)));
1186   env->ReleaseByteArrayElements(metadata, meta, 0);
1187 }
1188 
StartBroadcastNative(JNIEnv * env,jobject object,jint broadcast_id)1189 static void StartBroadcastNative(JNIEnv* env, jobject object,
1190                                  jint broadcast_id) {
1191   LOG(INFO) << __func__;
1192   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1193   if (!sLeAudioBroadcasterInterface) return;
1194   sLeAudioBroadcasterInterface->StartBroadcast(broadcast_id);
1195 }
1196 
StopBroadcastNative(JNIEnv * env,jobject object,jint broadcast_id)1197 static void StopBroadcastNative(JNIEnv* env, jobject object,
1198                                 jint broadcast_id) {
1199   LOG(INFO) << __func__;
1200   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1201   if (!sLeAudioBroadcasterInterface) return;
1202   sLeAudioBroadcasterInterface->StopBroadcast(broadcast_id);
1203 }
1204 
PauseBroadcastNative(JNIEnv * env,jobject object,jint broadcast_id)1205 static void PauseBroadcastNative(JNIEnv* env, jobject object,
1206                                  jint broadcast_id) {
1207   LOG(INFO) << __func__;
1208   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1209   if (!sLeAudioBroadcasterInterface) return;
1210   sLeAudioBroadcasterInterface->PauseBroadcast(broadcast_id);
1211 }
1212 
DestroyBroadcastNative(JNIEnv * env,jobject object,jint broadcast_id)1213 static void DestroyBroadcastNative(JNIEnv* env, jobject object,
1214                                    jint broadcast_id) {
1215   LOG(INFO) << __func__;
1216   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1217   if (!sLeAudioBroadcasterInterface) return;
1218   sLeAudioBroadcasterInterface->DestroyBroadcast(broadcast_id);
1219 }
1220 
getBroadcastMetadataNative(JNIEnv * env,jobject object,jint broadcast_id)1221 static void getBroadcastMetadataNative(JNIEnv* env, jobject object,
1222                                        jint broadcast_id) {
1223   LOG(INFO) << __func__;
1224   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1225   if (!sLeAudioBroadcasterInterface) return;
1226   sLeAudioBroadcasterInterface->GetBroadcastMetadata(broadcast_id);
1227 }
1228 
1229 static JNINativeMethod sBroadcasterMethods[] = {
1230     {"classInitNative", "()V", (void*)BroadcasterClassInitNative},
1231     {"initNative", "()V", (void*)BroadcasterInitNative},
1232     {"stopNative", "()V", (void*)BroadcasterStopNative},
1233     {"cleanupNative", "()V", (void*)BroadcasterCleanupNative},
1234     {"createBroadcastNative", "([B[B)V", (void*)CreateBroadcastNative},
1235     {"updateMetadataNative", "(I[B)V", (void*)UpdateMetadataNative},
1236     {"startBroadcastNative", "(I)V", (void*)StartBroadcastNative},
1237     {"stopBroadcastNative", "(I)V", (void*)StopBroadcastNative},
1238     {"pauseBroadcastNative", "(I)V", (void*)PauseBroadcastNative},
1239     {"destroyBroadcastNative", "(I)V", (void*)DestroyBroadcastNative},
1240     {"getBroadcastMetadataNative", "(I)V", (void*)getBroadcastMetadataNative},
1241 };
1242 
register_com_android_bluetooth_le_audio(JNIEnv * env)1243 int register_com_android_bluetooth_le_audio(JNIEnv* env) {
1244   int register_success = jniRegisterNativeMethods(
1245       env, "com/android/bluetooth/le_audio/LeAudioNativeInterface", sMethods,
1246       NELEM(sMethods));
1247   return register_success &
1248          jniRegisterNativeMethods(
1249              env,
1250              "com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterface",
1251              sBroadcasterMethods, NELEM(sBroadcasterMethods));
1252 }
1253 }  // namespace android
1254