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 <bluetooth/log.h>
20 #include <jni.h>
21 #include <nativehelper/JNIHelp.h>
22 #include <nativehelper/scoped_local_ref.h>
23 
24 #include <algorithm>
25 #include <array>
26 #include <cctype>
27 #include <cerrno>
28 #include <cstdint>
29 #include <cstring>
30 #include <map>
31 #include <mutex>
32 #include <optional>
33 #include <shared_mutex>
34 #include <string>
35 #include <type_traits>
36 #include <vector>
37 
38 #include "com_android_bluetooth.h"
39 #include "hardware/bluetooth.h"
40 #include "hardware/bt_le_audio.h"
41 #include "types/raw_address.h"
42 
43 // TODO(b/369381361) Enfore -Wmissing-prototypes
44 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
45 
46 using bluetooth::le_audio::BroadcastId;
47 using bluetooth::le_audio::BroadcastState;
48 using bluetooth::le_audio::btle_audio_bits_per_sample_index_t;
49 using bluetooth::le_audio::btle_audio_channel_count_index_t;
50 using bluetooth::le_audio::btle_audio_codec_config_t;
51 using bluetooth::le_audio::btle_audio_codec_index_t;
52 using bluetooth::le_audio::btle_audio_frame_duration_index_t;
53 using bluetooth::le_audio::btle_audio_sample_rate_index_t;
54 using bluetooth::le_audio::ConnectionState;
55 using bluetooth::le_audio::GroupNodeStatus;
56 using bluetooth::le_audio::GroupStatus;
57 using bluetooth::le_audio::GroupStreamStatus;
58 using bluetooth::le_audio::LeAudioBroadcasterCallbacks;
59 using bluetooth::le_audio::LeAudioBroadcasterInterface;
60 using bluetooth::le_audio::LeAudioClientCallbacks;
61 using bluetooth::le_audio::LeAudioClientInterface;
62 using bluetooth::le_audio::UnicastMonitorModeStatus;
63 
64 namespace android {
65 static jmethodID method_onInitialized;
66 static jmethodID method_onConnectionStateChanged;
67 static jmethodID method_onGroupStatus;
68 static jmethodID method_onGroupNodeStatus;
69 static jmethodID method_onAudioConf;
70 static jmethodID method_onSinkAudioLocationAvailable;
71 static jmethodID method_onAudioLocalCodecCapabilities;
72 static jmethodID method_onAudioGroupCurrentCodecConf;
73 static jmethodID method_onAudioGroupSelectableCodecConf;
74 static jmethodID method_onHealthBasedRecommendationAction;
75 static jmethodID method_onHealthBasedGroupRecommendationAction;
76 static jmethodID method_onUnicastMonitorModeStatus;
77 static jmethodID method_onGroupStreamStatus;
78 
79 static struct {
80   jclass clazz;
81   jmethodID constructor;
82   jmethodID getCodecType;
83   jmethodID getSampleRate;
84   jmethodID getBitsPerSample;
85   jmethodID getChannelCount;
86   jmethodID getFrameDuration;
87   jmethodID getOctetsPerFrame;
88   jmethodID getCodecPriority;
89 } android_bluetooth_BluetoothLeAudioCodecConfig;
90 
91 static struct {
92   jclass clazz;
93   jmethodID constructor;
94 } android_bluetooth_BluetoothLeAudioCodecConfigMetadata;
95 
96 static struct {
97   jclass clazz;
98   jmethodID constructor;
99   jmethodID add;
100 } java_util_ArrayList;
101 
102 static struct {
103   jclass clazz;
104   jmethodID constructor;
105 } android_bluetooth_BluetoothLeBroadcastChannel;
106 
107 static struct {
108   jclass clazz;
109   jmethodID constructor;
110 } android_bluetooth_BluetoothLeBroadcastSubgroup;
111 
112 static struct {
113   jclass clazz;
114   jmethodID constructor;
115 } android_bluetooth_BluetoothLeAudioContentMetadata;
116 
117 static struct {
118   jclass clazz;
119   jmethodID constructor;
120 } android_bluetooth_BluetoothLeBroadcastMetadata;
121 
122 static struct {
123   jclass clazz;
124   jmethodID constructor;
125 } android_bluetooth_BluetoothDevice;
126 
127 static LeAudioClientInterface* sLeAudioClientInterface = nullptr;
128 static std::shared_timed_mutex interface_mutex;
129 
130 static jobject mCallbacksObj = nullptr;
131 static std::shared_timed_mutex callbacks_mutex;
132 
prepareCodecConfigObj(JNIEnv * env,btle_audio_codec_config_t codecConfig)133 jobject prepareCodecConfigObj(JNIEnv* env, btle_audio_codec_config_t codecConfig) {
134   log::info(
135           "ct: {}, codec_priority: {}, sample_rate: {}, bits_per_sample: {}, "
136           "channel_count: {}, frame_duration: {}, octets_per_frame: {}",
137           codecConfig.codec_type, codecConfig.codec_priority, codecConfig.sample_rate,
138           codecConfig.bits_per_sample, codecConfig.channel_count, codecConfig.frame_duration,
139           codecConfig.octets_per_frame);
140 
141   jobject codecConfigObj = env->NewObject(
142           android_bluetooth_BluetoothLeAudioCodecConfig.clazz,
143           android_bluetooth_BluetoothLeAudioCodecConfig.constructor, (jint)codecConfig.codec_type,
144           (jint)codecConfig.codec_priority, (jint)codecConfig.sample_rate,
145           (jint)codecConfig.bits_per_sample, (jint)codecConfig.channel_count,
146           (jint)codecConfig.frame_duration, (jint)codecConfig.octets_per_frame, 0, 0);
147   return codecConfigObj;
148 }
149 
prepareArrayOfCodecConfigs(JNIEnv * env,std::vector<btle_audio_codec_config_t> codecConfigs)150 jobjectArray prepareArrayOfCodecConfigs(JNIEnv* env,
151                                         std::vector<btle_audio_codec_config_t> codecConfigs) {
152   jsize i = 0;
153   jobjectArray CodecConfigArray = env->NewObjectArray(
154           (jsize)codecConfigs.size(), android_bluetooth_BluetoothLeAudioCodecConfig.clazz, nullptr);
155 
156   for (auto const& cap : codecConfigs) {
157     jobject Obj = prepareCodecConfigObj(env, cap);
158 
159     env->SetObjectArrayElement(CodecConfigArray, i++, Obj);
160     env->DeleteLocalRef(Obj);
161   }
162 
163   return CodecConfigArray;
164 }
165 
166 class LeAudioClientCallbacksImpl : public LeAudioClientCallbacks {
167 public:
168   ~LeAudioClientCallbacksImpl() = default;
169 
OnInitialized(void)170   void OnInitialized(void) override {
171     log::info("");
172     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
173     CallbackEnv sCallbackEnv(__func__);
174     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) {
175       return;
176     }
177     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onInitialized);
178   }
179 
OnConnectionState(ConnectionState state,const RawAddress & bd_addr)180   void OnConnectionState(ConnectionState state, const RawAddress& bd_addr) override {
181     log::info("state:{}, addr: {}", int(state), bd_addr.ToRedactedStringForLogging());
182 
183     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
184     CallbackEnv sCallbackEnv(__func__);
185     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) {
186       return;
187     }
188 
189     ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(),
190                                     sCallbackEnv->NewByteArray(sizeof(RawAddress)));
191     if (!addr.get()) {
192       log::error("Failed to new jbyteArray bd addr for connection state");
193       return;
194     }
195 
196     sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)&bd_addr);
197     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, (jint)state,
198                                  addr.get());
199   }
200 
OnGroupStatus(int group_id,GroupStatus group_status)201   void OnGroupStatus(int group_id, GroupStatus group_status) override {
202     log::info("");
203 
204     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
205     CallbackEnv sCallbackEnv(__func__);
206     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) {
207       return;
208     }
209 
210     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGroupStatus, (jint)group_id,
211                                  (jint)group_status);
212   }
213 
OnGroupNodeStatus(const RawAddress & bd_addr,int group_id,GroupNodeStatus node_status)214   void OnGroupNodeStatus(const RawAddress& bd_addr, int group_id,
215                          GroupNodeStatus node_status) override {
216     log::info("");
217 
218     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
219     CallbackEnv sCallbackEnv(__func__);
220     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) {
221       return;
222     }
223 
224     ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(),
225                                     sCallbackEnv->NewByteArray(sizeof(RawAddress)));
226     if (!addr.get()) {
227       log::error("Failed to new jbyteArray bd addr for group status");
228       return;
229     }
230 
231     sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)&bd_addr);
232     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGroupNodeStatus, addr.get(),
233                                  (jint)group_id, (jint)node_status);
234   }
235 
OnAudioConf(uint8_t direction,int group_id,uint32_t sink_audio_location,uint32_t source_audio_location,uint16_t avail_cont)236   void OnAudioConf(uint8_t direction, int group_id, uint32_t sink_audio_location,
237                    uint32_t source_audio_location, uint16_t avail_cont) override {
238     log::info("");
239 
240     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
241     CallbackEnv sCallbackEnv(__func__);
242     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) {
243       return;
244     }
245 
246     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioConf, (jint)direction, (jint)group_id,
247                                  (jint)sink_audio_location, (jint)source_audio_location,
248                                  (jint)avail_cont);
249   }
250 
OnSinkAudioLocationAvailable(const RawAddress & bd_addr,uint32_t sink_audio_location)251   void OnSinkAudioLocationAvailable(const RawAddress& bd_addr,
252                                     uint32_t sink_audio_location) override {
253     log::info("");
254 
255     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
256     CallbackEnv sCallbackEnv(__func__);
257     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) {
258       return;
259     }
260 
261     ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(),
262                                     sCallbackEnv->NewByteArray(sizeof(RawAddress)));
263     if (!addr.get()) {
264       log::error("Failed to new jbyteArray bd addr for group status");
265       return;
266     }
267 
268     sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)&bd_addr);
269     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSinkAudioLocationAvailable, addr.get(),
270                                  (jint)sink_audio_location);
271   }
272 
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)273   void OnAudioLocalCodecCapabilities(
274           std::vector<btle_audio_codec_config_t> local_input_capa_codec_conf,
275           std::vector<btle_audio_codec_config_t> local_output_capa_codec_conf) override {
276     log::info("");
277 
278     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
279     CallbackEnv sCallbackEnv(__func__);
280     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) {
281       return;
282     }
283 
284     jobject localInputCapCodecConfigArray =
285             prepareArrayOfCodecConfigs(sCallbackEnv.get(), local_input_capa_codec_conf);
286 
287     jobject localOutputCapCodecConfigArray =
288             prepareArrayOfCodecConfigs(sCallbackEnv.get(), local_output_capa_codec_conf);
289 
290     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioLocalCodecCapabilities,
291                                  localInputCapCodecConfigArray, localOutputCapCodecConfigArray);
292   }
293 
OnAudioGroupCurrentCodecConf(int group_id,btle_audio_codec_config_t input_codec_conf,btle_audio_codec_config_t output_codec_conf)294   void OnAudioGroupCurrentCodecConf(int group_id, btle_audio_codec_config_t input_codec_conf,
295                                     btle_audio_codec_config_t output_codec_conf) override {
296     log::info("");
297 
298     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
299     CallbackEnv sCallbackEnv(__func__);
300     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) {
301       return;
302     }
303 
304     jobject inputCodecConfigObj = prepareCodecConfigObj(sCallbackEnv.get(), input_codec_conf);
305     jobject outputCodecConfigObj = prepareCodecConfigObj(sCallbackEnv.get(), output_codec_conf);
306 
307     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioGroupCurrentCodecConf, (jint)group_id,
308                                  inputCodecConfigObj, outputCodecConfigObj);
309   }
310 
OnAudioGroupSelectableCodecConf(int group_id,std::vector<btle_audio_codec_config_t> input_selectable_codec_conf,std::vector<btle_audio_codec_config_t> output_selectable_codec_conf)311   void OnAudioGroupSelectableCodecConf(
312           int group_id, std::vector<btle_audio_codec_config_t> input_selectable_codec_conf,
313           std::vector<btle_audio_codec_config_t> output_selectable_codec_conf) override {
314     log::info("");
315 
316     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
317     CallbackEnv sCallbackEnv(__func__);
318     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) {
319       return;
320     }
321 
322     jobject inputSelectableCodecConfigArray =
323             prepareArrayOfCodecConfigs(sCallbackEnv.get(), input_selectable_codec_conf);
324     jobject outputSelectableCodecConfigArray =
325             prepareArrayOfCodecConfigs(sCallbackEnv.get(), output_selectable_codec_conf);
326 
327     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioGroupSelectableCodecConf,
328                                  (jint)group_id, inputSelectableCodecConfigArray,
329                                  outputSelectableCodecConfigArray);
330   }
331 
OnHealthBasedRecommendationAction(const RawAddress & bd_addr,bluetooth::le_audio::LeAudioHealthBasedAction action)332   void OnHealthBasedRecommendationAction(
333           const RawAddress& bd_addr,
334           bluetooth::le_audio::LeAudioHealthBasedAction action) override {
335     log::info("");
336 
337     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
338     CallbackEnv sCallbackEnv(__func__);
339     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) {
340       return;
341     }
342 
343     ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(),
344                                     sCallbackEnv->NewByteArray(sizeof(RawAddress)));
345     if (!addr.get()) {
346       log::error("Failed to new jbyteArray bd addr for group status");
347       return;
348     }
349 
350     sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)&bd_addr);
351     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onHealthBasedRecommendationAction,
352                                  addr.get(), (jint)action);
353   }
354 
OnHealthBasedGroupRecommendationAction(int group_id,bluetooth::le_audio::LeAudioHealthBasedAction action)355   void OnHealthBasedGroupRecommendationAction(
356           int group_id, bluetooth::le_audio::LeAudioHealthBasedAction action) override {
357     log::info("");
358 
359     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
360     CallbackEnv sCallbackEnv(__func__);
361     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) {
362       return;
363     }
364 
365     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onHealthBasedGroupRecommendationAction,
366                                  (jint)group_id, (jint)action);
367   }
368 
OnUnicastMonitorModeStatus(uint8_t direction,UnicastMonitorModeStatus status)369   void OnUnicastMonitorModeStatus(uint8_t direction, UnicastMonitorModeStatus status) override {
370     log::info("");
371 
372     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
373     CallbackEnv sCallbackEnv(__func__);
374     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) {
375       return;
376     }
377 
378     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onUnicastMonitorModeStatus, (jint)direction,
379                                  (jint)status);
380   }
381 
OnGroupStreamStatus(int group_id,GroupStreamStatus group_stream_status)382   void OnGroupStreamStatus(int group_id, GroupStreamStatus group_stream_status) override {
383     log::info("");
384 
385     std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
386     CallbackEnv sCallbackEnv(__func__);
387     if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) {
388       return;
389     }
390 
391     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onGroupStreamStatus, (jint)group_id,
392                                  (jint)group_stream_status);
393   }
394 };
395 
396 static LeAudioClientCallbacksImpl sLeAudioClientCallbacks;
397 
prepareCodecPreferences(JNIEnv * env,jobject,jobjectArray codecConfigArray)398 std::vector<btle_audio_codec_config_t> prepareCodecPreferences(JNIEnv* env, jobject /* object */,
399                                                                jobjectArray codecConfigArray) {
400   std::vector<btle_audio_codec_config_t> codec_preferences;
401 
402   int numConfigs = env->GetArrayLength(codecConfigArray);
403   for (int i = 0; i < numConfigs; i++) {
404     jobject jcodecConfig = env->GetObjectArrayElement(codecConfigArray, i);
405     if (jcodecConfig == nullptr) {
406       continue;
407     }
408     if (!env->IsInstanceOf(jcodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.clazz)) {
409       log::error("Invalid BluetoothLeAudioCodecConfig instance");
410       continue;
411     }
412     jint codecType = env->CallIntMethod(jcodecConfig,
413                                         android_bluetooth_BluetoothLeAudioCodecConfig.getCodecType);
414 
415     btle_audio_codec_config_t codec_config = {
416             .codec_type = static_cast<btle_audio_codec_index_t>(codecType)};
417 
418     codec_preferences.push_back(codec_config);
419   }
420   return codec_preferences;
421 }
422 
initNative(JNIEnv * env,jobject object,jobjectArray codecOffloadingArray)423 static void initNative(JNIEnv* env, jobject object, jobjectArray codecOffloadingArray) {
424   std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex);
425   std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex);
426 
427   const bt_interface_t* btInf = getBluetoothInterface();
428   if (btInf == nullptr) {
429     log::error("Bluetooth module is not loaded");
430     return;
431   }
432 
433   if (mCallbacksObj != nullptr) {
434     log::info("Cleaning up LeAudio callback object");
435     env->DeleteGlobalRef(mCallbacksObj);
436     mCallbacksObj = nullptr;
437   }
438 
439   if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) {
440     log::error("Failed to allocate Global Ref for LeAudio Callbacks");
441     return;
442   }
443 
444   android_bluetooth_BluetoothLeAudioCodecConfig.clazz = (jclass)env->NewGlobalRef(
445           env->FindClass("android/bluetooth/BluetoothLeAudioCodecConfig"));
446   if (android_bluetooth_BluetoothLeAudioCodecConfig.clazz == nullptr) {
447     log::error("Failed to allocate Global Ref for BluetoothLeAudioCodecConfig class");
448     return;
449   }
450 
451   sLeAudioClientInterface =
452           (LeAudioClientInterface*)btInf->get_profile_interface(BT_PROFILE_LE_AUDIO_ID);
453   if (sLeAudioClientInterface == nullptr) {
454     log::error("Failed to get Bluetooth LeAudio Interface");
455     return;
456   }
457 
458   std::vector<btle_audio_codec_config_t> codec_offloading =
459           prepareCodecPreferences(env, object, codecOffloadingArray);
460 
461   sLeAudioClientInterface->Initialize(&sLeAudioClientCallbacks, codec_offloading);
462 }
463 
cleanupNative(JNIEnv * env,jobject)464 static void cleanupNative(JNIEnv* env, jobject /* object */) {
465   std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex);
466   std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex);
467 
468   const bt_interface_t* btInf = getBluetoothInterface();
469   if (btInf == nullptr) {
470     log::error("Bluetooth module is not loaded");
471     return;
472   }
473 
474   if (sLeAudioClientInterface != nullptr) {
475     sLeAudioClientInterface->Cleanup();
476     sLeAudioClientInterface = nullptr;
477   }
478 
479   env->DeleteGlobalRef(android_bluetooth_BluetoothLeAudioCodecConfig.clazz);
480   android_bluetooth_BluetoothLeAudioCodecConfig.clazz = nullptr;
481 
482   if (mCallbacksObj != nullptr) {
483     env->DeleteGlobalRef(mCallbacksObj);
484     mCallbacksObj = nullptr;
485   }
486 }
487 
connectLeAudioNative(JNIEnv * env,jobject,jbyteArray address)488 static jboolean connectLeAudioNative(JNIEnv* env, jobject /* object */, jbyteArray address) {
489   log::info("");
490   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
491   if (!sLeAudioClientInterface) {
492     return JNI_FALSE;
493   }
494 
495   jbyte* addr = env->GetByteArrayElements(address, nullptr);
496   if (!addr) {
497     jniThrowIOException(env, EINVAL);
498     return JNI_FALSE;
499   }
500 
501   RawAddress* tmpraw = (RawAddress*)addr;
502   sLeAudioClientInterface->Connect(*tmpraw);
503   env->ReleaseByteArrayElements(address, addr, 0);
504   return JNI_TRUE;
505 }
506 
disconnectLeAudioNative(JNIEnv * env,jobject,jbyteArray address)507 static jboolean disconnectLeAudioNative(JNIEnv* env, jobject /* object */, jbyteArray address) {
508   log::info("");
509   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
510   if (!sLeAudioClientInterface) {
511     return JNI_FALSE;
512   }
513 
514   jbyte* addr = env->GetByteArrayElements(address, nullptr);
515   if (!addr) {
516     jniThrowIOException(env, EINVAL);
517     return JNI_FALSE;
518   }
519 
520   RawAddress* tmpraw = (RawAddress*)addr;
521   sLeAudioClientInterface->Disconnect(*tmpraw);
522   env->ReleaseByteArrayElements(address, addr, 0);
523   return JNI_TRUE;
524 }
525 
setEnableStateNative(JNIEnv * env,jobject,jbyteArray address,jboolean enabled)526 static jboolean setEnableStateNative(JNIEnv* env, jobject /* object */, jbyteArray address,
527                                      jboolean enabled) {
528   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
529   jbyte* addr = env->GetByteArrayElements(address, nullptr);
530 
531   if (!sLeAudioClientInterface) {
532     log::error("Failed to get the Bluetooth LeAudio Interface");
533     return JNI_FALSE;
534   }
535 
536   if (!addr) {
537     jniThrowIOException(env, EINVAL);
538     return JNI_FALSE;
539   }
540 
541   RawAddress* tmpraw = (RawAddress*)addr;
542   sLeAudioClientInterface->SetEnableState(*tmpraw, enabled);
543   env->ReleaseByteArrayElements(address, addr, 0);
544   return JNI_TRUE;
545 }
546 
groupAddNodeNative(JNIEnv * env,jobject,jint group_id,jbyteArray address)547 static jboolean groupAddNodeNative(JNIEnv* env, jobject /* object */, jint group_id,
548                                    jbyteArray address) {
549   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
550   jbyte* addr = env->GetByteArrayElements(address, nullptr);
551 
552   if (!sLeAudioClientInterface) {
553     log::error("Failed to get the Bluetooth LeAudio Interface");
554     return JNI_FALSE;
555   }
556 
557   if (!addr) {
558     jniThrowIOException(env, EINVAL);
559     return JNI_FALSE;
560   }
561 
562   RawAddress* tmpraw = (RawAddress*)addr;
563   sLeAudioClientInterface->GroupAddNode(group_id, *tmpraw);
564   env->ReleaseByteArrayElements(address, addr, 0);
565 
566   return JNI_TRUE;
567 }
568 
groupRemoveNodeNative(JNIEnv * env,jobject,jint group_id,jbyteArray address)569 static jboolean groupRemoveNodeNative(JNIEnv* env, jobject /* object */, jint group_id,
570                                       jbyteArray address) {
571   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
572   if (!sLeAudioClientInterface) {
573     log::error("Failed to get the Bluetooth LeAudio Interface");
574     return JNI_FALSE;
575   }
576 
577   jbyte* addr = env->GetByteArrayElements(address, nullptr);
578   if (!addr) {
579     jniThrowIOException(env, EINVAL);
580     return JNI_FALSE;
581   }
582 
583   RawAddress* tmpraw = (RawAddress*)addr;
584   sLeAudioClientInterface->GroupRemoveNode(group_id, *tmpraw);
585   env->ReleaseByteArrayElements(address, addr, 0);
586   return JNI_TRUE;
587 }
588 
groupSetActiveNative(JNIEnv *,jobject,jint group_id)589 static void groupSetActiveNative(JNIEnv* /* env */, jobject /* object */, jint group_id) {
590   log::info("");
591   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
592 
593   if (!sLeAudioClientInterface) {
594     log::error("Failed to get the Bluetooth LeAudio Interface");
595     return;
596   }
597 
598   sLeAudioClientInterface->GroupSetActive(group_id);
599 }
600 
setCodecConfigPreferenceNative(JNIEnv * env,jobject,jint group_id,jobject inputCodecConfig,jobject outputCodecConfig)601 static void setCodecConfigPreferenceNative(JNIEnv* env, jobject /* object */, jint group_id,
602                                            jobject inputCodecConfig, jobject outputCodecConfig) {
603   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
604 
605   if (!env->IsInstanceOf(inputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.clazz) ||
606       !env->IsInstanceOf(outputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.clazz)) {
607     log::error("Invalid BluetoothLeAudioCodecConfig instance");
608     return;
609   }
610 
611   jint inputCodecType = env->CallIntMethod(
612           inputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.getCodecType);
613 
614   jint inputSampleRate = env->CallIntMethod(
615           inputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.getSampleRate);
616 
617   jint inputBitsPerSample = env->CallIntMethod(
618           inputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.getBitsPerSample);
619 
620   jint inputChannelCount = env->CallIntMethod(
621           inputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.getChannelCount);
622 
623   jint inputFrameDuration = env->CallIntMethod(
624           inputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.getFrameDuration);
625 
626   jint inputOctetsPerFrame = env->CallIntMethod(
627           inputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.getOctetsPerFrame);
628 
629   jint inputCodecPriority = env->CallIntMethod(
630           inputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.getCodecPriority);
631 
632   btle_audio_codec_config_t input_codec_config = {
633           .codec_type = static_cast<btle_audio_codec_index_t>(inputCodecType),
634           .sample_rate = static_cast<btle_audio_sample_rate_index_t>(inputSampleRate),
635           .bits_per_sample = static_cast<btle_audio_bits_per_sample_index_t>(inputBitsPerSample),
636           .channel_count = static_cast<btle_audio_channel_count_index_t>(inputChannelCount),
637           .frame_duration = static_cast<btle_audio_frame_duration_index_t>(inputFrameDuration),
638           .octets_per_frame = static_cast<uint16_t>(inputOctetsPerFrame),
639           .codec_priority = static_cast<int32_t>(inputCodecPriority),
640   };
641 
642   jint outputCodecType = env->CallIntMethod(
643           outputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.getCodecType);
644 
645   jint outputSampleRate = env->CallIntMethod(
646           outputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.getSampleRate);
647 
648   jint outputBitsPerSample = env->CallIntMethod(
649           outputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.getBitsPerSample);
650 
651   jint outputChannelCount = env->CallIntMethod(
652           outputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.getChannelCount);
653 
654   jint outputFrameDuration = env->CallIntMethod(
655           outputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.getFrameDuration);
656 
657   jint outputOctetsPerFrame = env->CallIntMethod(
658           outputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.getOctetsPerFrame);
659 
660   jint outputCodecPriority = env->CallIntMethod(
661           outputCodecConfig, android_bluetooth_BluetoothLeAudioCodecConfig.getCodecPriority);
662 
663   btle_audio_codec_config_t output_codec_config = {
664           .codec_type = static_cast<btle_audio_codec_index_t>(outputCodecType),
665           .sample_rate = static_cast<btle_audio_sample_rate_index_t>(outputSampleRate),
666           .bits_per_sample = static_cast<btle_audio_bits_per_sample_index_t>(outputBitsPerSample),
667           .channel_count = static_cast<btle_audio_channel_count_index_t>(outputChannelCount),
668           .frame_duration = static_cast<btle_audio_frame_duration_index_t>(outputFrameDuration),
669           .octets_per_frame = static_cast<uint16_t>(outputOctetsPerFrame),
670           .codec_priority = static_cast<int32_t>(outputCodecPriority),
671   };
672 
673   sLeAudioClientInterface->SetCodecConfigPreference(group_id, input_codec_config,
674                                                     output_codec_config);
675 }
676 
setCcidInformationNative(JNIEnv *,jobject,jint ccid,jint contextType)677 static void setCcidInformationNative(JNIEnv* /* env */, jobject /* object */, jint ccid,
678                                      jint contextType) {
679   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
680   if (!sLeAudioClientInterface) {
681     log::error("Failed to get the Bluetooth LeAudio Interface");
682     return;
683   }
684 
685   sLeAudioClientInterface->SetCcidInformation(ccid, contextType);
686 }
687 
setInCallNative(JNIEnv *,jobject,jboolean inCall)688 static void setInCallNative(JNIEnv* /* env */, jobject /* object */, jboolean inCall) {
689   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
690   if (!sLeAudioClientInterface) {
691     log::error("Failed to get the Bluetooth LeAudio Interface");
692     return;
693   }
694 
695   sLeAudioClientInterface->SetInCall(inCall);
696 }
697 
setUnicastMonitorModeNative(JNIEnv *,jobject,jint direction,jboolean enable)698 static void setUnicastMonitorModeNative(JNIEnv* /* env */, jobject /* object */, jint direction,
699                                         jboolean enable) {
700   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
701   if (!sLeAudioClientInterface) {
702     log::error("Failed to get the Bluetooth LeAudio Interface");
703     return;
704   }
705 
706   sLeAudioClientInterface->SetUnicastMonitorMode(direction, enable);
707 }
708 
sendAudioProfilePreferencesNative(JNIEnv *,jobject,jint groupId,jboolean isOutputPreferenceLeAudio,jboolean isDuplexPreferenceLeAudio)709 static void sendAudioProfilePreferencesNative(JNIEnv* /* env */, jobject /* object */, jint groupId,
710                                               jboolean isOutputPreferenceLeAudio,
711                                               jboolean isDuplexPreferenceLeAudio) {
712   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
713   if (!sLeAudioClientInterface) {
714     log::error("Failed to get the Bluetooth LeAudio Interface");
715     return;
716   }
717 
718   sLeAudioClientInterface->SendAudioProfilePreferences(groupId, isOutputPreferenceLeAudio,
719                                                        isDuplexPreferenceLeAudio);
720 }
721 
setGroupAllowedContextMaskNative(JNIEnv *,jobject,jint groupId,jint sinkContextTypes,jint sourceContextTypes)722 static void setGroupAllowedContextMaskNative(JNIEnv* /* env */, jobject /* object */, jint groupId,
723                                              jint sinkContextTypes, jint sourceContextTypes) {
724   std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
725   if (!sLeAudioClientInterface) {
726     log::error("Failed to get the Bluetooth LeAudio Interface");
727     return;
728   }
729 
730   log::info("group_id: {}, sink context types: {}, source context types: {}", groupId,
731             sinkContextTypes, sourceContextTypes);
732 
733   sLeAudioClientInterface->SetGroupAllowedContextMask(groupId, sinkContextTypes,
734                                                       sourceContextTypes);
735 }
736 
737 /* Le Audio Broadcaster */
738 static jmethodID method_onBroadcastCreated;
739 static jmethodID method_onBroadcastDestroyed;
740 static jmethodID method_onBroadcastStateChanged;
741 static jmethodID method_onBroadcastMetadataChanged;
742 static jmethodID method_onBroadcastAudioSessionCreated;
743 
744 static LeAudioBroadcasterInterface* sLeAudioBroadcasterInterface = nullptr;
745 static std::shared_timed_mutex sBroadcasterInterfaceMutex;
746 
747 static jobject sBroadcasterCallbacksObj = nullptr;
748 static std::shared_timed_mutex sBroadcasterCallbacksMutex;
749 
750 #define VEC_UINT8_TO_UINT32(vec) \
751   ((vec.data()[3] << 24) + (vec.data()[2] << 16) + (vec.data()[1] << 8) + vec.data()[0])
752 
753 #define VEC_UINT8_TO_UINT16(vec) (((vec).data()[1] << 8) + ((vec).data()[0]))
754 
RawPacketSize(const std::map<uint8_t,std::vector<uint8_t>> & values)755 size_t RawPacketSize(const std::map<uint8_t, std::vector<uint8_t>>& values) {
756   size_t bytes = 0;
757   for (auto const& value : values) {
758     bytes += (/* ltv_len + ltv_type */ 2 + value.second.size());
759   }
760   return bytes;
761 }
762 
prepareRawLtvArray(JNIEnv * env,const std::map<uint8_t,std::vector<uint8_t>> & metadata)763 jbyteArray prepareRawLtvArray(JNIEnv* env,
764                               const std::map<uint8_t, std::vector<uint8_t>>& metadata) {
765   auto raw_meta_size = RawPacketSize(metadata);
766 
767   jbyteArray raw_metadata = env->NewByteArray(raw_meta_size);
768   if (!raw_metadata) {
769     log::error("Failed to create new jbyteArray for raw LTV");
770     return nullptr;
771   }
772 
773   jsize offset = 0;
774   for (auto const& kv_pair : metadata) {
775     // Length
776     const jbyte ltv_sz = kv_pair.second.size() + 1;
777     env->SetByteArrayRegion(raw_metadata, offset, 1, &ltv_sz);
778     offset += 1;
779     // Type
780     env->SetByteArrayRegion(raw_metadata, offset, 1, (const jbyte*)&kv_pair.first);
781     offset += 1;
782     // Value
783     env->SetByteArrayRegion(raw_metadata, offset, kv_pair.second.size(),
784                             (const jbyte*)kv_pair.second.data());
785     offset += kv_pair.second.size();
786   }
787 
788   return raw_metadata;
789 }
790 
getAudioLocationOrDefault(const std::map<uint8_t,std::vector<uint8_t>> & metadata,jlong default_location)791 static jlong getAudioLocationOrDefault(const std::map<uint8_t, std::vector<uint8_t>>& metadata,
792                                        jlong default_location) {
793   if (metadata.count(bluetooth::le_audio::kLeAudioLtvTypeAudioChannelAllocation) == 0) {
794     return default_location;
795   }
796 
797   auto& vec = metadata.at(bluetooth::le_audio::kLeAudioLtvTypeAudioChannelAllocation);
798   return VEC_UINT8_TO_UINT32(vec);
799 }
800 
getSamplingFrequencyOrDefault(const std::map<uint8_t,std::vector<uint8_t>> & metadata,jint default_sampling_frequency)801 static jint getSamplingFrequencyOrDefault(const std::map<uint8_t, std::vector<uint8_t>>& metadata,
802                                           jint default_sampling_frequency) {
803   if (metadata.count(bluetooth::le_audio::kLeAudioLtvTypeSamplingFreq) == 0) {
804     return default_sampling_frequency;
805   }
806 
807   auto& vec = metadata.at(bluetooth::le_audio::kLeAudioLtvTypeSamplingFreq);
808   return (jint)(vec.data()[0]);
809 }
810 
getFrameDurationOrDefault(const std::map<uint8_t,std::vector<uint8_t>> & metadata,jint default_frame_duration)811 static jint getFrameDurationOrDefault(const std::map<uint8_t, std::vector<uint8_t>>& metadata,
812                                       jint default_frame_duration) {
813   if (metadata.count(bluetooth::le_audio::kLeAudioLtvTypeFrameDuration) == 0) {
814     return default_frame_duration;
815   }
816 
817   auto& vec = metadata.at(bluetooth::le_audio::kLeAudioLtvTypeFrameDuration);
818   return (jint)(vec.data()[0]);
819 }
820 
getOctetsPerFrameOrDefault(const std::map<uint8_t,std::vector<uint8_t>> & metadata,jint default_octets_per_frame)821 static jint getOctetsPerFrameOrDefault(const std::map<uint8_t, std::vector<uint8_t>>& metadata,
822                                        jint default_octets_per_frame) {
823   if (metadata.count(bluetooth::le_audio::kLeAudioLtvTypeOctetsPerCodecFrame) == 0) {
824     return default_octets_per_frame;
825   }
826 
827   auto& vec = metadata.at(bluetooth::le_audio::kLeAudioLtvTypeOctetsPerCodecFrame);
828   return VEC_UINT8_TO_UINT16(vec);
829 }
830 
prepareLeAudioCodecConfigMetadataObject(JNIEnv * env,const std::map<uint8_t,std::vector<uint8_t>> & metadata)831 jobject prepareLeAudioCodecConfigMetadataObject(
832         JNIEnv* env, const std::map<uint8_t, std::vector<uint8_t>>& metadata) {
833   jlong audio_location = getAudioLocationOrDefault(metadata, -1);
834   jint sampling_frequency = getSamplingFrequencyOrDefault(metadata, 0);
835   jint frame_duration = getFrameDurationOrDefault(metadata, -1);
836   jint octets_per_frame = getOctetsPerFrameOrDefault(metadata, 0);
837   ScopedLocalRef<jbyteArray> raw_metadata(env, prepareRawLtvArray(env, metadata));
838   if (!raw_metadata.get()) {
839     log::error("Failed to create raw metadata jbyteArray");
840     return nullptr;
841   }
842 
843   jobject obj = env->NewObject(android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz,
844                                android_bluetooth_BluetoothLeAudioCodecConfigMetadata.constructor,
845                                audio_location, sampling_frequency, frame_duration, octets_per_frame,
846                                raw_metadata.get());
847 
848   return obj;
849 }
850 
prepareLeBroadcastChannelObject(JNIEnv * env,const bluetooth::le_audio::BasicAudioAnnouncementBisConfig & bis_config)851 jobject prepareLeBroadcastChannelObject(
852         JNIEnv* env, const bluetooth::le_audio::BasicAudioAnnouncementBisConfig& bis_config) {
853   ScopedLocalRef<jobject> meta_object(
854           env, prepareLeAudioCodecConfigMetadataObject(env, bis_config.codec_specific_params));
855   if (!meta_object.get()) {
856     log::error("Failed to create new metadata object for bis config");
857     return nullptr;
858   }
859 
860   jobject obj = env->NewObject(android_bluetooth_BluetoothLeBroadcastChannel.clazz,
861                                android_bluetooth_BluetoothLeBroadcastChannel.constructor, false,
862                                bis_config.bis_index, meta_object.get());
863 
864   return obj;
865 }
866 
prepareLeAudioContentMetadataObject(JNIEnv * env,const std::map<uint8_t,std::vector<uint8_t>> & metadata)867 jobject prepareLeAudioContentMetadataObject(
868         JNIEnv* env, const std::map<uint8_t, std::vector<uint8_t>>& metadata) {
869   jstring program_info_str = nullptr;
870   if (metadata.count(bluetooth::le_audio::kLeAudioMetadataTypeProgramInfo)) {
871     // Convert the metadata vector to string with null terminator
872     std::string p_str(
873             (const char*)metadata.at(bluetooth::le_audio::kLeAudioMetadataTypeProgramInfo).data(),
874             metadata.at(bluetooth::le_audio::kLeAudioMetadataTypeProgramInfo).size());
875 
876     program_info_str = env->NewStringUTF(p_str.c_str());
877     if (!program_info_str) {
878       log::error("Failed to create new preset name String for preset name");
879       return nullptr;
880     }
881   }
882 
883   jstring language_str = nullptr;
884   if (metadata.count(bluetooth::le_audio::kLeAudioMetadataTypeLanguage)) {
885     // Convert the metadata vector to string with null terminator
886     std::string l_str(
887             (const char*)metadata.at(bluetooth::le_audio::kLeAudioMetadataTypeLanguage).data(),
888             metadata.at(bluetooth::le_audio::kLeAudioMetadataTypeLanguage).size());
889 
890     language_str = env->NewStringUTF(l_str.c_str());
891     if (!language_str) {
892       log::error("Failed to create new preset name String for language");
893       return nullptr;
894     }
895   }
896 
897   // This can be nullptr
898   ScopedLocalRef<jbyteArray> raw_metadata(env, prepareRawLtvArray(env, metadata));
899   if (!raw_metadata.get()) {
900     log::error("Failed to create raw_metadata jbyteArray");
901     return nullptr;
902   }
903 
904   jobject obj = env->NewObject(android_bluetooth_BluetoothLeAudioContentMetadata.clazz,
905                                android_bluetooth_BluetoothLeAudioContentMetadata.constructor,
906                                program_info_str, language_str, raw_metadata.get());
907 
908   if (program_info_str) {
909     env->DeleteLocalRef(program_info_str);
910   }
911 
912   if (language_str) {
913     env->DeleteLocalRef(language_str);
914   }
915 
916   return obj;
917 }
918 
prepareLeBroadcastChannelListObject(JNIEnv * env,const std::vector<bluetooth::le_audio::BasicAudioAnnouncementBisConfig> & bis_configs)919 jobject prepareLeBroadcastChannelListObject(
920         JNIEnv* env,
921         const std::vector<bluetooth::le_audio::BasicAudioAnnouncementBisConfig>& bis_configs) {
922   jobject array = env->NewObject(java_util_ArrayList.clazz, java_util_ArrayList.constructor);
923   if (!array) {
924     log::error("Failed to create array for subgroups");
925     return nullptr;
926   }
927 
928   for (const auto& el : bis_configs) {
929     ScopedLocalRef<jobject> channel_obj(env, prepareLeBroadcastChannelObject(env, el));
930     if (!channel_obj.get()) {
931       log::error("Failed to create new channel object");
932       return nullptr;
933     }
934 
935     env->CallBooleanMethod(array, java_util_ArrayList.add, channel_obj.get());
936   }
937   return array;
938 }
939 
prepareLeBroadcastSubgroupObject(JNIEnv * env,const bluetooth::le_audio::BasicAudioAnnouncementSubgroup & subgroup)940 jobject prepareLeBroadcastSubgroupObject(
941         JNIEnv* env, const bluetooth::le_audio::BasicAudioAnnouncementSubgroup& subgroup) {
942   // Serialize codec ID
943   jlong jlong_codec_id = subgroup.codec_config.codec_id |
944                          ((jlong)subgroup.codec_config.vendor_company_id << 16) |
945                          ((jlong)subgroup.codec_config.vendor_codec_id << 32);
946 
947   ScopedLocalRef<jobject> codec_config_meta_obj(
948           env, prepareLeAudioCodecConfigMetadataObject(
949                        env, subgroup.codec_config.codec_specific_params));
950   if (!codec_config_meta_obj.get()) {
951     log::error("Failed to create new codec config metadata");
952     return nullptr;
953   }
954 
955   ScopedLocalRef<jobject> content_meta_obj(
956           env, prepareLeAudioContentMetadataObject(env, subgroup.metadata));
957   if (!content_meta_obj.get()) {
958     log::error("Failed to create new codec config metadata");
959     return nullptr;
960   }
961 
962   ScopedLocalRef<jobject> channel_list_obj(
963           env, prepareLeBroadcastChannelListObject(env, subgroup.bis_configs));
964   if (!channel_list_obj.get()) {
965     log::error("Failed to create new codec config metadata");
966     return nullptr;
967   }
968 
969   // Create the subgroup
970   return env->NewObject(android_bluetooth_BluetoothLeBroadcastSubgroup.clazz,
971                         android_bluetooth_BluetoothLeBroadcastSubgroup.constructor, jlong_codec_id,
972                         codec_config_meta_obj.get(), content_meta_obj.get(),
973                         channel_list_obj.get());
974 }
975 
prepareLeBroadcastSubgroupListObject(JNIEnv * env,const std::vector<bluetooth::le_audio::BasicAudioAnnouncementSubgroup> & subgroup_configs)976 jobject prepareLeBroadcastSubgroupListObject(
977         JNIEnv* env,
978         const std::vector<bluetooth::le_audio::BasicAudioAnnouncementSubgroup>& subgroup_configs) {
979   jobject array = env->NewObject(java_util_ArrayList.clazz, java_util_ArrayList.constructor);
980   if (!array) {
981     log::error("Failed to create array for subgroups");
982     return nullptr;
983   }
984 
985   for (const auto& el : subgroup_configs) {
986     ScopedLocalRef<jobject> subgroup_obj(env, prepareLeBroadcastSubgroupObject(env, el));
987     if (!subgroup_obj.get()) {
988       log::error("Failed to create new subgroup object");
989       return nullptr;
990     }
991 
992     env->CallBooleanMethod(array, java_util_ArrayList.add, subgroup_obj.get());
993   }
994   return array;
995 }
996 
prepareBluetoothDeviceObject(JNIEnv * env,const RawAddress & addr,int addr_type)997 jobject prepareBluetoothDeviceObject(JNIEnv* env, const RawAddress& addr, int addr_type) {
998   // The address string has to be uppercase or the BluetoothDevice constructor
999   // will treat it as invalid.
1000   auto addr_str = addr.ToString();
1001   std::transform(addr_str.begin(), addr_str.end(), addr_str.begin(),
1002                  [](unsigned char c) { return std::toupper(c); });
1003 
1004   ScopedLocalRef<jstring> addr_jstr(env, env->NewStringUTF(addr_str.c_str()));
1005   if (!addr_jstr.get()) {
1006     log::error("Failed to create new preset name String for preset name");
1007     return nullptr;
1008   }
1009 
1010   return env->NewObject(android_bluetooth_BluetoothDevice.clazz,
1011                         android_bluetooth_BluetoothDevice.constructor, addr_jstr.get(),
1012                         (jint)addr_type);
1013 }
1014 
prepareBluetoothLeBroadcastMetadataObject(JNIEnv * env,const bluetooth::le_audio::BroadcastMetadata & broadcast_metadata)1015 jobject prepareBluetoothLeBroadcastMetadataObject(
1016         JNIEnv* env, const bluetooth::le_audio::BroadcastMetadata& broadcast_metadata) {
1017   ScopedLocalRef<jobject> device_obj(
1018           env,
1019           prepareBluetoothDeviceObject(env, broadcast_metadata.addr, broadcast_metadata.addr_type));
1020   if (!device_obj.get()) {
1021     log::error("Failed to create new BluetoothDevice");
1022     return nullptr;
1023   }
1024 
1025   ScopedLocalRef<jobject> subgroup_list_obj(
1026           env, prepareLeBroadcastSubgroupListObject(
1027                        env, broadcast_metadata.basic_audio_announcement.subgroup_configs));
1028   if (!subgroup_list_obj.get()) {
1029     log::error("Failed to create new Subgroup array");
1030     return nullptr;
1031   }
1032 
1033   // Remove the ending null char bytes
1034   int nativeCodeSize = 16;
1035   if (broadcast_metadata.broadcast_code) {
1036     auto& nativeCode = broadcast_metadata.broadcast_code.value();
1037     nativeCodeSize =
1038             std::find_if(nativeCode.cbegin(), nativeCode.cend(), [](int x) { return x == 0x00; }) -
1039             nativeCode.cbegin();
1040   }
1041 
1042   ScopedLocalRef<jbyteArray> code(env, env->NewByteArray(nativeCodeSize));
1043   if (!code.get()) {
1044     log::error("Failed to create new jbyteArray for the broadcast code");
1045     return nullptr;
1046   }
1047 
1048   if (broadcast_metadata.broadcast_code) {
1049     env->SetByteArrayRegion(code.get(), 0, nativeCodeSize,
1050                             (const jbyte*)broadcast_metadata.broadcast_code->data());
1051     log::assert_that(!env->ExceptionCheck(), "assert failed: !env->ExceptionCheck()");
1052   }
1053 
1054   ScopedLocalRef<jstring> broadcast_name(
1055           env, env->NewStringUTF(broadcast_metadata.broadcast_name.c_str()));
1056   if (!broadcast_name.get()) {
1057     log::error("Failed to create new broadcast name String");
1058     return nullptr;
1059   }
1060 
1061   jint audio_cfg_quality = 0;
1062   if (broadcast_metadata.public_announcement.features &
1063       bluetooth::le_audio::kLeAudioQualityStandard) {
1064     // Set bit 0 for AUDIO_CONFIG_QUALITY_STANDARD
1065     audio_cfg_quality |= 0x1 << bluetooth::le_audio::QUALITY_STANDARD;
1066   }
1067   if (broadcast_metadata.public_announcement.features & bluetooth::le_audio::kLeAudioQualityHigh) {
1068     // Set bit 1 for AUDIO_CONFIG_QUALITY_HIGH
1069     audio_cfg_quality |= 0x1 << bluetooth::le_audio::QUALITY_HIGH;
1070   }
1071 
1072   ScopedLocalRef<jobject> public_meta_obj(
1073           env, prepareLeAudioContentMetadataObject(
1074                        env, broadcast_metadata.public_announcement.metadata));
1075   if (!public_meta_obj.get()) {
1076     log::error("Failed to create new public metadata obj");
1077     return nullptr;
1078   }
1079 
1080   return env->NewObject(
1081           android_bluetooth_BluetoothLeBroadcastMetadata.clazz,
1082           android_bluetooth_BluetoothLeBroadcastMetadata.constructor,
1083           (jint)broadcast_metadata.addr_type, device_obj.get(), (jint)broadcast_metadata.adv_sid,
1084           (jint)broadcast_metadata.broadcast_id, (jint)broadcast_metadata.pa_interval,
1085           broadcast_metadata.broadcast_code ? true : false, broadcast_metadata.is_public,
1086           broadcast_name.get(), broadcast_metadata.broadcast_code ? code.get() : nullptr,
1087           (jint)broadcast_metadata.basic_audio_announcement.presentation_delay_us,
1088           audio_cfg_quality, (jint)bluetooth::le_audio::kLeAudioSourceRssiUnknown,
1089           public_meta_obj.get(), subgroup_list_obj.get());
1090 }
1091 
1092 class LeAudioBroadcasterCallbacksImpl : public LeAudioBroadcasterCallbacks {
1093 public:
1094   ~LeAudioBroadcasterCallbacksImpl() = default;
1095 
OnBroadcastCreated(uint32_t broadcast_id,bool success)1096   void OnBroadcastCreated(uint32_t broadcast_id, bool success) override {
1097     log::info("");
1098 
1099     std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
1100     CallbackEnv sCallbackEnv(__func__);
1101 
1102     if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) {
1103       return;
1104     }
1105     sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj, method_onBroadcastCreated,
1106                                  (jint)broadcast_id, success ? JNI_TRUE : JNI_FALSE);
1107   }
1108 
OnBroadcastDestroyed(uint32_t broadcast_id)1109   void OnBroadcastDestroyed(uint32_t broadcast_id) override {
1110     log::info("");
1111 
1112     std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
1113     CallbackEnv sCallbackEnv(__func__);
1114 
1115     if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) {
1116       return;
1117     }
1118     sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj, method_onBroadcastDestroyed,
1119                                  (jint)broadcast_id);
1120   }
1121 
OnBroadcastStateChanged(uint32_t broadcast_id,BroadcastState state)1122   void OnBroadcastStateChanged(uint32_t broadcast_id, BroadcastState state) override {
1123     log::info("");
1124 
1125     std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
1126     CallbackEnv sCallbackEnv(__func__);
1127 
1128     if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) {
1129       return;
1130     }
1131     sCallbackEnv->CallVoidMethod(
1132             sBroadcasterCallbacksObj, method_onBroadcastStateChanged, (jint)broadcast_id,
1133             (jint) static_cast<std::underlying_type<BroadcastState>::type>(state));
1134   }
1135 
OnBroadcastMetadataChanged(uint32_t broadcast_id,const bluetooth::le_audio::BroadcastMetadata & broadcast_metadata)1136   void OnBroadcastMetadataChanged(
1137           uint32_t broadcast_id,
1138           const bluetooth::le_audio::BroadcastMetadata& broadcast_metadata) override {
1139     log::info("");
1140 
1141     std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
1142     CallbackEnv sCallbackEnv(__func__);
1143 
1144     ScopedLocalRef<jobject> metadata_obj(
1145             sCallbackEnv.get(),
1146             prepareBluetoothLeBroadcastMetadataObject(sCallbackEnv.get(), broadcast_metadata));
1147 
1148     if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) {
1149       return;
1150     }
1151     sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj, method_onBroadcastMetadataChanged,
1152                                  (jint)broadcast_id, metadata_obj.get());
1153   }
1154 
OnBroadcastAudioSessionCreated(bool success)1155   void OnBroadcastAudioSessionCreated(bool success) override {
1156     log::info("");
1157 
1158     std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterCallbacksMutex);
1159     CallbackEnv sCallbackEnv(__func__);
1160 
1161     if (!sCallbackEnv.valid() || sBroadcasterCallbacksObj == nullptr) {
1162       return;
1163     }
1164     sCallbackEnv->CallVoidMethod(sBroadcasterCallbacksObj, method_onBroadcastAudioSessionCreated,
1165                                  success ? JNI_TRUE : JNI_FALSE);
1166   }
1167 };
1168 
1169 static LeAudioBroadcasterCallbacksImpl sLeAudioBroadcasterCallbacks;
1170 
BroadcasterInitNative(JNIEnv * env,jobject object)1171 static void BroadcasterInitNative(JNIEnv* env, jobject object) {
1172   std::unique_lock<std::shared_timed_mutex> interface_lock(sBroadcasterInterfaceMutex);
1173   std::unique_lock<std::shared_timed_mutex> callbacks_lock(sBroadcasterCallbacksMutex);
1174 
1175   const bt_interface_t* btInf = getBluetoothInterface();
1176   if (btInf == nullptr) {
1177     log::error("Bluetooth module is not loaded");
1178     return;
1179   }
1180 
1181   android_bluetooth_BluetoothDevice.clazz =
1182           (jclass)env->NewGlobalRef(env->FindClass("android/bluetooth/BluetoothDevice"));
1183   if (android_bluetooth_BluetoothDevice.clazz == nullptr) {
1184     log::error("Failed to allocate Global Ref for BluetoothDevice class");
1185     return;
1186   }
1187 
1188   java_util_ArrayList.clazz = (jclass)env->NewGlobalRef(env->FindClass("java/util/ArrayList"));
1189   if (java_util_ArrayList.clazz == nullptr) {
1190     log::error("Failed to allocate Global Ref for ArrayList class");
1191     return;
1192   }
1193 
1194   android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz = (jclass)env->NewGlobalRef(
1195           env->FindClass("android/bluetooth/BluetoothLeAudioCodecConfigMetadata"));
1196   if (android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz == nullptr) {
1197     log::error(
1198             "Failed to allocate Global Ref for BluetoothLeAudioCodecConfigMetadata "
1199             "class");
1200     return;
1201   }
1202 
1203   android_bluetooth_BluetoothLeAudioContentMetadata.clazz = (jclass)env->NewGlobalRef(
1204           env->FindClass("android/bluetooth/BluetoothLeAudioContentMetadata"));
1205   if (android_bluetooth_BluetoothLeAudioContentMetadata.clazz == nullptr) {
1206     log::error(
1207             "Failed to allocate Global Ref for BluetoothLeAudioContentMetadata "
1208             "class");
1209     return;
1210   }
1211 
1212   android_bluetooth_BluetoothLeBroadcastSubgroup.clazz = (jclass)env->NewGlobalRef(
1213           env->FindClass("android/bluetooth/BluetoothLeBroadcastSubgroup"));
1214   if (android_bluetooth_BluetoothLeBroadcastSubgroup.clazz == nullptr) {
1215     log::error("Failed to allocate Global Ref for BluetoothLeBroadcastSubgroup class");
1216     return;
1217   }
1218 
1219   android_bluetooth_BluetoothLeBroadcastChannel.clazz = (jclass)env->NewGlobalRef(
1220           env->FindClass("android/bluetooth/BluetoothLeBroadcastChannel"));
1221   if (android_bluetooth_BluetoothLeBroadcastChannel.clazz == nullptr) {
1222     log::error("Failed to allocate Global Ref for BluetoothLeBroadcastChannel class");
1223     return;
1224   }
1225 
1226   android_bluetooth_BluetoothLeBroadcastMetadata.clazz = (jclass)env->NewGlobalRef(
1227           env->FindClass("android/bluetooth/BluetoothLeBroadcastMetadata"));
1228   if (android_bluetooth_BluetoothLeBroadcastMetadata.clazz == nullptr) {
1229     log::error("Failed to allocate Global Ref for BluetoothLeBroadcastMetadata class");
1230     return;
1231   }
1232 
1233   if (sBroadcasterCallbacksObj != nullptr) {
1234     log::info("Cleaning up LeAudio Broadcaster callback object");
1235     env->DeleteGlobalRef(sBroadcasterCallbacksObj);
1236     sBroadcasterCallbacksObj = nullptr;
1237   }
1238 
1239   if ((sBroadcasterCallbacksObj = env->NewGlobalRef(object)) == nullptr) {
1240     log::error("Failed to allocate Global Ref for LeAudio Broadcaster Callbacks");
1241     return;
1242   }
1243 
1244   sLeAudioBroadcasterInterface = (LeAudioBroadcasterInterface*)btInf->get_profile_interface(
1245           BT_PROFILE_LE_AUDIO_BROADCASTER_ID);
1246   if (sLeAudioBroadcasterInterface == nullptr) {
1247     log::error("Failed to get Bluetooth LeAudio Broadcaster Interface");
1248     return;
1249   }
1250 
1251   sLeAudioBroadcasterInterface->Initialize(&sLeAudioBroadcasterCallbacks);
1252 }
1253 
BroadcasterStopNative(JNIEnv *,jobject)1254 static void BroadcasterStopNative(JNIEnv* /* env */, jobject /* object */) {
1255   std::unique_lock<std::shared_timed_mutex> interface_lock(sBroadcasterInterfaceMutex);
1256 
1257   const bt_interface_t* btInf = getBluetoothInterface();
1258   if (btInf == nullptr) {
1259     log::error("Bluetooth module is not loaded");
1260     return;
1261   }
1262 
1263   if (sLeAudioBroadcasterInterface != nullptr) {
1264     sLeAudioBroadcasterInterface->Stop();
1265   }
1266 }
1267 
BroadcasterCleanupNative(JNIEnv * env,jobject)1268 static void BroadcasterCleanupNative(JNIEnv* env, jobject /* object */) {
1269   std::unique_lock<std::shared_timed_mutex> interface_lock(sBroadcasterInterfaceMutex);
1270   std::unique_lock<std::shared_timed_mutex> callbacks_lock(sBroadcasterCallbacksMutex);
1271 
1272   const bt_interface_t* btInf = getBluetoothInterface();
1273   if (btInf == nullptr) {
1274     log::error("Bluetooth module is not loaded");
1275     return;
1276   }
1277 
1278   env->DeleteGlobalRef(java_util_ArrayList.clazz);
1279   java_util_ArrayList.clazz = nullptr;
1280 
1281   env->DeleteGlobalRef(android_bluetooth_BluetoothDevice.clazz);
1282   android_bluetooth_BluetoothDevice.clazz = nullptr;
1283 
1284   env->DeleteGlobalRef(android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz);
1285   android_bluetooth_BluetoothLeAudioCodecConfigMetadata.clazz = nullptr;
1286 
1287   env->DeleteGlobalRef(android_bluetooth_BluetoothLeAudioContentMetadata.clazz);
1288   android_bluetooth_BluetoothLeAudioContentMetadata.clazz = nullptr;
1289 
1290   env->DeleteGlobalRef(android_bluetooth_BluetoothLeBroadcastSubgroup.clazz);
1291   android_bluetooth_BluetoothLeBroadcastSubgroup.clazz = nullptr;
1292 
1293   env->DeleteGlobalRef(android_bluetooth_BluetoothLeBroadcastChannel.clazz);
1294   android_bluetooth_BluetoothLeBroadcastChannel.clazz = nullptr;
1295 
1296   env->DeleteGlobalRef(android_bluetooth_BluetoothLeBroadcastMetadata.clazz);
1297   android_bluetooth_BluetoothLeBroadcastMetadata.clazz = nullptr;
1298 
1299   if (sLeAudioBroadcasterInterface != nullptr) {
1300     sLeAudioBroadcasterInterface->Cleanup();
1301     sLeAudioBroadcasterInterface = nullptr;
1302   }
1303 
1304   if (sBroadcasterCallbacksObj != nullptr) {
1305     env->DeleteGlobalRef(sBroadcasterCallbacksObj);
1306     sBroadcasterCallbacksObj = nullptr;
1307   }
1308 }
1309 
convertToDataVectors(JNIEnv * env,jobjectArray dataArray)1310 std::vector<std::vector<uint8_t>> convertToDataVectors(JNIEnv* env, jobjectArray dataArray) {
1311   jsize arraySize = env->GetArrayLength(dataArray);
1312   std::vector<std::vector<uint8_t>> res(arraySize);
1313 
1314   for (int i = 0; i < arraySize; ++i) {
1315     jbyteArray rowData = (jbyteArray)env->GetObjectArrayElement(dataArray, i);
1316     jsize dataSize = env->GetArrayLength(rowData);
1317     std::vector<uint8_t>& rowVector = res[i];
1318     rowVector.resize(dataSize);
1319     env->GetByteArrayRegion(rowData, 0, dataSize, reinterpret_cast<jbyte*>(rowVector.data()));
1320     env->DeleteLocalRef(rowData);
1321   }
1322   return res;
1323 }
1324 
CreateBroadcastNative(JNIEnv * env,jobject,jboolean isPublic,jstring broadcastName,jbyteArray broadcast_code,jbyteArray publicMetadata,jintArray qualityArray,jobjectArray metadataArray)1325 static void CreateBroadcastNative(JNIEnv* env, jobject /* object */, jboolean isPublic,
1326                                   jstring broadcastName, jbyteArray broadcast_code,
1327                                   jbyteArray publicMetadata, jintArray qualityArray,
1328                                   jobjectArray metadataArray) {
1329   log::info("");
1330   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1331   if (!sLeAudioBroadcasterInterface) {
1332     return;
1333   }
1334 
1335   std::array<uint8_t, 16> code_array{0};
1336   if (broadcast_code) {
1337     jsize size = env->GetArrayLength(broadcast_code);
1338     if (size > 16) {
1339       log::error("broadcast code to long");
1340       return;
1341     }
1342 
1343     // Padding with zeros on MSB positions if code is shorter than 16 octets
1344     env->GetByteArrayRegion(broadcast_code, 0, size, (jbyte*)code_array.data());
1345   }
1346 
1347   const char* broadcast_name = nullptr;
1348   if (broadcastName) {
1349     broadcast_name = env->GetStringUTFChars(broadcastName, nullptr);
1350   }
1351 
1352   jbyte* public_meta = nullptr;
1353   if (publicMetadata) {
1354     public_meta = env->GetByteArrayElements(publicMetadata, nullptr);
1355   }
1356 
1357   jint* quality_array = nullptr;
1358   if (qualityArray) {
1359     quality_array = env->GetIntArrayElements(qualityArray, nullptr);
1360   }
1361 
1362   sLeAudioBroadcasterInterface->CreateBroadcast(
1363           isPublic, broadcast_name ? broadcast_name : "",
1364           broadcast_code ? std::optional<std::array<uint8_t, 16>>(code_array) : std::nullopt,
1365           public_meta ? std::vector<uint8_t>(public_meta,
1366                                              public_meta + env->GetArrayLength(publicMetadata))
1367                       : std::vector<uint8_t>(),
1368           quality_array ? std::vector<uint8_t>(quality_array,
1369                                                quality_array + env->GetArrayLength(qualityArray))
1370                         : std::vector<uint8_t>(),
1371           convertToDataVectors(env, metadataArray));
1372 
1373   if (broadcast_name) {
1374     env->ReleaseStringUTFChars(broadcastName, broadcast_name);
1375   }
1376   if (public_meta) {
1377     env->ReleaseByteArrayElements(publicMetadata, public_meta, 0);
1378   }
1379   if (quality_array) {
1380     env->ReleaseIntArrayElements(qualityArray, quality_array, 0);
1381   }
1382 }
1383 
UpdateMetadataNative(JNIEnv * env,jobject,jint broadcast_id,jstring broadcastName,jbyteArray publicMetadata,jobjectArray metadataArray)1384 static void UpdateMetadataNative(JNIEnv* env, jobject /* object */, jint broadcast_id,
1385                                  jstring broadcastName, jbyteArray publicMetadata,
1386                                  jobjectArray metadataArray) {
1387   const char* broadcast_name = nullptr;
1388   if (broadcastName) {
1389     broadcast_name = env->GetStringUTFChars(broadcastName, nullptr);
1390   }
1391 
1392   jbyte* public_meta = nullptr;
1393   if (publicMetadata) {
1394     public_meta = env->GetByteArrayElements(publicMetadata, nullptr);
1395   }
1396 
1397   sLeAudioBroadcasterInterface->UpdateMetadata(
1398           broadcast_id, broadcast_name ? broadcast_name : "",
1399           public_meta ? std::vector<uint8_t>(public_meta,
1400                                              public_meta + env->GetArrayLength(publicMetadata))
1401                       : std::vector<uint8_t>(),
1402           convertToDataVectors(env, metadataArray));
1403 
1404   if (broadcast_name) {
1405     env->ReleaseStringUTFChars(broadcastName, broadcast_name);
1406   }
1407   if (public_meta) {
1408     env->ReleaseByteArrayElements(publicMetadata, public_meta, 0);
1409   }
1410 }
1411 
StartBroadcastNative(JNIEnv *,jobject,jint broadcast_id)1412 static void StartBroadcastNative(JNIEnv* /* env */, jobject /* object */, jint broadcast_id) {
1413   log::info("");
1414   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1415   if (!sLeAudioBroadcasterInterface) {
1416     return;
1417   }
1418   sLeAudioBroadcasterInterface->StartBroadcast(broadcast_id);
1419 }
1420 
StopBroadcastNative(JNIEnv *,jobject,jint broadcast_id)1421 static void StopBroadcastNative(JNIEnv* /* env */, jobject /* object */, jint broadcast_id) {
1422   log::info("");
1423   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1424   if (!sLeAudioBroadcasterInterface) {
1425     return;
1426   }
1427   sLeAudioBroadcasterInterface->StopBroadcast(broadcast_id);
1428 }
1429 
PauseBroadcastNative(JNIEnv *,jobject,jint broadcast_id)1430 static void PauseBroadcastNative(JNIEnv* /* env */, jobject /* object */, jint broadcast_id) {
1431   log::info("");
1432   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1433   if (!sLeAudioBroadcasterInterface) {
1434     return;
1435   }
1436   sLeAudioBroadcasterInterface->PauseBroadcast(broadcast_id);
1437 }
1438 
DestroyBroadcastNative(JNIEnv *,jobject,jint broadcast_id)1439 static void DestroyBroadcastNative(JNIEnv* /* env */, jobject /* object */, jint broadcast_id) {
1440   log::info("");
1441   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1442   if (!sLeAudioBroadcasterInterface) {
1443     return;
1444   }
1445   sLeAudioBroadcasterInterface->DestroyBroadcast(broadcast_id);
1446 }
1447 
getBroadcastMetadataNative(JNIEnv *,jobject,jint broadcast_id)1448 static void getBroadcastMetadataNative(JNIEnv* /* env */, jobject /* object */, jint broadcast_id) {
1449   log::info("");
1450   std::shared_lock<std::shared_timed_mutex> lock(sBroadcasterInterfaceMutex);
1451   if (!sLeAudioBroadcasterInterface) {
1452     return;
1453   }
1454   sLeAudioBroadcasterInterface->GetBroadcastMetadata(broadcast_id);
1455 }
1456 
register_com_android_bluetooth_le_audio_broadcaster(JNIEnv * env)1457 static int register_com_android_bluetooth_le_audio_broadcaster(JNIEnv* env) {
1458   const JNINativeMethod methods[] = {
1459           {"initNative", "()V", (void*)BroadcasterInitNative},
1460           {"stopNative", "()V", (void*)BroadcasterStopNative},
1461           {"cleanupNative", "()V", (void*)BroadcasterCleanupNative},
1462           {"createBroadcastNative", "(ZLjava/lang/String;[B[B[I[[B)V",
1463            (void*)CreateBroadcastNative},
1464           {"updateMetadataNative", "(ILjava/lang/String;[B[[B)V", (void*)UpdateMetadataNative},
1465           {"startBroadcastNative", "(I)V", (void*)StartBroadcastNative},
1466           {"stopBroadcastNative", "(I)V", (void*)StopBroadcastNative},
1467           {"pauseBroadcastNative", "(I)V", (void*)PauseBroadcastNative},
1468           {"destroyBroadcastNative", "(I)V", (void*)DestroyBroadcastNative},
1469           {"getBroadcastMetadataNative", "(I)V", (void*)getBroadcastMetadataNative},
1470   };
1471 
1472   const int result = REGISTER_NATIVE_METHODS(
1473           env, "com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterface", methods);
1474   if (result != 0) {
1475     return result;
1476   }
1477 
1478   const JNIJavaMethod javaMethods[] = {
1479           {"onBroadcastCreated", "(IZ)V", &method_onBroadcastCreated},
1480           {"onBroadcastDestroyed", "(I)V", &method_onBroadcastDestroyed},
1481           {"onBroadcastStateChanged", "(II)V", &method_onBroadcastStateChanged},
1482           {"onBroadcastMetadataChanged", "(ILandroid/bluetooth/BluetoothLeBroadcastMetadata;)V",
1483            &method_onBroadcastMetadataChanged},
1484           {"onBroadcastAudioSessionCreated", "(Z)V", &method_onBroadcastAudioSessionCreated},
1485   };
1486   GET_JAVA_METHODS(env, "com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterface",
1487                    javaMethods);
1488 
1489   const JNIJavaMethod javaArrayListMethods[] = {
1490           {"<init>", "()V", &java_util_ArrayList.constructor},
1491           {"add", "(Ljava/lang/Object;)Z", &java_util_ArrayList.add},
1492   };
1493   GET_JAVA_METHODS(env, "java/util/ArrayList", javaArrayListMethods);
1494 
1495   const JNIJavaMethod javaLeAudioCodecMethods[] = {
1496           {"<init>", "(JIII[B)V",
1497            &android_bluetooth_BluetoothLeAudioCodecConfigMetadata.constructor},
1498   };
1499   GET_JAVA_METHODS(env, "android/bluetooth/BluetoothLeAudioCodecConfigMetadata",
1500                    javaLeAudioCodecMethods);
1501 
1502   const JNIJavaMethod javaLeAudioContentMethods[] = {
1503           {"<init>", "(Ljava/lang/String;Ljava/lang/String;[B)V",
1504            &android_bluetooth_BluetoothLeAudioContentMetadata.constructor},
1505   };
1506   GET_JAVA_METHODS(env, "android/bluetooth/BluetoothLeAudioContentMetadata",
1507                    javaLeAudioContentMethods);
1508 
1509   const JNIJavaMethod javaLeBroadcastChannelMethods[] = {
1510           {"<init>", "(ZILandroid/bluetooth/BluetoothLeAudioCodecConfigMetadata;)V",
1511            &android_bluetooth_BluetoothLeBroadcastChannel.constructor},
1512   };
1513   GET_JAVA_METHODS(env, "android/bluetooth/BluetoothLeBroadcastChannel",
1514                    javaLeBroadcastChannelMethods);
1515 
1516   const JNIJavaMethod javaLeBroadcastSubgroupMethods[] = {
1517           {"<init>",
1518            "(JLandroid/bluetooth/BluetoothLeAudioCodecConfigMetadata;"
1519            "Landroid/bluetooth/BluetoothLeAudioContentMetadata;"
1520            "Ljava/util/List;)V",
1521            &android_bluetooth_BluetoothLeBroadcastSubgroup.constructor},
1522   };
1523   GET_JAVA_METHODS(env, "android/bluetooth/BluetoothLeBroadcastSubgroup",
1524                    javaLeBroadcastSubgroupMethods);
1525 
1526   const JNIJavaMethod javaBluetoothDevieceMethods[] = {
1527           {"<init>", "(Ljava/lang/String;I)V", &android_bluetooth_BluetoothDevice.constructor},
1528   };
1529   GET_JAVA_METHODS(env, "android/bluetooth/BluetoothDevice", javaBluetoothDevieceMethods);
1530 
1531   const JNIJavaMethod javaLeBroadcastMetadataMethods[] = {
1532           {"<init>",
1533            "(ILandroid/bluetooth/BluetoothDevice;IIIZZLjava/lang/String;"
1534            "[BIIILandroid/bluetooth/BluetoothLeAudioContentMetadata;"
1535            "Ljava/util/List;)V",
1536            &android_bluetooth_BluetoothLeBroadcastMetadata.constructor},
1537   };
1538   GET_JAVA_METHODS(env, "android/bluetooth/BluetoothLeBroadcastMetadata",
1539                    javaLeBroadcastMetadataMethods);
1540 
1541   return 0;
1542 }
1543 
register_com_android_bluetooth_le_audio(JNIEnv * env)1544 int register_com_android_bluetooth_le_audio(JNIEnv* env) {
1545   const JNINativeMethod methods[] = {
1546           {"initNative", "([Landroid/bluetooth/BluetoothLeAudioCodecConfig;)V", (void*)initNative},
1547           {"cleanupNative", "()V", (void*)cleanupNative},
1548           {"connectLeAudioNative", "([B)Z", (void*)connectLeAudioNative},
1549           {"disconnectLeAudioNative", "([B)Z", (void*)disconnectLeAudioNative},
1550           {"setEnableStateNative", "([BZ)Z", (void*)setEnableStateNative},
1551           {"groupAddNodeNative", "(I[B)Z", (void*)groupAddNodeNative},
1552           {"groupRemoveNodeNative", "(I[B)Z", (void*)groupRemoveNodeNative},
1553           {"groupSetActiveNative", "(I)V", (void*)groupSetActiveNative},
1554           {"setCodecConfigPreferenceNative",
1555            "(ILandroid/bluetooth/BluetoothLeAudioCodecConfig;"
1556            "Landroid/bluetooth/BluetoothLeAudioCodecConfig;)V",
1557            (void*)setCodecConfigPreferenceNative},
1558           {"setCcidInformationNative", "(II)V", (void*)setCcidInformationNative},
1559           {"setInCallNative", "(Z)V", (void*)setInCallNative},
1560           {"setUnicastMonitorModeNative", "(IZ)V", (void*)setUnicastMonitorModeNative},
1561           {"sendAudioProfilePreferencesNative", "(IZZ)V", (void*)sendAudioProfilePreferencesNative},
1562           {"setGroupAllowedContextMaskNative", "(III)V", (void*)setGroupAllowedContextMaskNative},
1563   };
1564 
1565   const int result = REGISTER_NATIVE_METHODS(
1566           env, "com/android/bluetooth/le_audio/LeAudioNativeInterface", methods);
1567   if (result != 0) {
1568     return result;
1569   }
1570 
1571   const JNIJavaMethod javaMethods[] = {
1572           {"onGroupStatus", "(II)V", &method_onGroupStatus},
1573           {"onGroupNodeStatus", "([BII)V", &method_onGroupNodeStatus},
1574           {"onAudioConf", "(IIIII)V", &method_onAudioConf},
1575           {"onSinkAudioLocationAvailable", "([BI)V", &method_onSinkAudioLocationAvailable},
1576           {"onInitialized", "()V", &method_onInitialized},
1577           {"onConnectionStateChanged", "(I[B)V", &method_onConnectionStateChanged},
1578           {"onAudioLocalCodecCapabilities",
1579            "([Landroid/bluetooth/BluetoothLeAudioCodecConfig;"
1580            "[Landroid/bluetooth/BluetoothLeAudioCodecConfig;)V",
1581            &method_onAudioLocalCodecCapabilities},
1582           {"onAudioGroupCurrentCodecConf",
1583            "(ILandroid/bluetooth/BluetoothLeAudioCodecConfig;"
1584            "Landroid/bluetooth/BluetoothLeAudioCodecConfig;)V",
1585            &method_onAudioGroupCurrentCodecConf},
1586           {"onAudioGroupSelectableCodecConf",
1587            "(I[Landroid/bluetooth/BluetoothLeAudioCodecConfig;"
1588            "[Landroid/bluetooth/BluetoothLeAudioCodecConfig;)V",
1589            &method_onAudioGroupSelectableCodecConf},
1590           {"onHealthBasedRecommendationAction", "([BI)V",
1591            &method_onHealthBasedRecommendationAction},
1592           {"onHealthBasedGroupRecommendationAction", "(II)V",
1593            &method_onHealthBasedGroupRecommendationAction},
1594           {"onUnicastMonitorModeStatus", "(II)V", &method_onUnicastMonitorModeStatus},
1595           {"onGroupStreamStatus", "(II)V", &method_onGroupStreamStatus},
1596   };
1597   GET_JAVA_METHODS(env, "com/android/bluetooth/le_audio/LeAudioNativeInterface", javaMethods);
1598 
1599   const JNIJavaMethod javaLeAudioCodecMethods[] = {
1600           {"<init>", "(IIIIIIIII)V", &android_bluetooth_BluetoothLeAudioCodecConfig.constructor},
1601           {"getCodecType", "()I", &android_bluetooth_BluetoothLeAudioCodecConfig.getCodecType},
1602           {"getSampleRate", "()I", &android_bluetooth_BluetoothLeAudioCodecConfig.getSampleRate},
1603           {"getBitsPerSample", "()I",
1604            &android_bluetooth_BluetoothLeAudioCodecConfig.getBitsPerSample},
1605           {"getChannelCount", "()I",
1606            &android_bluetooth_BluetoothLeAudioCodecConfig.getChannelCount},
1607           {"getFrameDuration", "()I",
1608            &android_bluetooth_BluetoothLeAudioCodecConfig.getFrameDuration},
1609           {"getOctetsPerFrame", "()I",
1610            &android_bluetooth_BluetoothLeAudioCodecConfig.getOctetsPerFrame},
1611           {"getCodecPriority", "()I",
1612            &android_bluetooth_BluetoothLeAudioCodecConfig.getCodecPriority},
1613   };
1614   GET_JAVA_METHODS(env, "android/bluetooth/BluetoothLeAudioCodecConfig", javaLeAudioCodecMethods);
1615 
1616   return register_com_android_bluetooth_le_audio_broadcaster(env);
1617 }
1618 }  // namespace android
1619